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