📄 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 + -