📄 classrecord.java
字号:
package js.tinyvm;import java.io.BufferedInputStream;import java.io.IOException;import java.io.InputStream;import java.util.Hashtable;import java.util.Iterator;import java.util.Vector;import js.tinyvm.io.IByteWriter;import js.tinyvm.io.IOUtilities;import js.tinyvm.util.HashVector;import org.apache.bcel.Constants;import org.apache.bcel.classfile.ClassParser;import org.apache.bcel.classfile.Constant;import org.apache.bcel.classfile.ConstantClass;import org.apache.bcel.classfile.ConstantDouble;import org.apache.bcel.classfile.ConstantFloat;import org.apache.bcel.classfile.ConstantInteger;import org.apache.bcel.classfile.ConstantInterfaceMethodref;import org.apache.bcel.classfile.ConstantLong;import org.apache.bcel.classfile.ConstantMethodref;import org.apache.bcel.classfile.ConstantNameAndType;import org.apache.bcel.classfile.ConstantPool;import org.apache.bcel.classfile.ConstantString;import org.apache.bcel.classfile.Field;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Method;/** * Abstraction for a class record (see vmsrc/language.h). */public class ClassRecord implements WritableData{ int iIndex = -1; String iName; /** * On-demand size of the class. */ int iClassSize = -1; JavaClass iCF; Binary iBinary; final RecordTable iMethodTable = new RecordTable("methods", false, false); final RecordTable iInstanceFields = new RecordTable("instance fields", true, false); final Hashtable iStaticValues = new Hashtable(); final Hashtable iStaticFields = new Hashtable(); final Hashtable iMethods = new Hashtable(); final Vector iUsedMethods = new Vector(); int iParentClassIndex; int iArrayElementType; int iFlags; boolean iUseAllMethods = false; public void useAllMethods () { iUseAllMethods = true; } public String getName () { return iCF.getClassName(); } public int getLength () { return IOUtilities.adjustedSize(2 + // class size 2 + // method table offset 2 + // instance field table offset 1 + // number of fields 1 + // number of methods 1 + // parent class 1, // flags 2); } public void dump (IByteWriter aOut) throws TinyVMException { try { int pAllocSize = getAllocationSize(); assert pAllocSize != 0: "Check: alloc ok"; aOut.writeU2(pAllocSize); int pMethodTableOffset = iMethodTable.getOffset(); aOut.writeU2(pMethodTableOffset); aOut.writeU2(iInstanceFields.getOffset()); int pNumFields = iInstanceFields.size(); if (pNumFields > TinyVMConstants.MAX_FIELDS) { throw new TinyVMException("Class " + iName + ": No more than " + TinyVMConstants.MAX_FIELDS + " fields expected"); } aOut.writeU1(pNumFields); int pNumMethods = iMethodTable.size(); if (pNumMethods > TinyVMConstants.MAX_METHODS) { throw new TinyVMException("Class " + iName + ": No more than " + TinyVMConstants.MAX_METHODS + " methods expected"); } aOut.writeU1(pNumMethods); aOut.writeU1(iParentClassIndex); //aOut.writeU1 (iArrayElementType); aOut.writeU1(iFlags); IOUtilities.writePadding(aOut, 2); } catch (IOException e) { throw new TinyVMException(e.getMessage(), e); } } public boolean isArray () { // TBD: return false; } public boolean isInterface () { return iCF.isInterface(); } public boolean hasStaticInitializer () { Method[] methods = iCF.getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals(Constants.STATIC_INITIALIZER_NAME)) { return true; } } return false; } /** * (Call only after record has been processed). */ public boolean hasMethod (Signature aSignature, boolean aStatic) { MethodRecord pRec = (MethodRecord) iMethods.get(aSignature); if (pRec == null) return false; return ((pRec.getFlags() & TinyVMConstants.M_STATIC) == 0) ^ aStatic; } public void initFlags () { iFlags = 0; if (isArray()) iFlags |= TinyVMConstants.C_ARRAY; if (isInterface()) iFlags |= TinyVMConstants.C_INTERFACE; if (hasStaticInitializer()) iFlags |= TinyVMConstants.C_HASCLINIT; } /** * @return Number of words required for object allocation. * @throws TinyVMException */ public int getAllocationSize () throws TinyVMException { return (getClassSize() + 5) / 2; } /** * @return Number of bytes occupied by instance fields. * @throws TinyVMException */ public int getClassSize () throws TinyVMException { if (iClassSize != -1) return iClassSize; iClassSize = computeClassSize(); return iClassSize; } /** * @return The size of the class in 2-byte words, including any VM space. * This is the exact size required for memory allocation. * @throws TinyVMException */ public int computeClassSize () throws TinyVMException { int pSize = hasParent()? getParent().getClassSize() : 0; for (Iterator iter = iInstanceFields.iterator(); iter.hasNext();) { InstanceFieldRecord pRec = (InstanceFieldRecord) iter.next(); pSize += pRec.getFieldSize(); } return pSize; } public boolean hasParent () { return !"java.lang.Object".equals(iCF.getClassName()); } public ClassRecord getParent () { assert hasParent(): "Precondition: hasParent()"; ClassRecord result = iBinary.getClassRecord(iCF.getSuperclassName().replace('.', '/')); assert result != null: "Postconditon: result != null"; return result; } public void initParent () throws TinyVMException { if (hasParent()) { iParentClassIndex = iBinary.getClassIndex(getParent()); if (iParentClassIndex == -1) { throw new TinyVMException("Superclass of " + iCF.getClassName() + " not found"); } } else // only java.lang.Object has no super class... { iParentClassIndex = 0; if (!iCF.getClassName().equals("java.lang.Object")) { throw new TinyVMException("Expected java.lang.Object: " + iCF.getClassName()); } } } public void storeReferredClasses (Hashtable aClasses, RecordTable aClassRecords, ClassPath aClassPath, Vector aInterfaceMethods) throws TinyVMException { // _logger.log(Level.INFO, "Processing CONSTANT_Class entries in " + // iName); ConstantPool pPool = iCF.getConstantPool(); Constant[] constants = pPool.getConstantPool(); for (int i = 0; i < constants.length; i++) { Constant pEntry = constants[i]; if (pEntry instanceof ConstantClass) { String pClassName = ((ConstantClass) pEntry).getBytes(pPool); if (pClassName.startsWith("[")) { // _logger.log(Level.INFO, "Skipping array: " + pClassName); continue; } if (aClasses.get(pClassName) == null) { ClassRecord pRec = ClassRecord.getClassRecord(pClassName, aClassPath, iBinary); aClasses.put(pClassName, pRec); aClassRecords.add(pRec); } } else if (pEntry instanceof ConstantMethodref) { String className = ((ConstantMethodref) pEntry).getClass(pPool) .replace('.', '/'); ClassRecord pClassRec = (ClassRecord) aClasses.get(className); if (pClassRec == null) { pClassRec = ClassRecord.getClassRecord(className, aClassPath, iBinary); aClasses.put(className, pClassRec);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -