classinfo.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,142 行 · 第 1/3 页
JAVA
1,142 行
if (name.string.equals(/*NOI18N*/"SourceFile")) { if (ClassInfo.classDebug) { UnicodeConstant srcName = (UnicodeConstant)constants[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 if (name.string.equals("InnerClasses")) { //Added to support the InnerClasses Attribute defined in the //1.2 JVM Spec. /* this need not be done if reflection isn't supported */ innerClassAttr = (InnerClassAttribute)InnerClassAttribute.readAttribute(in, bytes, name, constants); clssAttr.addElement(innerClassAttr); /* TODO :: BEGIN experimental code for future signature support. } else if (name.string.equals("Signature")) { // Added to support the Signature Attribute defined in the // 1.5 VM spec. // this need not be done if reflection isn't supported. int idx = in.readUnsignedShort(); UnicodeConstant signature = (UnicodeConstant)constants[idx]; //StringConstant sigStr = StringConstant.utfToString(signature); //sigStr = (StringConstant)cp.add(sigStr); //sigStr.resolve(cp); //constants = cp.getConstants(); signatureAttr = //new SignatureAttribute(name, bytes, sigStr); new SignatureAttribute(name, bytes, signature); clssAttr.addElement(signatureAttr); * TODO :: END */ } 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); } } // Read in the entire classfile. // Assumes that the file is open, and the magic numbers are o.k. // public void read(DataInput in, boolean readCode) throws IOException { readConstantPool(in); flattenConstants(); Assert.disallowClassloading(); ConstantObject constants[] = cp.getConstants(); access = in.readUnsignedShort(); thisClass = (ClassConstant) constants[in.readUnsignedShort()]; int sup = in.readUnsignedShort(); if (sup != 0) { superClass = (ClassConstant) constants[sup]; } className = thisClass.name.string; pkgNameLength = className.lastIndexOf(SIGC_PACKAGE); // Read the various parts of the class file readInterfaces( in ); readFields( in ); readMethods( in, readCode ); readAttributes( in ); /* DONT DO THIS HERE enterClass(); */ Assert.allowClassloading(); } // Sets the classfile version numner: public void setVersionInfo(int majorVersion, int minorVersion) { this.majorVersion = majorVersion; this.minorVersion = minorVersion; } // 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(){ 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(); 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; // // Build a mapping of slot id to FieldInfo structure. // This makes offset based calculations much easier -- for // example stackmap computation // this.slottable = buildSlotTable(fieldtable, fieldoff); } // // Build a mapping of slot id to FieldInfo structure. // This makes offset based calculations much easier -- for // example stackmap computation // private FieldInfo[] buildSlotTable(FieldInfo[] fieldtable, int slotTableSize) { FieldInfo[] slotTable = new FieldInfo[slotTableSize]; int sIdx = 0; for (int i = 0; i < fieldtable.length; i++) { FieldInfo fld = fieldtable[i]; if (fld.nSlots == 1) { slotTable[sIdx] = fld; } else { slotTable[sIdx] = fld; slotTable[sIdx + 1] = fld; } sIdx += fld.nSlots; } return slotTable; } // 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. // // Jdk 1.4 javac does not insert miranda methods // into a class if the class is abstract and does not // declare all the methods of its direct superinterfaces, // like older versions of javac. So we are doing it. public void buildMethodtable() { if ( this.methodtable != null ) return; // already done. MethodInfo table[]; MethodInfo methods0[] = this.methods; ClassInfo sup = superClassInfo; int myPkgNameLength = this.pkgNameLength; if ((sup != null) && ( (sup.access&Const.ACC_INTERFACE)==(this.access&Const.ACC_INTERFACE) ) ) { sup.buildMethodtable(); table = sup.methodtable; } else { table = new MethodInfo[0]; } // // This might change soon, if we try to override the non-trivial // finalizer of the superclass with a trivial one. Otherwise // it stands. // if (sup != null) { this.hasNonTrivialFinalizer = sup.hasNonTrivialFinalizer; } /* * allocate a temporary table that is certainly large enough. * It starts as a copy of our parent's table */ MethodInfo newTable[] = new MethodInfo[table.length + methods0.length]; int index = table.length; System.arraycopy( table, 0, newTable, 0, index ); if (sup == null) { // finalize() goes into slot 0 of java.lang.Object index++; } method_loop: for (int i = 0; i < methods0.length; i++) { if ((methods0[i].access & (Const.ACC_STATIC|Const.ACC_PRIVATE)) != 0) { /* static and private methods don't go in the table */ continue method_loop; } else if (methods0[i].name.string.equals(/*NOI18N*/"<init>")) { /* <init> methods don't go in the table */ continue method_loop; } else if (sup == null && methods0[i].name.string.equals(/*NOI18N*/"finalize") && methods0[i].type.string.equals(/*NOI18N*/"()V")) { /* java.lang.Object.finalize()V always goes at the top of the table*/ newTable[0] = methods0[i]; newTable[0].methodTableIndex = 0; // 1=>0 EJVM continue method_loop; } int j; int thisID = methods0[i].getID(); if (thisID == finalizerID) { /* Note that this class has its own finalizer */ this.hasNonTrivialFinalizer = methods0[i].isNonTrivial(); } /* * Now search the table (initialized with our parent's table) * for a name/type match. * Since private methods aren't even in the table, we don't have * to worry about those. But we do need to consider * package scoping. */ match_loop: for ( j = 0; j < table.length; j++) { if (thisID == table[j].getID()) { MethodInfo parentMethod = table[j]; if ((parentMethod.access & (Const.ACC_PUBLIC|Const.ACC_PROTECTED)) == 0) { /* * we must be in the same package to override this one * sadly, the only way to compare packages is * to compare names */ int parentPkgNameLength = parentMethod.parent.pkgNameLength; boolean equalPkgNames; if (parentPkgNameLength != myPkgNameLength){ /* package names of unequal length. Quick failure */ equalPkgNames = false; } else if (myPkgNameLength == -1){ equalPkgNames = true; // neither is in a package. } else { equalPkgNames = parentMethod.parent.className.regionMatches( 0, className, 0, myPkgNameLength); } if (! equalPkgNames){ /* package names of unequal value. Failure */ continue match_loop; } } newTable[j] = methods0[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] = methods0[i]; newTable[index].methodTableIndex = index + 0; // 1=>0 EJVM index++; } // now allocate a table of the correct size. MethodInfo methodTable0[] = new MethodInfo[index]; System.arraycopy( newTable, 0, methodTable0, 0, index ); this.methodtable = methodTable0; // now try to resolve miranda methods. MethodInfo thisMethodtable[] = null; MethodInfo thisMethods[] = null; if ((this.access&Const.ACC_ABSTRACT) != 0 && (this.access&Const.ACC_INTERFACE) == 0 ) { int i; int methodsnumber = methods.length; for (i = 0; i < interfaces.length; i++) { ClassInfo superinterface = interfaces[i].find(); superinterface.buildMethodtable(); MethodInfo interfaceMethodtable[] = superinterface.methodtable; MethodInfo tmpTable[] = new MethodInfo[interfaceMethodtable.length]; int idx = 0; interface_method_loop: for (int j = 0; j < interfaceMethodtable.length; j++) { int imID = interfaceMethodtable[j].getID(); for (int k = 0; k < methodtable.length; k++) { if (imID == methodtable[k].getID()) { continue interface_method_loop; } } // We need to get a copy of the methodInfo, because // we are going to change its states. try { tmpTable[idx] = (MethodInfo)(interfaceMethodtable[j].clone()); tmpTable[idx].parent = this; tmpTable[idx].index = methodsnumber; methodsnumber++; } catch (CloneNotSupportedException cnse) { cnse.printStackTrace(); } idx++; } // We need to insert these miranda methods into // both this.methods[] and this.methodtable[]. // The reason is methods[] data structure is // used to resolve MethodRef constant in quicken // process, while methodtable[] is used in // InterfaceMethodTable.generateInterfaceVector() // to verify if the class implements all the // interface methods. if (idx > 0) { int newMethodsNum = methods.length + idx; thisMethods = new MethodInfo[newMethodsNum]; System.arraycopy(methods, 0, thisMethods, 0, methods.length); System.arraycopy(tmpTable, 0, thisMethods, methods.length, idx); this.methods = thisMethods; int newTableLen = methodtable.length + idx; thisMethodtable = new MethodInfo[newTableLen]; System.arraycopy(methodtable, 0, thisMethodtable, 0, methodtable.length); System.arraycopy(tmpTable, 0, thisMethodtable, methodtable.length, idx); for (int mtidx = methodtable.length; mtidx < newTableLen; mtidx++) { thisMethodtable[mtidx].methodTableIndex = mtidx + 0; } this.methodtable = thisMethodtable; } } } } 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 ( allInterfaces != null ) return; // already done 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();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?