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