📄 classwriter.java
字号:
/** * @(#)ClassWriter.java 1.48 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.tools.javac.v8.code;import com.sun.tools.javac.v8.util.*;import java.io.*;import com.sun.tools.javac.v8.code.Symbol.*;import com.sun.tools.javac.v8.code.Type.*;/** * This class provides operations to map an internal symbol table graph * rooted in a ClassSymbol into a classfile. */public class ClassWriter extends ClassFile implements Flags, Kinds, TypeTags { private static final Context.Key classWriterKey = new Context.Key(); private final Symtab syms; /** * Can be reassigned from outside: the output directory. * If outDir = null, files are written into same directory as the sources * the were generated from. */ public File outDir = null; /** * 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; /** * Target class version. */ private Target target; /** * The initial sizes of the data and constant pool buffers. * sizes are increased when buffers get full. */ static final int DATA_BUF_SIZE = 65520; static final int POOL_BUF_SIZE = 131056; /** * 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 innerClasses; /** * The inner classes to be written, as a queue where * enclosing classes come first. */ ListBuffer innerClassesQueue; /** * The log to use for verbose output. */ private final Log log; /** * The name table. */ private final Name.Table names; /** * Get the ClassWriter instance for this context. */ public static ClassWriter instance(Context context) { ClassWriter instance = (ClassWriter) context.get(classWriterKey); if (instance == null) instance = new ClassWriter(context); return instance; } /** * Construct a class writer, given an options table. */ private ClassWriter(Context context) { super(); context.put(classWriterKey, this); log = Log.instance(context); names = Name.Table.instance(context); syms = Symtab.instance(context); Options options = Options.instance(context); target = Target.instance(context); 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; emitSourceFile = options.get("-g:") == null || options.get("-g:source") != null; String od = (String) options.get("-d"); if (od != null) outDir = new File(od); String dumpModFlags = (String) 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); } /** * 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; private final boolean dumpFieldModifiers; private final boolean dumpInnerClassModifiers; private final boolean dumpMethodModifiers; /** * 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(); } private static final String[] flagName = {"PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL", "SUPER", "VOLATILE", "TRANSIENT", "NATIVE", "INTERFACE", "ABSTRACT", "STRICTFP"}; /** * 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) & 255); buf.elems[op + 1] = (byte)((x) & 255); } /** * 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) & 255); buf.elems[adr + 1] = (byte)((x >> 16) & 255); buf.elems[adr + 2] = (byte)((x >> 8) & 255); buf.elems[adr + 3] = (byte)((x) & 255); } /** * 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: ClassType ct = (ClassType) type; ClassSymbol c = (ClassSymbol) ct.tsym; enterInner(c); if (ct.outer().allparams().nonEmpty()) { assembleSig(ct.outer()); sigbuf.appendByte('.'); } sigbuf.appendByte('L'); sigbuf.appendBytes(externalize(c.flatname)); 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); break; default: assert false : "typeSig" + type.tag; } } void assembleSig(List types) { for (List ts = types; ts.nonEmpty(); ts = ts.tail) assembleSig((Type) ts.head); } /** * Return signature of given type */ Name typeSig(Type type) { assert sigbuf.length == 0; assembleSig(type); Name n = sigbuf.toName(names); sigbuf.reset(); 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(t.erasure()); } else { throw new AssertionError("xClassName"); } } /** * Thrown when the constant pool is over full. */ public static class PoolOverflow extends Exception { public PoolOverflow() { super(); } } public static class StringOverflow extends Exception { public final String value; public StringOverflow(String s) { super(); 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) { poolbuf.appendByte(CONSTANT_Class); poolbuf.appendChar(pool.put(xClassName((Type) value))); } 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -