📄 classwriter.java
字号:
/* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.jvm;import java.io.*;import java.util.*;import java.util.Set;import java.util.HashSet;import javax.tools.JavaFileManager;import javax.tools.FileObject;import javax.tools.JavaFileObject;import com.sun.tools.javac.code.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.List;import static com.sun.tools.javac.code.BoundKind.*;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;import static com.sun.tools.javac.jvm.UninitializedType.*;import static javax.tools.StandardLocation.CLASS_OUTPUT;/** This class provides operations to map an internal symbol table graph * rooted in a ClassSymbol into a classfile. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class ClassWriter extends ClassFile { protected static final Context.Key<ClassWriter> classWriterKey = new Context.Key<ClassWriter>(); private final Symtab syms; private final Options options; /** Switch: verbose output. */ private boolean verbose; /** Switch: scrable private names. */ private boolean scramble; /** Switch: scrable private names. */ private boolean scrambleAll; /** Switch: retrofit mode. */ private boolean retrofit; /** Switch: emit source file attribute. */ private boolean emitSourceFile; /** Switch: generate CharacterRangeTable attribute. */ private boolean genCrt; /** Switch: describe the generated stackmap */ boolean debugstackmap; /** * Target class version. */ private Target target; /** * Source language version. */ private Source source; /** Type utilities. */ private Types types; /** The initial sizes of the data and constant pool buffers. * sizes are increased when buffers get full. */ static final int DATA_BUF_SIZE = 0x0fff0; static final int POOL_BUF_SIZE = 0x1fff0; /** An output buffer for member info. */ ByteBuffer databuf = new ByteBuffer(DATA_BUF_SIZE); /** An output buffer for the constant pool. */ ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE); /** An output buffer for type signatures. */ ByteBuffer sigbuf = new ByteBuffer(); /** The constant pool. */ Pool pool; /** The inner classes to be written, as a set. */ Set<ClassSymbol> innerClasses; /** The inner classes to be written, as a queue where * enclosing classes come first. */ ListBuffer<ClassSymbol> innerClassesQueue; /** The log to use for verbose output. */ private final Log log; /** The name table. */ private final Name.Table names; /** Access to files. */ private final JavaFileManager fileManager; /** The tags and constants used in compressed stackmap. */ static final int SAME_FRAME_SIZE = 64; static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; static final int SAME_FRAME_EXTENDED = 251; static final int FULL_FRAME = 255; static final int MAX_LOCAL_LENGTH_DIFF = 4; /** Get the ClassWriter instance for this context. */ public static ClassWriter instance(Context context) { ClassWriter instance = context.get(classWriterKey); if (instance == null) instance = new ClassWriter(context); return instance; } /** Construct a class writer, given an options table. */ private ClassWriter(Context context) { context.put(classWriterKey, this); log = Log.instance(context); names = Name.Table.instance(context); syms = Symtab.instance(context); options = Options.instance(context); target = Target.instance(context); source = Source.instance(context); types = Types.instance(context); fileManager = context.get(JavaFileManager.class); verbose = options.get("-verbose") != null; scramble = options.get("-scramble") != null; scrambleAll = options.get("-scrambleAll") != null; retrofit = options.get("-retrofit") != null; genCrt = options.get("-Xjcov") != null; debugstackmap = options.get("debugstackmap") != null; emitSourceFile = options.get("-g:")==null || options.get("-g:source")!=null; String dumpModFlags = options.get("dumpmodifiers"); dumpClassModifiers = (dumpModFlags != null && dumpModFlags.indexOf('c') != -1); dumpFieldModifiers = (dumpModFlags != null && dumpModFlags.indexOf('f') != -1); dumpInnerClassModifiers = (dumpModFlags != null && dumpModFlags.indexOf('i') != -1); dumpMethodModifiers = (dumpModFlags != null && dumpModFlags.indexOf('m') != -1); }/****************************************************************** * Diagnostics: dump generated class names and modifiers ******************************************************************/ /** Value of option 'dumpmodifiers' is a string * indicating which modifiers should be dumped for debugging: * 'c' -- classes * 'f' -- fields * 'i' -- innerclass attributes * 'm' -- methods * For example, to dump everything: * javac -XDdumpmodifiers=cifm MyProg.java */ private final boolean dumpClassModifiers; // -XDdumpmodifiers=c private final boolean dumpFieldModifiers; // -XDdumpmodifiers=f private final boolean dumpInnerClassModifiers; // -XDdumpmodifiers=i private final boolean dumpMethodModifiers; // -XDdumpmodifiers=m /** Return flags as a string, separated by " ". */ public static String flagNames(long flags) { StringBuffer sbuf = new StringBuffer(); int i = 0; long f = flags & StandardFlags; while (f != 0) { if ((f & 1) != 0) sbuf.append(" " + flagName[i]); f = f >> 1; i++; } return sbuf.toString(); } //where private final static String[] flagName = { "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL", "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE", "ABSTRACT", "STRICTFP"};/****************************************************************** * Output routines ******************************************************************/ /** Write a character into given byte buffer; * byte buffer will not be grown. */ void putChar(ByteBuffer buf, int op, int x) { buf.elems[op ] = (byte)((x >> 8) & 0xFF); buf.elems[op+1] = (byte)((x ) & 0xFF); } /** Write an integer into given byte buffer; * byte buffer will not be grown. */ void putInt(ByteBuffer buf, int adr, int x) { buf.elems[adr ] = (byte)((x >> 24) & 0xFF); buf.elems[adr+1] = (byte)((x >> 16) & 0xFF); buf.elems[adr+2] = (byte)((x >> 8) & 0xFF); buf.elems[adr+3] = (byte)((x ) & 0xFF); }/****************************************************************** * Signature Generation ******************************************************************/ /** Assemble signature of given type in string buffer. */ void assembleSig(Type type) { switch (type.tag) { case BYTE: sigbuf.appendByte('B'); break; case SHORT: sigbuf.appendByte('S'); break; case CHAR: sigbuf.appendByte('C'); break; case INT: sigbuf.appendByte('I'); break; case LONG: sigbuf.appendByte('J'); break; case FLOAT: sigbuf.appendByte('F'); break; case DOUBLE: sigbuf.appendByte('D'); break; case BOOLEAN: sigbuf.appendByte('Z'); break; case VOID: sigbuf.appendByte('V'); break; case CLASS: sigbuf.appendByte('L'); assembleClassSig(type); sigbuf.appendByte(';'); break; case ARRAY: ArrayType at = (ArrayType)type; sigbuf.appendByte('['); assembleSig(at.elemtype); break; case METHOD: MethodType mt = (MethodType)type; sigbuf.appendByte('('); assembleSig(mt.argtypes); sigbuf.appendByte(')'); assembleSig(mt.restype); if (hasTypeVar(mt.thrown)) { for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) { sigbuf.appendByte('^'); assembleSig(l.head); } } break; case WILDCARD: { WildcardType ta = (WildcardType) type; switch (ta.kind) { case SUPER: sigbuf.appendByte('-'); assembleSig(ta.type); break; case EXTENDS: sigbuf.appendByte('+'); assembleSig(ta.type); break; case UNBOUND: sigbuf.appendByte('*'); break; default: throw new AssertionError(ta.kind); } break; } case TYPEVAR: sigbuf.appendByte('T'); sigbuf.appendName(type.tsym.name); sigbuf.appendByte(';'); break; case FORALL: ForAll ft = (ForAll)type; assembleParamsSig(ft.tvars); assembleSig(ft.qtype); break; case UNINITIALIZED_THIS: case UNINITIALIZED_OBJECT: // we don't yet have a spec for uninitialized types in the // local variable table assembleSig(types.erasure(((UninitializedType)type).qtype)); break; default: throw new AssertionError("typeSig " + type.tag); } } boolean hasTypeVar(List<Type> l) { while (l.nonEmpty()) { if (l.head.tag == TypeTags.TYPEVAR) return true; l = l.tail; } return false; } void assembleClassSig(Type type) { ClassType ct = (ClassType)type; ClassSymbol c = (ClassSymbol)ct.tsym; enterInner(c); Type outer = ct.getEnclosingType(); if (outer.allparams().nonEmpty()) { boolean rawOuter = c.owner.kind == MTH || // either a local class c.name == names.empty; // or anonymous assembleClassSig(rawOuter ? types.erasure(outer) : outer); sigbuf.appendByte('.'); assert c.flatname.startsWith(c.owner.enclClass().flatname); sigbuf.appendName(rawOuter ? c.flatname.subName(c.owner.enclClass() .flatname.len+1, c.flatname.len) : c.name); } else { sigbuf.appendBytes(externalize(c.flatname)); } if (ct.getTypeArguments().nonEmpty()) { sigbuf.appendByte('<'); assembleSig(ct.getTypeArguments()); sigbuf.appendByte('>'); } } void assembleSig(List<Type> types) { for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) assembleSig(ts.head); } void assembleParamsSig(List<Type> typarams) { sigbuf.appendByte('<'); for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) { TypeVar tvar = (TypeVar)ts.head; sigbuf.appendName(tvar.tsym.name); List<Type> bounds = types.getBounds(tvar); if ((bounds.head.tsym.flags() & INTERFACE) != 0) { sigbuf.appendByte(':'); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -