📄 classwriter.java
字号:
static class SameFrame extends StackMapTableFrame { final int offsetDelta; SameFrame(int offsetDelta) { this.offsetDelta = offsetDelta; } int getFrameType() { return (offsetDelta < SAME_FRAME_SIZE) ? offsetDelta : SAME_FRAME_EXTENDED; } @Override void write(ClassWriter writer) { super.write(writer); if (getFrameType() == SAME_FRAME_EXTENDED) { writer.databuf.appendChar(offsetDelta); if (writer.debugstackmap){ System.out.print(" offset_delta=" + offsetDelta); } } } } static class SameLocals1StackItemFrame extends StackMapTableFrame { final int offsetDelta; final Type stack; SameLocals1StackItemFrame(int offsetDelta, Type stack) { this.offsetDelta = offsetDelta; this.stack = stack; } int getFrameType() { return (offsetDelta < SAME_FRAME_SIZE) ? (SAME_FRAME_SIZE + offsetDelta) : SAME_LOCALS_1_STACK_ITEM_EXTENDED; } @Override void write(ClassWriter writer) { super.write(writer); if (getFrameType() == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { writer.databuf.appendChar(offsetDelta); if (writer.debugstackmap) { System.out.print(" offset_delta=" + offsetDelta); } } if (writer.debugstackmap) { System.out.print(" stack[" + 0 + "]="); } writer.writeStackMapType(stack); } } static class ChopFrame extends StackMapTableFrame { final int frameType; final int offsetDelta; ChopFrame(int frameType, int offsetDelta) { this.frameType = frameType; this.offsetDelta = offsetDelta; } int getFrameType() { return frameType; } @Override void write(ClassWriter writer) { super.write(writer); writer.databuf.appendChar(offsetDelta); if (writer.debugstackmap) { System.out.print(" offset_delta=" + offsetDelta); } } } static class AppendFrame extends StackMapTableFrame { final int frameType; final int offsetDelta; final Type[] locals; AppendFrame(int frameType, int offsetDelta, Type[] locals) { this.frameType = frameType; this.offsetDelta = offsetDelta; this.locals = locals; } int getFrameType() { return frameType; } @Override void write(ClassWriter writer) { super.write(writer); writer.databuf.appendChar(offsetDelta); if (writer.debugstackmap) { System.out.print(" offset_delta=" + offsetDelta); } for (int i=0; i<locals.length; i++) { if (writer.debugstackmap) System.out.print(" locals[" + i + "]="); writer.writeStackMapType(locals[i]); } } } static class FullFrame extends StackMapTableFrame { final int offsetDelta; final Type[] locals; final Type[] stack; FullFrame(int offsetDelta, Type[] locals, Type[] stack) { this.offsetDelta = offsetDelta; this.locals = locals; this.stack = stack; } int getFrameType() { return FULL_FRAME; } @Override void write(ClassWriter writer) { super.write(writer); writer.databuf.appendChar(offsetDelta); writer.databuf.appendChar(locals.length); if (writer.debugstackmap) { System.out.print(" offset_delta=" + offsetDelta); System.out.print(" nlocals=" + locals.length); } for (int i=0; i<locals.length; i++) { if (writer.debugstackmap) System.out.print(" locals[" + i + "]="); writer.writeStackMapType(locals[i]); } writer.databuf.appendChar(stack.length); if (writer.debugstackmap) { System.out.print(" nstack=" + stack.length); } for (int i=0; i<stack.length; i++) { if (writer.debugstackmap) System.out.print(" stack[" + i + "]="); writer.writeStackMapType(stack[i]); } } } /** Compare this frame with the previous frame and produce * an entry of compressed stack map frame. */ static StackMapTableFrame getInstance(Code.StackMapFrame this_frame, int prev_pc, Type[] prev_locals, Types types) { Type[] locals = this_frame.locals; Type[] stack = this_frame.stack; int offset_delta = this_frame.pc - prev_pc - 1; if (stack.length == 1) { if (locals.length == prev_locals.length && compare(prev_locals, locals, types) == 0) { return new SameLocals1StackItemFrame(offset_delta, stack[0]); } } else if (stack.length == 0) { int diff_length = compare(prev_locals, locals, types); if (diff_length == 0) { return new SameFrame(offset_delta); } else if (-MAX_LOCAL_LENGTH_DIFF < diff_length && diff_length < 0) { // APPEND Type[] local_diff = new Type[-diff_length]; for (int i=prev_locals.length, j=0; i<locals.length; i++,j++) { local_diff[j] = locals[i]; } return new AppendFrame(SAME_FRAME_EXTENDED - diff_length, offset_delta, local_diff); } else if (0 < diff_length && diff_length < MAX_LOCAL_LENGTH_DIFF) { // CHOP return new ChopFrame(SAME_FRAME_EXTENDED - diff_length, offset_delta); } } // FULL_FRAME return new FullFrame(offset_delta, locals, stack); } static boolean isInt(Type t) { return (t.tag < TypeTags.INT || t.tag == TypeTags.BOOLEAN); } static boolean isSameType(Type t1, Type t2, Types types) { if (t1 == null) { return t2 == null; } if (t2 == null) { return false; } if (isInt(t1) && isInt(t2)) { return true; } if (t1.tag == UNINITIALIZED_THIS) { return t2.tag == UNINITIALIZED_THIS; } else if (t1.tag == UNINITIALIZED_OBJECT) { if (t2.tag == UNINITIALIZED_OBJECT) { return ((UninitializedType)t1).offset == ((UninitializedType)t2).offset; } else { return false; } } else if (t2.tag == UNINITIALIZED_THIS || t2.tag == UNINITIALIZED_OBJECT) { return false; } return types.isSameType(t1, t2); } static int compare(Type[] arr1, Type[] arr2, Types types) { int diff_length = arr1.length - arr2.length; if (diff_length > MAX_LOCAL_LENGTH_DIFF || diff_length < -MAX_LOCAL_LENGTH_DIFF) { return Integer.MAX_VALUE; } int len = (diff_length > 0) ? arr2.length : arr1.length; for (int i=0; i<len; i++) { if (!isSameType(arr1[i], arr2[i], types)) { return Integer.MAX_VALUE; } } return diff_length; } } void writeFields(Scope.Entry e) { // process them in reverse sibling order; // i.e., process them in declaration order. List<VarSymbol> vars = List.nil(); for (Scope.Entry i = e; i != null; i = i.sibling) { if (i.sym.kind == VAR) vars = vars.prepend((VarSymbol)i.sym); } while (vars.nonEmpty()) { writeField(vars.head); vars = vars.tail; } } void writeMethods(Scope.Entry e) { List<MethodSymbol> methods = List.nil(); for (Scope.Entry i = e; i != null; i = i.sibling) { if (i.sym.kind == MTH && (i.sym.flags() & HYPOTHETICAL) == 0) methods = methods.prepend((MethodSymbol)i.sym); } while (methods.nonEmpty()) { writeMethod(methods.head); methods = methods.tail; } } /** Emit a class file for a given class. * @param c The class from which a class file is generated. */ public JavaFileObject writeClass(ClassSymbol c) throws IOException, PoolOverflow, StringOverflow { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, c.flatname.toString(), JavaFileObject.Kind.CLASS, c.sourcefile); OutputStream out = outFile.openOutputStream(); try { writeClassFile(out, c); if (verbose) log.errWriter.println(log.getLocalizedString("verbose.wrote.file", outFile)); out.close(); out = null; } finally { if (out != null) { // if we are propogating an exception, delete the file out.close(); outFile.delete(); outFile = null; } } return outFile; // may be null if write failed } /** Write class `c' to outstream `out'. */ public void writeClassFile(OutputStream out, ClassSymbol c) throws IOException, PoolOverflow, StringOverflow { assert (c.flags() & COMPOUND) == 0; databuf.reset(); poolbuf.reset(); sigbuf.reset(); pool = c.pool; innerClasses = null; innerClassesQueue = null; Type supertype = types.supertype(c.type); List<Type> interfaces = types.interfaces(c.type); List<Type> typarams = c.type.getTypeArguments(); int flags = adjustFlags(c.flags()); if ((flags & PROTECTED) != 0) flags |= PUBLIC; flags = flags & ClassFlags & ~STRICTFP; if ((flags & INTERFACE) == 0) flags |= ACC_SUPER; if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL; if (dumpClassModifiers) { log.errWriter.println(); log.errWriter.println("CLASSFILE " + c.getQualifiedName()); log.errWriter.println("---" + flagNames(flags)); } databuf.appendChar(flags); databuf.appendChar(pool.put(c)); databuf.appendChar(supertype.tag == CLASS ? pool.put(supertype.tsym) : 0); databuf.appendChar(interfaces.length()); for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail) databuf.appendChar(pool.put(l.head.tsym)); int fieldsCount = 0; int methodsCount = 0; for (Scope.Entry e = c.members().elems; e != null; e = e.sibling) { switch (e.sym.kind) { case VAR: fieldsCount++; break; case MTH: if ((e.sym.flags() & HYPOTHETICAL) == 0) methodsCount++; break; case TYP: enterInner((ClassSymbol)e.sym); break; default : assert false; } } databuf.appendChar(fieldsCount); writeFields(c.members().elems); databuf.appendChar(methodsCount); writeMethods(c.members().elems); int acountIdx = beginAttrs(); int acount = 0; boolean sigReq = typarams.length() != 0 || supertype.getTypeArguments().length() != 0; for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail) sigReq = l.head.getTypeArguments().length() != 0; if (sigReq) { assert source.allowGenerics(); int alenIdx = writeAttr(names.Signature); if (typarams.length() != 0) assembleParamsSig(typarams); assembleSig(supertype); for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail) assembleSig(l.head); databuf.appendChar(pool.put(sigbuf.toName(names))); sigbuf.reset(); endAttr(alenIdx); acount++; } if (c.sourcefile != null && emitSourceFile) { int alenIdx = writeAttr(names.SourceFile); // WHM 6/29/1999: Strip file path prefix. We do it here at // the last possible moment because the sourcefile may be used // elsewhere in error diagnostics. Fixes 4241573. //databuf.appendChar(c.pool.put(c.sourcefile)); String filename = c.sourcefile.toString(); int sepIdx = filename.lastIndexOf(File.separatorChar); // Allow '/' as separator on all platforms, e.g., on Win32. int slashIdx = filename.lastIndexOf('/'); if (slashIdx > sepIdx) sepIdx = slashIdx; if (sepIdx >= 0) filename = filename.substring(sepIdx + 1); databuf.appendChar(c.pool.put(names.fromString(filename))); endAttr(alenIdx); acount++; } if (genCrt) { // Append SourceID attribute int alenIdx = writeAttr(names.SourceID); databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile))))); endAttr(alenIdx); acount++; // Append CompilationID attribute alenIdx = writeAttr(names.CompilationID); databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis())))); endAttr(alenIdx); acount++; } acount += writeFlagAttrs(c.flags()); acount += writeJavaAnnotations(c.getAnnotationMirrors()); acount += writeEnclosingMethodAttribute(c); poolbuf.appendInt(JAVA_MAGIC); poolbuf.appendChar(target.minorVersion); poolbuf.appendChar(target.majorVersion); writePool(c.pool); if (innerClasses != null) { writeInnerClasses(); acount++; } endAttrs(acountIdx, acount); poolbuf.appendBytes(databuf.elems, 0, databuf.length); out.write(poolbuf.elems, 0, poolbuf.length); pool = c.pool = null; // to conserve space } int adjustFlags(final long flags) { int result = (int)flags; if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) result &= ~SYNTHETIC; if ((flags & ENUM) != 0 && !target.useEnumFlag()) result &= ~ENUM; if ((flags & ANNOTATION) != 0 && !target.useAnnotationFlag()) result &= ~ANNOTATION; if ((flags & BRIDGE) != 0 && target.useBridgeFlag()) result |= ACC_BRIDGE; if ((flags & VARARGS) != 0 && target.useVarargsFlag()) result |= ACC_VARARGS; return result; } long getLastModified(FileObject filename) { long mod = 0; try { mod = filename.getLastModified(); } catch (SecurityException e) { throw new AssertionError("CRT: couldn't get source file modification date: " + e.getMessage()); } return mod; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -