📄 classwriter.java
字号:
return sym.name;
}
/**
* Given a symbol, return its name-and-type.
*/
NameAndType nameType(Symbol sym) {
return new NameAndType(fieldName(sym),
retrofit ? sym.erasure() : sym.externalType());
}
/**
* 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 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 & SYNTHETIC) != 0) {
int alenIdx = writeAttr(names.Synthetic);
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());
return acount;
}
/**
* Enter an inner class into the `innerClasses' set/queue.
*/
void enterInner(ClassSymbol c) {
assert (c.flags() & COMPOUND) == 0;
if (c.type.tag != CLASS)
return;
if (pool != null && c.owner.kind != PCK &&
(innerClasses == null || !innerClasses.contains(c))) {
if (c.owner.kind == TYP)
enterInner((ClassSymbol) c.owner);
pool.put(c);
pool.put(c.name);
if (innerClasses == null) {
innerClasses = Set.make();
innerClassesQueue = new ListBuffer();
pool.put(names.InnerClasses);
}
innerClasses.put(c);
innerClassesQueue.append(c);
}
}
/**
* Write "inner classes" attribute.
*/
void writeInnerClasses() {
int alenIdx = writeAttr(names.InnerClasses);
databuf.appendChar(innerClassesQueue.length());
for (List l = innerClassesQueue.toList(); l.nonEmpty(); l = l.tail) {
ClassSymbol inner = (ClassSymbol) l.head;
if (dumpInnerClassModifiers) {
log.errWriter.println("INNERCLASS " + inner.name);
log.errWriter.println("---" + flagNames(inner.flags_field));
}
databuf.appendChar(pool.get(inner));
databuf.appendChar(inner.owner.kind == TYP ? pool.get(inner.owner) : 0);
databuf.appendChar(inner.name.len != 0 ? pool.get(inner.name) : 0);
databuf.appendChar((int) inner.flags_field);
}
endAttr(alenIdx);
}
/**
* Write field symbol, entering all references into constant pool.
*/
void writeField(VarSymbol v) {
databuf.appendChar((int) v.flags());
if (dumpFieldModifiers) {
log.errWriter.println("FIELD " + fieldName(v));
log.errWriter.println("---" + flagNames(v.flags()));
}
databuf.appendChar(pool.put(fieldName(v)));
databuf.appendChar(pool.put(typeSig(v.erasure())));
int acountIdx = beginAttrs();
int acount = 0;
if (v.constValue != null) {
int alenIdx = writeAttr(names.ConstantValue);
databuf.appendChar(pool.put(v.constValue));
endAttr(alenIdx);
acount++;
}
acount += writeMemberAttrs(v);
endAttrs(acountIdx, acount);
}
/**
* Write method symbol, entering all references into constant pool.
*/
void writeMethod(MethodSymbol m) {
databuf.appendChar((int) m.flags());
if (dumpMethodModifiers) {
log.errWriter.println("METHOD " + fieldName(m));
log.errWriter.println("---" + flagNames(m.flags()));
}
databuf.appendChar(pool.put(fieldName(m)));
databuf.appendChar(pool.put(typeSig(m.externalType())));
int acountIdx = beginAttrs();
int acount = 0;
if (m.code != null) {
int alenIdx = writeAttr(names.Code);
writeCode(m.code);
m.code = null;
endAttr(alenIdx);
acount++;
}
List thrown = m.erasure().thrown();
if (thrown.nonEmpty()) {
int alenIdx = writeAttr(names.Exceptions);
databuf.appendChar(thrown.length());
for (List l = thrown; l.nonEmpty(); l = l.tail)
databuf.appendChar(pool.put(((Type) l.head).tsym));
endAttr(alenIdx);
acount++;
}
acount += writeMemberAttrs(m);
endAttrs(acountIdx, acount);
}
/**
* Write code attribute of method.
*/
void writeCode(Code code) {
databuf.appendChar(code.max_stack);
databuf.appendChar(code.max_locals);
databuf.appendInt(code.cp);
databuf.appendBytes(code.code, 0, code.cp);
databuf.appendChar(code.catchInfo.length());
for (List l = code.catchInfo.toList(); l.nonEmpty(); l = l.tail) {
for (int i = 0; i < ((char[]) l.head).length; i++)
databuf.appendChar(((char[]) l.head)[i]);
}
int acountIdx = beginAttrs();
int acount = 0;
if (code.lineInfo.nonEmpty()) {
int alenIdx = writeAttr(names.LineNumberTable);
databuf.appendChar(code.lineInfo.length());
for (List l = code.lineInfo.reverse(); l.nonEmpty(); l = l.tail)
for (int i = 0; i < ((char[]) l.head).length; i++)
databuf.appendChar(((char[]) l.head)[i]);
endAttr(alenIdx);
acount++;
}
if (genCrt && (code.crt != null)) {
CRTable crt = code.crt;
int alenIdx = writeAttr(names.CharacterRangeTable);
int crtIdx = beginAttrs();
int crtEntries = crt.writeCRT(databuf);
endAttrs(crtIdx, crtEntries);
endAttr(alenIdx);
acount++;
}
if (code.varBufferSize > 0) {
int alenIdx = writeAttr(names.LocalVariableTable);
int nvars = code.varBufferSize;
databuf.appendChar(nvars);
for (int i = 0; i < nvars; i++) {
Code.LocalVar var = code.varBuffer[i];
assert var.start_pc >= 0;
assert var.start_pc <= code.cp;
databuf.appendChar(var.start_pc);
assert var.length >= 0;
assert (var.start_pc + var.length) <= code.cp;
databuf.appendChar(var.length);
VarSymbol sym = var.var;
databuf.appendChar(pool.put(sym.name));
databuf.appendChar(pool.put(typeSig(sym.erasure())));
databuf.appendChar(var.reg);
}
endAttr(alenIdx);
acount++;
}
endAttrs(acountIdx, acount);
}
void writeFields(Scope.Entry e) {
List vars = List.make();
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((VarSymbol) vars.head);
vars = vars.tail;
}
}
void writeMethods(Scope.Entry e) {
List methods = List.make();
for (Scope.Entry i = e; i != null; i = i.sibling) {
if (i.sym.kind == MTH)
methods = methods.prepend((MethodSymbol) i.sym);
}
while (methods.nonEmpty()) {
writeMethod((MethodSymbol) 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 void writeClass(ClassSymbol c) throws IOException, PoolOverflow,
StringOverflow {
File outFile = outputFile(c, ".class");
OutputStream out = new FileOutputStream(outFile);
try {
writeClassFile(out, c);
if (verbose)
log.errWriter.println( log.getLocalizedString("verbose.wrote.file",
outFile.getPath()));
out.close();
out = null;
}
finally { if (out != null) {
out.close();
outFile.delete();
out = null;
}
} }
/**
* 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 = c.type.supertype();
List interfaces = c.type.interfaces();
long flags = c.flags();
if ((flags & PROTECTED) != 0)
flags |= PUBLIC;
flags = flags & ClassFlags & ~STRICTFP;
if ((flags & INTERFACE) == 0)
flags |= ACC_SUPER;
if (dumpClassModifiers) {
log.errWriter.println();
log.errWriter.println("CLASSFILE " + c.fullName());
log.errWriter.println("---" + flagNames(flags));
}
databuf.appendChar((int) flags);
databuf.appendChar(pool.put(c));
databuf.appendChar(supertype.tag == CLASS ? pool.put(supertype.tsym) : 0);
databuf.appendChar(interfaces.length());
for (List l = interfaces; l.nonEmpty(); l = l.tail)
databuf.appendChar(pool.put(((Type) 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:
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;
if (c.sourcefile != null && emitSourceFile) {
int alenIdx = writeAttr(names.SourceFile);
String filename = c.sourcefile.toString();
int sepIdx = filename.lastIndexOf(File.separatorChar);
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) {
int alenIdx = writeAttr(names.SourceID);
databuf.appendChar( c.pool.put(
names.fromString(Long.toString(getLastModified(c.sourcefile)))));
endAttr(alenIdx);
acount++;
alenIdx = writeAttr(names.CompilationID);
databuf.appendChar( c.pool.put(
names.fromString(Long.toString(System.currentTimeMillis()))));
endAttr(alenIdx);
acount++;
}
acount += writeFlagAttrs(c.flags());
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;
}
/**
* Get modification date of file entry with name filename
*/
long getLastModified(Name filename) {
long mod = 0;
File file = new File(filename.toString());
try {
mod = file.lastModified();
} catch (SecurityException e) {
throw new AssertionError(
"CRT: couldn\'t get source file modification date: " +
e.getMessage());
}
return mod;
}
/**
* Create output file with given extension for given class.
*/
public File outputFile(ClassSymbol c, String extension) throws IOException {
if (outDir == null) {
String filename = Convert.shortName(c.flatname) + extension;
if (c.sourcefile == null)
return new File(filename);
String sourcedir = new File(c.sourcefile.toString()).getParent();
if (sourcedir == null)
return new File(filename);
else
return new File(sourcedir, filename);
} else {
return outputFile(outDir, c.flatname.toString(), extension);
}
}
/**
* open file given by a fully qualified name from root directory `outdir'.
* create intermediate directories if they don't exist already
*/
File outputFile(File outdir, String name, String extension) throws IOException {
int start = 0;
int end = name.indexOf('.');
while (end >= start) {
outdir = new File(outdir, name.substring(start, end));
if (!outdir.exists())
outdir.mkdir();
start = end + 1;
end = name.indexOf('.', start);
}
return new File(outdir, name.substring(start) + extension);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -