📄 classreader.java
字号:
throw badClassFile("unicode.str.not.supported"); case CONSTANT_Class: poolObj[i] = readClassOrType(getChar(index + 1)); break; case CONSTANT_String: poolObj[i] = readName(getChar(index + 1)).toString(); break; case CONSTANT_Fieldref: { ClassSymbol owner = readClassSymbol(getChar(index + 1)); NameAndType nt = (NameAndType) readPool(getChar(index + 3)); poolObj[i] = new VarSymbol(0, nt.name, nt.type, owner); break; } case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: { ClassSymbol owner = readClassSymbol(getChar(index + 1)); NameAndType nt = (NameAndType) readPool(getChar(index + 3)); poolObj[i] = new MethodSymbol(0, nt.name, nt.type, owner); break; } case CONSTANT_NameandType: poolObj[i] = new NameAndType(readName(getChar(index + 1)), readType(getChar(index + 3))); break; case CONSTANT_Integer: poolObj[i] = new Integer(getInt(index + 1)); break; case CONSTANT_Float: poolObj[i] = new Float(getFloat(index + 1)); break; case CONSTANT_Long: poolObj[i] = new Long(getLong(index + 1)); break; case CONSTANT_Double: poolObj[i] = new Double(getDouble(index + 1)); break; default: throw badClassFile("bad.const.pool.tag", Byte.toString(tag)); } return poolObj[i]; } /** * Read signature and convert to type. */ Type readType(int i) { int index = poolIdx[i]; return sigToType(buf, index + 3, getChar(index + 1)); } /** * If name is an array type or class signature, return the * corresponding type; otherwise return a ClassSymbol with given name. */ Object readClassOrType(int i) { int index = poolIdx[i]; int len = getChar(index + 1); int start = index + 3; return (buf[start] == '[' || buf[start + len - 1] == ';') ? (Object) sigToType(buf, start, len) : (Object) enterClass(names.fromUtf(internalize(buf, start, len))); } /** * Read class entry. */ ClassSymbol readClassSymbol(int i) { return (ClassSymbol)(readPool(i)); } /** * Read name. */ Name readName(int i) { return (Name)(readPool(i)); } /** * The unread portion of the currently read type is * signature[sigp..siglimit-1]. */ byte[] signature; int sigp; int siglimit; boolean sigEnterPhase = false; /** * Convert signature to type, where signature is a name. */ Type sigToType(Name sig) { return sig == null ? null : sigToType(sig.table.names, sig.index, sig.len); } /** * Convert signature to type, where signature is a byte array segment. */ Type sigToType(byte[] sig, int offset, int len) { signature = sig; sigp = offset; siglimit = offset + len; return sigToType(); } /** * Convert signature to type, where signature is implicit. */ Type sigToType() { switch ((char) signature[sigp]) { case 'B': sigp++; return syms.byteType; case 'C': sigp++; return syms.charType; case 'D': sigp++; return syms.doubleType; case 'F': sigp++; return syms.floatType; case 'I': sigp++; return syms.intType; case 'J': sigp++; return syms.longType; case 'L': Type t = classSigToType(Type.noType); while (sigp < siglimit && signature[sigp] == '.') { sigp++; t = classSigToType(t); } return t; case 'S': sigp++; return syms.shortType; case 'V': sigp++; return syms.voidType; case 'Z': sigp++; return syms.booleanType; case '[': sigp++; while ('0' <= signature[sigp] && signature[sigp] <= '9') sigp++; return new ArrayType(sigToType(), syms.arrayClass); case '(': List argtypes = sigToTypes(')'); Type restype = sigToType(); ListBuffer thrown = new ListBuffer(); while (signature[sigp] == '^') { sigp++; thrown.append(sigToType()); } return new MethodType(argtypes, restype, thrown.toList(), syms.methodClass); default: throw badClassFile("bad.signature", Convert.utf2string(signature, sigp, 10)); } } /** * Convert class signature to type, where signature is implicit. * @param outer The outer type encountered so far. This is meaningful * only if outer is parameterized. In that case we know * that we have to store it in the new type's * outer_field since a parameterized prefix is legal * only for non-static inner classes. */ Type classSigToType(Type outer) { if (signature[sigp] == 'L') { sigp++; int start = sigp; while (signature[sigp] != ';' && signature[sigp] != '<') sigp++; ClassType t = (ClassType) enterClass( names.fromUtf(internalize(signature, start, sigp - start))).type; if (signature[sigp] == '<') t = new ClassType(t.outer_field, sigToTypes('>'), t.tsym); else if (t.typarams().nonEmpty()) t = (ClassType) t.erasure(); if (outer.isParameterized()) t = new ClassType(outer, t.typarams(), t.tsym); sigp++; return t; } else { throw badClassFile("bad.class.signature", Convert.utf2string(signature, sigp, 10)); } } /** * Convert (implicit) signature to list of types * until `terminator' is encountered. */ List sigToTypes(char terminator) { sigp++; ListBuffer types = new ListBuffer(); while (signature[sigp] != terminator) types.append(sigToType()); sigp++; return types.toList(); } /** * Report unrecognized attribute. */ void unrecogized(Name attrName) { if (checkClassFile) printCCF("ccf.unrecognized.attribute", attrName.toJava()); } /** * Read member attribute. */ void readMemberAttr(Symbol sym, Name attrName, int attrLen) { if (attrName == names.ConstantValue) { Object v = readPool(nextChar()); if ((sym.flags() & FINAL) != 0) ((VarSymbol) sym).constValue = v; } else if (attrName == names.Code) { if (readAllOfClassFile) ((MethodSymbol) sym).code = readCode(sym); else bp = bp + attrLen; } else if (attrName == names.Exceptions) { int nexceptions = nextChar(); ListBuffer thrown = new ListBuffer(); for (int j = 0; j < nexceptions; j++) thrown.append(readClassSymbol(nextChar()).type); if (sym.type.thrown().isEmpty()) sym.type.asMethodType().thrown = thrown.toList(); } else if (attrName == names.Synthetic) { sym.flags_field |= SYNTHETIC; } else if (attrName == names.Deprecated) { sym.flags_field |= DEPRECATED; } else { unrecogized(attrName); bp = bp + attrLen; } } /** * Read member attributes. */ void readMemberAttrs(Symbol sym) { char ac = nextChar(); for (int i = 0; i < ac; i++) { Name attrName = readName(nextChar()); int attrLen = nextInt(); readMemberAttr(sym, attrName, attrLen); } } /** * Read class attribute. */ void readClassAttr(ClassSymbol c, Name attrName, int attrLen) { if (attrName == names.SourceFile) { c.sourcefile = readName(nextChar()); } else if (attrName == names.InnerClasses) { readInnerClasses(c); } else { readMemberAttr(c, attrName, attrLen); } } /** * Read class attributes. */ void readClassAttrs(ClassSymbol c) { char ac = nextChar(); for (int i = 0; i < ac; i++) { Name attrName = readName(nextChar()); int attrLen = nextInt(); readClassAttr(c, attrName, attrLen); } } /** * Read code block. */ Code readCode(Symbol owner) { return null; } /** * Read a field. */ VarSymbol readField() { int flags = nextChar(); Name name = readName(nextChar()); Type type = readType(nextChar()); VarSymbol v = new VarSymbol(flags, name, type, currentOwner); readMemberAttrs(v); return v; } /** * Read a method. */ MethodSymbol readMethod() { int flags = nextChar(); Name name = readName(nextChar()); Type type = readType(nextChar()); if (name == names.init && currentOwner.hasOuterInstance()) { type = new MethodType(type.argtypes().tail, type.restype(), type.thrown(), syms.methodClass); } MethodSymbol m = new MethodSymbol(flags, name, type, currentOwner); Symbol prevOwner = currentOwner; currentOwner = m; readMemberAttrs(m); currentOwner = prevOwner; return m; } /** * Skip a field or method */ void skipMember() { bp = bp + 6; char ac = nextChar(); for (int i = 0; i < ac; i++) { bp = bp + 2; int attrLen = nextInt(); bp = bp + attrLen; } } /** * Enter type variables of this classtype and all enclosing ones in * `typevars'. */ void enterTypevars(Type t) { if (t.outer().tag == CLASS) enterTypevars(t.outer()); for (List xs = t.typarams(); xs.nonEmpty(); xs = xs.tail) typevars.enter(((Type) xs.head).tsym); } /** * Read contents of a given class symbol `c'. Both external and internal * versions of an inner class are read. */ void readClass(ClassSymbol c) { ClassType ct = (ClassType) c.type; c.members_field = new Scope(c); typevars = typevars.dup(); if (ct.outer().tag == CLASS) enterTypevars(ct.outer()); int flags = nextChar(); if (c.owner.kind == PCK) c.flags_field = flags; ClassSymbol self = readClassSymbol(nextChar()); if (c != self) throw badClassFile("class.file.wrong.class", self.flatname.toJava()); int startbp = bp; nextChar(); char interfaceCount = nextChar(); bp += interfaceCount * 2; char fieldCount = nextChar(); for (int i = 0; i < fieldCount; i++) skipMember(); char methodCount = nextChar(); for (int i = 0; i < methodCount; i++) skipMember(); readClassAttrs(c); if (readAllOfClassFile) { for (int i = 1; i < poolObj.length; i++) readPool(i); c.pool = new Pool(poolObj.length, poolObj); } bp = startbp; int n = nextChar(); ct.supertype_field = (n == 0) ? Type.noType : readClassSymbol(n).type; n = nextChar(); ListBuffer is = new ListBuffer(); for (int i = 0; i < n; i++) is.append(readClassSymbol(nextChar()).type); ct.interfaces_field = is.toList(); if (fieldCount != nextChar()) assert false; for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); if (methodCount != nextChar()) assert false; for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); typevars = typevars.leave(); } /** * Read inner class info. For each inner/outer pair allocate a * member class. */ void readInnerClasses(ClassSymbol c) { int n = nextChar(); for (int i = 0; i < n; i++) { nextChar(); ClassSymbol outer = readClassSymbol(nextChar()); Name name = readName(nextChar()); if (name == null) name = names.empty; int flags = nextChar(); if (outer != null) { if (name == names.empty) name = names.one; ClassSymbol member = enterClass(name, outer); if ((flags & STATIC) == 0) { ((ClassType) member.type).outer_field = outer.type; } if (c == outer) { member.flags_field = flags; enterMember(c, member); } } } } /** * Read a class file. */ void readClassFile(ClassSymbol c) throws IOException { int magic = nextInt(); if (magic != JAVA_MAGIC) throw badClassFile("illegal.start.of.class.file"); int minorVersion = nextChar(); int majorVersion = nextChar(); if (majorVersion > Target.MAX().majorVersion || majorVersion * 1000 + minorVersion < Target.MIN().majorVersion * 1000 + Target.MIN().minorVersion) { throw badClassFile("wrong.version", Integer.toString(majorVersion), Integer.toString(minorVersion), Integer.toString(Target.MAX().majorVersion), Integer.toString(Target.MAX().minorVersion));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -