📄 codehtml.java
字号:
package de.fub.bytecode.util;import de.fub.bytecode.classfile.*;import java.io.*;import java.util.BitSet;/** * Convert code into HTML file. * * @version $Id: CodeHTML.java,v 1.2 2001/05/09 09:26:57 dahm Exp $ * @author <A HREF="http://www.berlin.de/~markus.dahm/">M. Dahm</A> * */final class CodeHTML implements de.fub.bytecode.Constants { private String class_name; // name of current class private Method[] methods; // Methods to print private PrintWriter file; // file to write to private BitSet goto_set; private ConstantPool constant_pool; private ConstantHTML constant_html; private static boolean wide=false; CodeHTML(String dir, String class_name, Method[] methods, ConstantPool constant_pool, ConstantHTML constant_html) throws IOException { this.class_name = class_name; this.methods = methods; this.constant_pool = constant_pool; this.constant_html = constant_html; file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html")); file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\">"); for(int i=0; i < methods.length; i++) writeMethod(methods[i], i); file.println("</BODY></HTML>"); file.close(); } /** * Disassemble a stream of byte codes and return the * string representation. * * @param stream data input stream * @return String representation of byte code */ private final String codeToHTML(ByteSequence bytes, int method_number) throws IOException { short opcode = (short)bytes.readUnsignedByte(); StringBuffer buf; String name, sig, signature; int default_offset=0, low, high; int index, class_index, vindex, constant; int[] jump_table; int no_pad_bytes=0, offset; buf = new StringBuffer("<TT>" + OPCODE_NAMES[opcode] + "</TT></TD><TD>"); /* Special case: Skip (0-3) padding bytes, i.e., the * following bytes are 4-byte-aligned */ if((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) { int remainder = bytes.getIndex() % 4; no_pad_bytes = (remainder == 0)? 0 : 4 - remainder; for(int i=0; i < no_pad_bytes; i++) bytes.readByte(); // Both cases have a field default_offset in common default_offset = bytes.readInt(); } switch(opcode) { case TABLESWITCH: low = bytes.readInt(); high = bytes.readInt(); offset = bytes.getIndex() - 12 - no_pad_bytes - 1; default_offset += offset; buf.append("<TABLE BORDER=1><TR>"); // Print switch indices in first row (and default) jump_table = new int[high - low + 1]; for(int i=0; i < jump_table.length; i++) { jump_table[i] = offset + bytes.readInt(); buf.append("<TH>" + (low + i) + "</TH>"); } buf.append("<TH>default</TH></TR>\n<TR>"); // Print target and default indices in second row for(int i=0; i < jump_table.length; i++) buf.append("<TD><A HREF=\"#code" + method_number + "@" + jump_table[i] + "\">" + jump_table[i] + "</A></TD>"); buf.append("<TD><A HREF=\"#code" + method_number + "@" + default_offset + "\">" + default_offset + "</A></TD></TR>\n</TABLE>\n"); break; /* Lookup switch has variable length arguments. */ case LOOKUPSWITCH: int npairs = bytes.readInt(); offset = bytes.getIndex() - 8 - no_pad_bytes - 1; jump_table = new int[npairs]; default_offset += offset; buf.append("<TABLE BORDER=1><TR>"); // Print switch indices in first row (and default) for(int i=0; i < npairs; i++) { int match = bytes.readInt(); jump_table[i] = offset + bytes.readInt(); buf.append("<TH>" + match + "</TH>"); } buf.append("<TH>default</TH></TR>\n<TR>"); // Print target and default indices in second row for(int i=0; i < npairs; i++) buf.append("<TD><A HREF=\"#code" + method_number + "@" + jump_table[i] + "\">" + jump_table[i] + "</A></TD>"); buf.append("<TD><A HREF=\"#code" + method_number + "@" + default_offset + "\">" + default_offset + "</A></TD></TR>\n</TABLE>\n"); break; /* Two address bytes + offset from start of byte stream form the * jump target. */ case GOTO: case IFEQ: case IFGE: case IFGT: case IFLE: case IFLT: case IFNE: case IFNONNULL: case IFNULL: case IF_ACMPEQ: case IF_ACMPNE: case IF_ICMPEQ: case IF_ICMPGE: case IF_ICMPGT: case IF_ICMPLE: case IF_ICMPLT: case IF_ICMPNE: case JSR: index = (int)(bytes.getIndex() + bytes.readShort() - 1); buf.append("<A HREF=\"#code" + method_number + "@" + index + "\">" + index + "</A>"); break; /* Same for 32-bit wide jumps */ case GOTO_W: case JSR_W: int windex = bytes.getIndex() + bytes.readInt() - 1; buf.append("<A HREF=\"#code" + method_number + "@" + windex + "\">" + windex + "</A>"); break; /* Index byte references local variable (register) */ case ALOAD: case ASTORE: case DLOAD: case DSTORE: case FLOAD: case FSTORE: case ILOAD: case ISTORE: case LLOAD: case LSTORE: case RET: if(wide) { vindex = bytes.readShort(); wide=false; // Clear flag } else vindex = bytes.readUnsignedByte(); buf.append("%" + vindex); break; /* * Remember wide byte which is used to form a 16-bit address in the * following instruction. Relies on that the method is called again with * the following opcode. */ case WIDE: wide = true; buf.append("(wide)"); break; /* Array of basic type. */ case NEWARRAY: buf.append("<FONT COLOR=\"#00FF00\">" + TYPE_NAMES[bytes.readByte()] + "</FONT>"); break; /* Access object/class fields. */ case GETFIELD: case GETSTATIC: case PUTFIELD: case PUTSTATIC: index = bytes.readShort(); ConstantFieldref c1 = (ConstantFieldref)constant_pool.getConstant(index, CONSTANT_Fieldref); class_index = c1.getClassIndex(); name = constant_pool.getConstantString(class_index, CONSTANT_Class); name = Utility.compactClassName(name, false); index = c1.getNameAndTypeIndex(); String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType); if(name.equals(class_name)) { // Local field buf.append("<A HREF=\"" + class_name + "_methods.html#field" + field_name + "\" TARGET=Methods>" + field_name + "</A>\n"); } else buf.append(constant_html.referenceConstant(class_index) + "." + field_name); break; /* Operands are references to classes in constant pool */ case CHECKCAST: case INSTANCEOF: case NEW: index = bytes.readShort(); buf.append(constant_html.referenceConstant(index)); break; /* Operands are references to methods in constant pool */ case INVOKESPECIAL: case INVOKESTATIC: case INVOKEVIRTUAL: case INVOKEINTERFACE: int m_index = bytes.readShort(); String str; if(opcode == INVOKEINTERFACE) { // Special treatment needed int nargs = bytes.readUnsignedByte(); // Redundant int reserved = bytes.readUnsignedByte(); // Reserved ConstantInterfaceMethodref c=(ConstantInterfaceMethodref)constant_pool.getConstant(m_index, CONSTANT_InterfaceMethodref); class_index = c.getClassIndex(); str = constant_pool.constantToString(c); index = c.getNameAndTypeIndex(); } else { ConstantMethodref c = (ConstantMethodref)constant_pool.getConstant(m_index, CONSTANT_Methodref); class_index = c.getClassIndex(); str = constant_pool.constantToString(c); index = c.getNameAndTypeIndex(); } name = Class2HTML.referenceClass(class_index); str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant(index, CONSTANT_NameAndType))); // Get signature, i.e., types ConstantNameAndType c2 = (ConstantNameAndType)constant_pool. getConstant(index, CONSTANT_NameAndType); signature = constant_pool.constantToString(c2.getSignatureIndex(), CONSTANT_Utf8); String[] args = Utility.methodSignatureArgumentTypes(signature, false); String type = Utility.methodSignatureReturnType(signature, false); buf.append(name + ".<A HREF=\"" + class_name + "_cp.html#cp" + m_index + "\" TARGET=ConstantPool>" + str + "</A>" + "("); // List arguments for(int i=0; i < args.length; i++) { buf.append(Class2HTML.referenceType(args[i])); if(i < args.length - 1) buf.append(", "); } // Attach return type buf.append("):" + Class2HTML.referenceType(type)); break; /* Operands are references to items in constant pool */ case LDC_W: case LDC2_W: index = bytes.readShort(); buf.append("<A HREF=\"" + class_name + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">" + Class2HTML.toHTML(constant_pool.constantToString(index, constant_pool. getConstant(index).getTag()))+ "</a>"); break; case LDC: index = bytes.readUnsignedByte(); buf.append("<A HREF=\"" + class_name + "_cp.html#cp" + index + "\" TARGET=\"ConstantPool\">" + Class2HTML.toHTML(constant_pool.constantToString(index, constant_pool. getConstant(index).getTag()))+ "</a>");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -