📄 classinfo.java
字号:
/* * ClassInfo.java 1.22 99/12/08 SMI * * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * Use is subject to license terms. */package components;import jcc.Util;import vm.Const;import util.*;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.io.PrintStream;import java.util.Hashtable;import java.util.Enumeration;import java.util.Vector;//// container for stuff about a class.// can be in a classfile or in a module.//publicclass ClassInfo{ public String className; public int access; public ClassConstant thisClass; public ClassConstant superClass; public ClassInfo superClassInfo; // Tables for all fields, methods and constants of this class public FieldInfo fields[]; public MethodInfo methods[]; public ConstantObject constants[]; private ConstantObject oldConstants[]; public ConstantObject symbols[]; public ClassConstant interfaces[]; public FieldConstant refFieldtable[]; public MethodConstant refMethodtable[]; // In case we lay it all out here public FieldInfo fieldtable[]; public MethodInfo methodtable[]; public UnicodeConstant fieldtableName; public UnicodeConstant methodtableName; // Class attributes that we do not interpret public Attribute[] classAttributes; public SourceFileAttribute sourceFileAttr; public vm.ClassClass vmClass; // used by in-core output writers public Vector allInterfaces; protected boolean verbose; protected PrintStream log = System.out; public ConstantPool externalPool; public static boolean classDebug = false; public int flags; public static final int INCLUDE_ALL = 1; public ClassInfo( boolean v ) { verbose = v; flags = INCLUDE_ALL; // by default, we want all members. // what else should be here? } private String genericNativeName; public final String getGenericNativeName() { if (genericNativeName == null) genericNativeName = createGenericNativeName(); return genericNativeName; } // This will be overridden by subclasses protected String createGenericNativeName() { return Util.convertToClassName(className ); } // Read in the constants from a classfile void readConstantPool( DataInput in ) throws IOException { int num = in.readUnsignedShort(); if(verbose){ log.println(Localizer.getString("classinfo.reading_entries_in_constant_pool", Integer.toString(num))); } constants = new ConstantObject[num]; for (int i = 1; i < num; i+=constants[i].nSlots) { constants[i] = ConstantObject.readObject( in ); constants[i].index = i; } } private void resolveConstants( ) { if (verbose){ log.println(Localizer.getString("classinfo.>>>resolving_constants")); } for (int i = 1; i < constants.length; i+=constants[i].nSlots) { constants[i].resolve( symbols ); } } protected void externalizeConstants( ConstantPool externalPool ){ if (verbose){ log.println(Localizer.getString("classinfo.>>>externalizing_constants")); } // externalize immediately certain kinds of constants // we know to have no direct references. for (int i = 1; i < constants.length; i+=constants[i].nSlots) { switch ( constants[i].tag ){ case Const.CONSTANT_UTF8: case Const.CONSTANT_NAMEANDTYPE: // unquestionably, share these. constants[i] = externalPool.add( constants[i] ); // FALLTHROUGH default: constants[i].externalize( externalPool ); break; } } } /* * If we are using an external string table, then * we can make our own table smaller. At this point, * all non-code references into it are by object reference, NEVER * by index -- everything has been resolved! Thus we can * compact our table, deleting all the UnicodeConstants. * We adjust each constant's index entry accordingly. * Naturally, we preserve the null entries. * */ public void smashConstantPool(){ int nOld = constants.length; int nNew = 1; ConstantObject o; // first, count and index. for ( int i = 1; i < nOld; i += o.nSlots ){ o = constants[i]; if ( ! o.shared ){ if ( o.references == 0 ){ o.index = -1; // trouble. } else { // we're keeping it. o.index = nNew; nNew += o.nSlots; } } } // now reallocate and copy. ConstantObject newConstants[] = new ConstantObject[ nNew ]; int j = 1; for ( int i = 1; i < nOld; i += o.nSlots ){ o = constants[i]; if ( (! o.shared ) && ( o.references != 0 ) ){ // we're keeping it. newConstants[j] = o; j += o.nSlots; } } oldConstants = constants; constants = newConstants; } // write constants back out, just like we read them in. void writeConstantPool( DataOutput out ) throws IOException { int num = constants==null ? 0 : constants.length; if(verbose){ log.println(Localizer.getString("classinfo.writing_constant_pool_entries", Integer.toString(num))); } out.writeShort( num ); for (int i = 1; i < num; i+=constants[i].nSlots) { constants[i].write( out ); } } // Read the list of interfaces this class supports void readInterfaces( DataInput in ) throws IOException { int count = in.readUnsignedShort(); if(verbose){ log.println(Localizer.getString("classinfo.reading_interfaces_implemented", Integer.toString(count))); } interfaces = new ClassConstant[count]; for (int i = 0; i < count; i++) { //interfaces[i] = (ClassConstant) symbols[in.readUnsignedShort()]; // interfaces not external -- they use own constant pool! interfaces[i] = (ClassConstant) constants[in.readUnsignedShort()]; } } void externalizeInterfaces( ConstantPool p ){ int count = interfaces==null ? 0 : interfaces.length; if(verbose){ log.println(Localizer.getString("classinfo.>>>externalizing_interfaces_implemented")); } for (int i = 0; i < count; i++) { interfaces[i] = (ClassConstant)p.dup( interfaces[i] ); } } void writeInterfaces( DataOutput out ) throws IOException { int count = interfaces==null ? 0 : interfaces.length; if(verbose){ log.println(Localizer.getString("classinfo.writing_interfaces_implemented", Integer.toString(count))); } out.writeShort( count ); for (int i = 0; i < count; i++) { out.writeShort( interfaces[i].index ); } } // Read the list of fields void readFields( DataInput in ) throws IOException { int count = in.readUnsignedShort(); fields = new FieldInfo[count]; if(verbose){ log.println(Localizer.getString("classinfo.reading_field_members", Integer.toString(count))); } for (int i = 0; i < count; i++) { fields[i] = FieldInfo.readField(in, this); fields[i].index = i; } } void externalizeFields( ConstantPool p ){ int count = fields==null ? 0 : fields.length; if(verbose){ log.println(Localizer.getString("classinfo.>>>externalizing_field_members")); } for (int i = 0; i < count; i++) { fields[i].externalize( p ); } } void writeFields( DataOutput out ) throws IOException { int count = fields==null ? 0 : fields.length; if(verbose){ log.println(Localizer.getString("classinfo.writing_field_members", Integer.toString(count))); } out.writeShort( count ); for (int i = 0; i < count; i++) { fields[i].write( out ); } } // Read the list of methods from classfile void readMethods( DataInput in, boolean readCode ) throws IOException { int count = in.readUnsignedShort(); methods = new MethodInfo[count]; if(verbose){ log.println(Localizer.getString( "classinfo.reading_methods", Integer.toString(count))); } for (int i = 0; i < count; i++) { methods[i] = MethodInfo.readMethod( in, this, readCode ); methods[i].index = i; } } void externalizeMethods( ConstantPool p ){ int count = methods==null ? 0 : methods.length; if(verbose){ log.println(Localizer.getString("classinfo.>>>externalizing_methods")); } for (int i = 0; i < count; i++) { methods[i].externalize( p ); } } void writeMethods( DataOutput out) throws IOException { int count = methods==null ? 0 : methods.length; if(verbose){ log.println(Localizer.getString("classinfo.writing_methods", Integer.toString(count))); } out.writeShort(count); for (int i = 0; i < count; i++) { methods[i].write( out ); } } void readAttributes( DataInput in ) throws IOException { int count = in.readUnsignedShort(); Vector clssAttr = new Vector(); if(verbose){ log.println(Localizer.getString("classinfo.reading_attributes", Integer.toString(count))); } for (int i = 0; i < count; i++) { int nameIndex = in.readUnsignedShort(); int bytes = in.readInt(); UnicodeConstant name = (UnicodeConstant)symbols[nameIndex]; if (name.string.equals(/*NOI18N*/"fieldtable")){ fieldtableName = name; if (verbose){ log.println(Localizer.getString("classinfo.reading_name",name)); } int n = bytes / 2; refFieldtable = new FieldConstant[ n ]; for( int j = 0; j < n; j++ ){ refFieldtable[j] = (FieldConstant)symbols[ in.readUnsignedShort() ]; } } else if (name.string.equals(/*NOI18N*/"methodtable")){ methodtableName = name; if (verbose){ log.println(Localizer.getString("classinfo.reading_name", name)); } int n = bytes / 2; refMethodtable = new MethodConstant[ n ]; for( int j = 0; j < n; j++ ){ refMethodtable[j] = (MethodConstant)symbols[ in.readUnsignedShort() ]; } } else if (name.string.equals(/*NOI18N*/"SourceFile")) { if (ClassInfo.classDebug) { UnicodeConstant srcName = (UnicodeConstant)symbols[in.readUnsignedShort()]; sourceFileAttr = new SourceFileAttribute(name, bytes, srcName); clssAttr.addElement(sourceFileAttr); } else { byte[] b = new byte[bytes]; in.readFully(b); clssAttr.addElement (new UninterpretedAttribute(name, bytes, b)); } } else { byte[] b = new byte[bytes]; in.readFully(b); clssAttr.addElement (new UninterpretedAttribute(name, bytes, b)); } } int nattr = clssAttr.size(); if (nattr > 0) { this.classAttributes = new Attribute[nattr]; clssAttr.copyInto(classAttributes); } } void externalizeAttributes( ConstantPool p ){ Attribute.externalizeAttributes(classAttributes, p); } public void allocateFieldsFromFieldtable(){ if ( refFieldtable == null ) return; // no can do. int n = refFieldtable.length; int nsuper; int fieldoff = 0; nsuper = ( superClassInfo == null ) ? 0 : superClassInfo.refFieldtable.length; if ( nsuper == 0 ){ fieldoff = 0; } else { FieldInfo f = refFieldtable[ nsuper-1 ].find(); if ( f.instanceOffset < 0 ){ superClassInfo.allocateFieldsFromFieldtable(); } fieldoff = f.instanceOffset + f.nSlots; } for ( int i = nsuper ; i < n; i++ ){ FieldInfo f = refFieldtable[ i ].find(); if ( f == null ){ // this is not supposed to happen. System.out.println( Localizer.getString("classinfo.cannot_find_field", refFieldtable[i])); continue; } f.instanceOffset = fieldoff; fieldoff += f.nSlots; } // // and while we're here, do methodtable as well. // n = refMethodtable.length; int methodoff = 0; // 1=>0 EJVM for ( int i = 0; i < n ; i++ ){ MethodInfo m = refMethodtable[ i ].find(); if ( m == null ){ // this is not supposed to happen. System.out.println( Localizer.getString("classinfo.cannot_find_field", refMethodtable[i])); continue; } else if ( m.methodTableIndex != methodoff ){ if ( m.parent != this ){ // this method is in a superclass. // which apparently hasn't set up its methodtable yet. // so go do it. superClassInfo.allocateFieldsFromFieldtable(); } else { // we do it here.? System.out.println("Inconsistent refMethodtable in class "+this.toString()); m.methodTableIndex = methodoff; } } methodoff += 1; } } void writeTableAttribute( DataOutput out, UnicodeConstant name, FMIrefConstant table[] ) throws IOException { if (verbose){ log.println(Localizer.getString("classinfo.writing_name", name.string)); } out.writeShort( name.index ); int n = table.length; out.writeInt( 2*n ); for ( int i = 0; i < n; i++ ){ out.writeShort( table[i].index ); } } void writeAttributes( DataOutput out ) throws IOException { int count = 0; if ( fieldtableName != null ) count++; if ( methodtableName != null ) count++; if (classAttributes != null) { count += classAttributes.length; } out.writeShort(count); if ( fieldtableName != null ){ writeTableAttribute( out, fieldtableName, refFieldtable ); } if ( methodtableName != null ){ writeTableAttribute( out, methodtableName, refMethodtable ); } if (classAttributes != null) { for (int k = 0; k < classAttributes.length; k++) { classAttributes[k].write( out ); } } } // Read in the entire class // assume file is open, magic numbers are o.k. // read assumes reading from class file // see also readMultiClass // private void doRead( DataInput in, boolean readCode, ConstantPool externalSymbols ) throws IOException { externalPool = externalSymbols; // for convenience, later
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -