📄 classwriter.java
字号:
for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) { sigbuf.appendByte(':'); assembleSig(l.head); } } sigbuf.appendByte('>'); } /** Return signature of given type */ Name typeSig(Type type) { assert sigbuf.length == 0; //- System.out.println(" ? " + type); assembleSig(type); Name n = sigbuf.toName(names); sigbuf.reset(); //- System.out.println(" " + n); return n; } /** Given a type t, return the extended class name of its erasure in * external representation. */ public Name xClassName(Type t) { if (t.tag == CLASS) { return names.fromUtf(externalize(t.tsym.flatName())); } else if (t.tag == ARRAY) { return typeSig(types.erasure(t)); } else { throw new AssertionError("xClassName"); } }/****************************************************************** * Writing the Constant Pool ******************************************************************/ /** Thrown when the constant pool is over full. */ public static class PoolOverflow extends Exception { private static final long serialVersionUID = 0; public PoolOverflow() {} } public static class StringOverflow extends Exception { private static final long serialVersionUID = 0; public final String value; public StringOverflow(String s) { value = s; } } /** Write constant pool to pool buffer. * Note: during writing, constant pool * might grow since some parts of constants still need to be entered. */ void writePool(Pool pool) throws PoolOverflow, StringOverflow { int poolCountIdx = poolbuf.length; poolbuf.appendChar(0); int i = 1; while (i < pool.pp) { Object value = pool.pool[i]; assert value != null; if (value instanceof Pool.Method) value = ((Pool.Method)value).m; else if (value instanceof Pool.Variable) value = ((Pool.Variable)value).v; if (value instanceof MethodSymbol) { MethodSymbol m = (MethodSymbol)value; poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0 ? CONSTANT_InterfaceMethodref : CONSTANT_Methodref); poolbuf.appendChar(pool.put(m.owner)); poolbuf.appendChar(pool.put(nameType(m))); } else if (value instanceof VarSymbol) { VarSymbol v = (VarSymbol)value; poolbuf.appendByte(CONSTANT_Fieldref); poolbuf.appendChar(pool.put(v.owner)); poolbuf.appendChar(pool.put(nameType(v))); } else if (value instanceof Name) { poolbuf.appendByte(CONSTANT_Utf8); byte[] bs = ((Name)value).toUtf(); poolbuf.appendChar(bs.length); poolbuf.appendBytes(bs, 0, bs.length); if (bs.length > Pool.MAX_STRING_LENGTH) throw new StringOverflow(value.toString()); } else if (value instanceof ClassSymbol) { ClassSymbol c = (ClassSymbol)value; if (c.owner.kind == TYP) pool.put(c.owner); poolbuf.appendByte(CONSTANT_Class); if (c.type.tag == ARRAY) { poolbuf.appendChar(pool.put(typeSig(c.type))); } else { poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname)))); enterInner(c); } } else if (value instanceof NameAndType) { NameAndType nt = (NameAndType)value; poolbuf.appendByte(CONSTANT_NameandType); poolbuf.appendChar(pool.put(nt.name)); poolbuf.appendChar(pool.put(typeSig(nt.type))); } else if (value instanceof Integer) { poolbuf.appendByte(CONSTANT_Integer); poolbuf.appendInt(((Integer)value).intValue()); } else if (value instanceof Long) { poolbuf.appendByte(CONSTANT_Long); poolbuf.appendLong(((Long)value).longValue()); i++; } else if (value instanceof Float) { poolbuf.appendByte(CONSTANT_Float); poolbuf.appendFloat(((Float)value).floatValue()); } else if (value instanceof Double) { poolbuf.appendByte(CONSTANT_Double); poolbuf.appendDouble(((Double)value).doubleValue()); i++; } else if (value instanceof String) { poolbuf.appendByte(CONSTANT_String); poolbuf.appendChar(pool.put(names.fromString((String)value))); } else if (value instanceof Type) { Type type = (Type)value; if (type.tag == CLASS) enterInner((ClassSymbol)type.tsym); poolbuf.appendByte(CONSTANT_Class); poolbuf.appendChar(pool.put(xClassName(type))); } else { assert false : "writePool " + value; } i++; } if (pool.pp > Pool.MAX_ENTRIES) throw new PoolOverflow(); putChar(poolbuf, poolCountIdx, pool.pp); } /** Given a field, return its name. */ Name fieldName(Symbol sym) { if (scramble && (sym.flags() & PRIVATE) != 0 || scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0) return names.fromString("_$" + sym.name.index); else return sym.name; } /** Given a symbol, return its name-and-type. */ NameAndType nameType(Symbol sym) { return new NameAndType(fieldName(sym), retrofit ? sym.erasure(types) : sym.externalType(types)); // if we retrofit, then the NameAndType has been read in as is // and no change is necessary. If we compile normally, the // NameAndType is generated from a symbol reference, and the // adjustment of adding an additional this$n parameter needs to be made. }/****************************************************************** * Writing Attributes ******************************************************************/ /** Write header for an attribute to data buffer and return * position past attribute length index. */ int writeAttr(Name attrName) { databuf.appendChar(pool.put(attrName)); databuf.appendInt(0); return databuf.length; } /** Fill in attribute length. */ void endAttr(int index) { putInt(databuf, index - 4, databuf.length - index); } /** Leave space for attribute count and return index for * number of attributes field. */ int beginAttrs() { databuf.appendChar(0); return databuf.length; } /** Fill in number of attributes. */ void endAttrs(int index, int count) { putChar(databuf, index - 2, count); } /** Write the EnclosingMethod attribute if needed. * Returns the number of attributes written (0 or 1). */ int writeEnclosingMethodAttribute(ClassSymbol c) { if (!target.hasEnclosingMethodAttribute() || c.owner.kind != MTH && // neither a local class c.name != names.empty) // nor anonymous return 0; int alenIdx = writeAttr(names.EnclosingMethod); ClassSymbol enclClass = c.owner.enclClass(); MethodSymbol enclMethod = (c.owner.type == null // local to init block || c.owner.kind != MTH) // or member init ? null : (MethodSymbol)c.owner; databuf.appendChar(pool.put(enclClass)); databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner))); endAttr(alenIdx); return 1; } /** Write flag attributes; return number of attributes written. */ int writeFlagAttrs(long flags) { int acount = 0; if ((flags & DEPRECATED) != 0) { int alenIdx = writeAttr(names.Deprecated); endAttr(alenIdx); acount++; } if ((flags & ENUM) != 0 && !target.useEnumFlag()) { int alenIdx = writeAttr(names.Enum); endAttr(alenIdx); acount++; } if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) { int alenIdx = writeAttr(names.Synthetic); endAttr(alenIdx); acount++; } if ((flags & BRIDGE) != 0 && !target.useBridgeFlag()) { int alenIdx = writeAttr(names.Bridge); endAttr(alenIdx); acount++; } if ((flags & VARARGS) != 0 && !target.useVarargsFlag()) { int alenIdx = writeAttr(names.Varargs); endAttr(alenIdx); acount++; } if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) { int alenIdx = writeAttr(names.Annotation); endAttr(alenIdx); acount++; } return acount; } /** Write member (field or method) attributes; * return number of attributes written. */ int writeMemberAttrs(Symbol sym) { int acount = writeFlagAttrs(sym.flags()); long flags = sym.flags(); if (source.allowGenerics() && (flags & (SYNTHETIC|BRIDGE)) != SYNTHETIC && (flags & ANONCONSTR) == 0 && (!types.isSameType(sym.type, sym.erasure(types)) || hasTypeVar(sym.type.getThrownTypes()))) { // note that a local class with captured variables // will get a signature attribute int alenIdx = writeAttr(names.Signature); databuf.appendChar(pool.put(typeSig(sym.type))); endAttr(alenIdx); acount++; } acount += writeJavaAnnotations(sym.getAnnotationMirrors()); return acount; } /** Write method parameter annotations; * return number of attributes written. */ int writeParameterAttrs(MethodSymbol m) { boolean hasVisible = false; boolean hasInvisible = false; if (m.params != null) for (VarSymbol s : m.params) { for (Attribute.Compound a : s.getAnnotationMirrors()) { switch (getRetention(a.type.tsym)) { case SOURCE: break; case CLASS: hasInvisible = true; break; case RUNTIME: hasVisible = true; break; default: ;// /* fail soft */ throw new AssertionError(vis); } } } int attrCount = 0; if (hasVisible) { int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations); databuf.appendByte(m.params.length()); for (VarSymbol s : m.params) { ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); for (Attribute.Compound a : s.getAnnotationMirrors()) if (getRetention(a.type.tsym) == RetentionPolicy.RUNTIME) buf.append(a); databuf.appendChar(buf.length()); for (Attribute.Compound a : buf) writeCompoundAttribute(a); } endAttr(attrIndex); attrCount++; } if (hasInvisible) { int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations); databuf.appendByte(m.params.length()); for (VarSymbol s : m.params) { ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); for (Attribute.Compound a : s.getAnnotationMirrors()) if (getRetention(a.type.tsym) == RetentionPolicy.CLASS) buf.append(a); databuf.appendChar(buf.length()); for (Attribute.Compound a : buf) writeCompoundAttribute(a); } endAttr(attrIndex); attrCount++; } return attrCount; }/********************************************************************** * Writing Java-language annotations (aka metadata, attributes) **********************************************************************/ /** Write Java-language annotations; return number of JVM * attributes written (zero or one). */ int writeJavaAnnotations(List<Attribute.Compound> attrs) { if (attrs.isEmpty()) return 0; ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>(); ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>(); for (Attribute.Compound a : attrs) { switch (getRetention(a.type.tsym)) { case SOURCE: break; case CLASS: invisibles.append(a); break; case RUNTIME: visibles.append(a); break; default: ;// /* fail soft */ throw new AssertionError(vis); } } int attrCount = 0; if (visibles.length() != 0) { int attrIndex = writeAttr(names.RuntimeVisibleAnnotations); databuf.appendChar(visibles.length()); for (Attribute.Compound a : visibles) writeCompoundAttribute(a); endAttr(attrIndex); attrCount++; } if (invisibles.length() != 0) { int attrIndex = writeAttr(names.RuntimeInvisibleAnnotations); databuf.appendChar(invisibles.length()); for (Attribute.Compound a : invisibles) writeCompoundAttribute(a); endAttr(attrIndex); attrCount++; } return attrCount; } /** A mirror of java.lang.annotation.RetentionPolicy. */ enum RetentionPolicy { SOURCE, CLASS, RUNTIME } RetentionPolicy getRetention(TypeSymbol annotationType) { RetentionPolicy vis = RetentionPolicy.CLASS; // the default Attribute.Compound c = annotationType.attribute(syms.retentionType.tsym); if (c != null) { Attribute value = c.member(names.value); if (value != null && value instanceof Attribute.Enum) { Name levelName = ((Attribute.Enum)value).value.name; if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE; else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS; else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME; else ;// /* fail soft */ throw new AssertionError(levelName); } } return vis; } /** A visitor to write an attribute including its leading * single-character marker. */ class AttributeWriter implements Attribute.Visitor { public void visitConstant(Attribute.Constant _value) { Object value = _value.value; switch (_value.type.tag) { case BYTE: databuf.appendByte('B'); break; case CHAR: databuf.appendByte('C'); break; case SHORT: databuf.appendByte('S'); break; case INT: databuf.appendByte('I'); break; case LONG: databuf.appendByte('J'); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -