📄 classinfo.java
字号:
resolveConstants( ); access = in.readUnsignedShort(); thisClass = (ClassConstant) symbols[in.readUnsignedShort()]; int sup = in.readUnsignedShort(); if ( sup != 0 ) superClass = (ClassConstant) symbols[sup]; className = thisClass.name.string; // Read the various parts of the class file readInterfaces( in ); readFields( in ); readMethods( in, readCode ); readAttributes( in ); enterClass( className ); } public void read( DataInput in, boolean readCode, ConstantPool externalSymbols ) throws IOException { readConstantPool( in ); symbols = constants; // symbol table == constant pool doRead( in, readCode, externalSymbols ); } // // read a whole class from a module file. // the only difference is in the treatment of the external // symbol table. In this case, it is not built, but USED. public void readMultiClass( DataInput in, boolean readCode, ConstantPool externalSymbols ) throws IOException { readConstantPool( in ); symbols = externalSymbols.getConstants(); //symbol table is external. doRead( in, readCode, externalSymbols ); } public void externalize( ConstantPool p ){ if (verbose){ log.println(Localizer.getString("classinfo.externalizing_class", className)); } externalizeConstants( p ); thisClass = (ClassConstant)p.dup( thisClass ); //thisClass.externalize(p);//redundant? if ( superClass != null ){ superClass = (ClassConstant)p.dup( superClass ); //superClass.externalize(p);//redundant? } //externalizeInterfaces( p ); // interfaces NOT externalized! externalizeMethods( p ); externalizeFields( p ); externalizeAttributes( p ); } // Compute the fieldtable for a class. This requires laying // out the fieldtable for our parent, then adding any fields // that are not inherited. public void buildFieldtable( ConstantPool cp ){ if (this.fieldtable != null) return; // already done. FieldInfo fieldtable[]; int n; int fieldoff; int fieldtableLength = 0; FieldInfo candidate[] = this.fields; for( int i =0; i < candidate.length; i++ ){ if ((candidate[i].access & Const.ACC_STATIC) == 0){ fieldtableLength++; } } if ( superClassInfo != null ){ superClassInfo.buildFieldtable( cp ); n = superClassInfo.fieldtable.length; fieldtableLength += n; fieldoff = (n==0)? 0 : (superClassInfo.fieldtable[n-1].instanceOffset + superClassInfo.fieldtable[n-1].nSlots); fieldtable = new FieldInfo[ fieldtableLength ]; System.arraycopy( superClassInfo.fieldtable, 0, fieldtable, 0, n ); } else { fieldtable = new FieldInfo[ fieldtableLength ]; n = 0; fieldoff = 0; } for( int i =0; i < candidate.length; i++ ){ if ((candidate[i].access & Const.ACC_STATIC) == 0){ fieldtable[n++] = candidate[i]; candidate[i].instanceOffset = fieldoff; fieldoff += candidate[i].nSlots; } } this.fieldtable = fieldtable; // // here, we make the gross assumption that // if we're building a fieldtable, we're using a shared // external Constant Pool fieldtableName = (UnicodeConstant)cp.add( new UnicodeConstant(/*NOI18N*/"fieldtable") ); } private FMIrefConstant buildReference( ClassMemberInfo m, boolean isMethod, ConstantPool cp ){ ClassConstant c = (ClassConstant) cp.dup( m.parent.thisClass ); FMIrefConstant x; NameAndTypeConstant n = (NameAndTypeConstant) cp.add( new NameAndTypeConstant( (UnicodeConstant)cp.add( m.name), (UnicodeConstant)cp.add( m.type ) ) ); if (isMethod){ x = new MethodConstant( c, n ); }else{ x = new FieldConstant( c, n ); } return (FMIrefConstant)cp.add( x ); } public void buildReferenceFieldtable( ConstantPool cp ){ if ( refFieldtable != null ) return; // already done, it says here. if ( fieldtableName == null ){ fieldtableName = (UnicodeConstant)cp.add( new UnicodeConstant(/*NOI18N*/"fieldtable") ); } buildFieldtable( cp ); int n = fieldtable.length; refFieldtable = new FieldConstant[ n ]; for ( int i = 0; i < n; i++ ){ refFieldtable[i] = (FieldConstant)buildReference( fieldtable[i], false, cp ); } } // Compute the method table for a class. This requires laying // out the method table for our parent, then adding any methods // that are not inherited. public void buildMethodtable( ConstantPool cp ) { if ( this.methodtable != null ) return; // already done. MethodInfo table[]; MethodInfo methods[] = this.methods; ClassInfo sup = superClassInfo; if ((sup != null) && ( (sup.access&Const.ACC_INTERFACE)==(this.access&Const.ACC_INTERFACE) ) ) { sup.buildMethodtable( cp ); table = sup.methodtable; } else { table = new MethodInfo[0]; } // allocate a temporary table that is certainly large enough. MethodInfo newTable[] = new MethodInfo[table.length + methods.length]; int index = table.length; System.arraycopy( table, 0, newTable, 0, index ); if (sup == null) { // finalize() goes into slot 0 of java.lang.Object // FY: Removed for KVM. We have no finalize() in slot 0. // index++; } method_loop: for (int i = 0; i < methods.length; i++) { if ((methods[i].access & (Const.ACC_STATIC|Const.ACC_PRIVATE)) != 0) { continue method_loop; } else if (methods[i].name.string.equals(/*NOI18N*/"<init>")) { continue method_loop; } else if (sup == null && methods[i].name.string.equals(/*NOI18N*/"finalize") && methods[i].type.string.equals(/*NOI18N*/"()V")) { newTable[0] = methods[i]; newTable[0].methodTableIndex = 0; // 1=>0 EJVM continue method_loop; } int j; int thisID = methods[i].getID(); for ( j = 0; j < table.length; j++) { if (thisID == table[j].getID()) { newTable[j] = methods[i]; newTable[j].methodTableIndex = j + 0; // 1=>0 EJVM continue method_loop; } } // If we're not overriding our parent's method we do add // a new entry to the method table. newTable[index] = methods[i]; newTable[index].methodTableIndex = index + 0; // 1=>0 EJVM index++; } // now allocate a table of the correct size. MethodInfo methodTable[] = new MethodInfo[index]; System.arraycopy( newTable, 0, methodTable, 0, index ); this.methodtable = methodTable; // // here, we make the gross assumption that // if we're building a methodtable, we're using a shared // external Constant Pool methodtableName = (UnicodeConstant)cp.add( new UnicodeConstant(/*NOI18N*/"methodtable") ); } public void buildReferenceMethodtable( ConstantPool cp ){ if ( refMethodtable != null ) return; // already done, it says here. if ( methodtableName == null ){ methodtableName = (UnicodeConstant)cp.add( new UnicodeConstant(/*NOI18N*/"methodtable") ); } buildMethodtable( cp ); int n = methodtable.length; refMethodtable = new MethodConstant[ n ]; for ( int i = 0; i < n; i++ ){ refMethodtable[i] = (MethodConstant)buildReference( methodtable[i], true, cp ); } } private static boolean conditionalAdd( Vector v, Object o ){ if ( v.contains( o ) ) return false; v.addElement( o ); return true; } /* * Compute the vector of all interfaces this class implements (or * this interface extends). Not only the interfaced declared in * the implements clause, which is what the interfaces[] field * represents, but all interfaces, including those of our superclasses * and those extended/implemented by any interfaces we implement. * */ public void findAllInterfaces(){ /* * This works recursively, by computing parent's interface * set first. THIS ASSUMES NON-CIRCULARITY, as does the rest * of the Java system. This assumption will fail loudly, if * at all. */ if ( superClassInfo == null ){ // we must be java.lang.Object! allInterfaces = new Vector(5); // a generous size. } else { if ( superClassInfo.allInterfaces == null ) superClassInfo.findAllInterfaces(); allInterfaces = (Vector)(superClassInfo.allInterfaces.clone()); } if ( interfaces == null ) return; // all done! for( int i = 0; i < interfaces.length; i++ ){ ClassInfo interf = interfaces[i].find(); if ( ( interf == null ) || ( (interf.access&Const.ACC_INTERFACE) == 0 ) ){ System.err.println(Localizer.getString("classinfo.class_which_should_be_an_interface_but_is_not", className, interfaces[i])); continue; } if ( interf.allInterfaces == null ) interf.findAllInterfaces(); if ( ! conditionalAdd( allInterfaces, interf ) ){ // if this interface was already in the set, // then all the interfaces that it extend/implement // will be, too. continue; } Enumeration interfInterf = interf.allInterfaces.elements(); while( interfInterf.hasMoreElements() ){ conditionalAdd( allInterfaces, interfInterf.nextElement() ); } } } public boolean findReferences(){ try { for ( int i = 0; i < methods.length; i++ ){ methods[i].findConstantReferences(); } } catch ( DataFormatException e ){ return false; } return true; } public boolean countReferences( boolean isRelocatable ){ thisClass.incReference(); if ( superClass != null ) superClass.incReference(); // count interface references if ( interfaces!=null ){ for ( int i = 0; i < interfaces.length ; i++ ){ interfaces[i].incReference(); } } // then count references from fields. if ( fields != null ){ for ( int i = 0; i < fields.length; i++ ){ fields[i].countConstantReferences( isRelocatable ); } } // then count references from code if ( methods != null ){ for ( int i = 0; i < methods.length; i++ ){ methods[i].countConstantReferences( constants, isRelocatable ); } } Attribute.countConstantReferences(classAttributes, isRelocatable); return true; } public boolean relocateReferences(){ try { for ( int i = 0; i < methods.length; i++ ){ methods[i].relocateConstantReferences( oldConstants ); } } catch ( DataFormatException e ){ return false; } return true; } public void clearMemberFlags( int flagsToClear ){ int mask = ~ flagsToClear; int n; ClassMemberInfo members[]; if ( fields != null ){ members = fields; n = members.length; for ( int i = 0; i < n; i++ ){ members[i].flags &= mask; } } if ( fields != null ){ members = methods; n = members.length; for ( int i = 0; i < n; i++ ){ members[i].flags &= mask; } } } public void write( DataOutput o ) throws IOException { writeConstantPool( o ); o.writeShort( access ); o.writeShort( thisClass.index ); o.writeShort( superClass==null? 0 : superClass.index ); writeInterfaces( o ); writeFields( o ); writeMethods( o ); writeAttributes( o ); } private static void dumpComponentTable( PrintStream o, String title, ClassComponent t[] ){ int n; if ( (t == null) || ((n=t.length) == 0) ) return; o.print( title ); o.println(/*NOI18N*/"["+n+"]:"); for( int i = 0; i < n; i++ ){ if ( t[i] != null ) o.println(/*NOI18N*/"\t["+i+/*NOI18N*/"]\t"+t[i]); } } private static void dumpConstantTable( PrintStream o, String title, ConstantObject t[] ){ int n; if ( (t == null) || ((n=t.length) == 0) ) return; o.print( title ); o.println(/*NOI18N*/"["+n+/*NOI18N*/"]:"); o.println(/*NOI18N*/"\tPosition Index\tNrefs"); for( int i = 0; i < n; i++ ){ if ( t[i] != null ) o.println(/*NOI18N*/"\t["+i+/*NOI18N*/"]\t"+t[i].index+/*NOI18N*/"\t"+t[i].references+/*NOI18N*/"\t"+t[i]); } } private static void dumpMemberTable( PrintStream o, String title, ClassMemberInfo t[] ){ int n; if ( (t == null) || ((n=t.length) == 0) ) return; o.print( title ); o.println(/*NOI18N*/":"); for( int i = 0; i < n; i++ ){ if ( t[i] != null ) o.println(/*NOI18N*/"\t["+i+/*NOI18N*/"]\t"+t[i].qualifiedName() ); } } public void dump( PrintStream o ){ o.print(Util.accessToString(access)+/*NOI18N*/"Class "+thisClass); if ( superClass != null ) o.print(/*NOI18N*/" extends "+superClass); if ( interfaces!=null && interfaces.length != 0 ){ o.print(/*NOI18N*/" implements"); for( int i = 0; i < interfaces.length ; i++ ){ o.print(" "+interfaces[i]); } } o.println(); dumpComponentTable( o, /*NOI18N*/"Methods", methods ); dumpComponentTable( o, /*NOI18N*/"Fields", fields ); if ( fieldtable != null ) dumpMemberTable( o, /*NOI18N*/"Fieldtable", fieldtable ); else dumpComponentTable( o, /*NOI18N*/"Fieldtable-by-reference", refFieldtable ); if ( methodtable != null ) dumpMemberTable( o, /*NOI18N*/"Methodtable", methodtable ); else dumpComponentTable( o, /*NOI18N*/"Methodtable-by-reference", refMethodtable ); dumpConstantTable( o, /*NOI18N*/"Constants", constants ); } /** * We keep track of classes by hashing them by name when * we read them. They can be looked up using lookupClass, * which will take a classname string as parameter. */ public static Hashtable classtable = new Hashtable(); protected void enterClass( String key ){ // should check to see if a class of this name is already there... if ( classtable.containsKey( className ) ){ System.err.println(Localizer.getString("classinfo.class_table_already_contains", className)); return; } classtable.put( key, this ); // if a classvector has been created, we need to add this. // at end should be sufficient. vm.ClassClass.appendClassElement( this ); } public static ClassInfo lookupClass( String key ){ return (ClassInfo)classtable.get( key ); } public static int nClasses(){ return classtable.size(); } public static Enumeration allClasses(){ return classtable.elements(); } public static boolean resolveSupers(){ Enumeration allclasses = allClasses(); boolean ok = true; while( allclasses.hasMoreElements() ){ ClassInfo c = (ClassInfo)allclasses.nextElement(); if ( c.superClass==null ){ // only java.lang.Object can be parentless if ( ! c.className.equals( /*NOI18N*/"java/lang/Object" ) ){ System.out.println(Localizer.getString("classinfo.class_is_parent-less", c.className)); ok = false; } } else { ClassInfo s = ClassInfo.lookupClass( c.superClass.name.string ); if ( s == null ){ System.out.println(Localizer.getString("classinfo.class_is_missing_parent", c.className, c.superClass.name.string )); ok = false; } else { c.superClassInfo = s; } } } return ok; } public String toString(){ return /*NOI18N*/"ClassInfo-\""+className+/*NOI18N*/"\""; } // Convert ldc to ldc2 public void relocateAndPackCode() { for ( int i = 0; i < methods.length; i++ ) methods[i].relocateAndPackCode(constants); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -