This repository has been archived by the owner on Aug 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Disassembly
Brian S. O'Neill edited this page Jun 2, 2013
·
2 revisions
A
private static java.util.Map cPropertiesCache; static { // max stack: 2 // max locals: 0 // line 35 new org.cojen.util.WeakIdentityMap dup invokespecial void org.cojen.util.WeakIdentityMap.<init>() putstatic java.util.Map org.cojen.util.BeanIntrospector.cPropertiesCache return } public static void main(java.lang.String[]) throws java.lang.Exception { // max stack: 3 // max locals: 1 // line 38 getstatic java.io.PrintStream java.lang.System.out aload_0 iconst_0 aaload invokestatic java.lang.Class java.lang.Class.forName(java.lang.String) invokestatic java.util.Map org.cojen.util.BeanIntrospector.getAllProperties(java.lang.Class) invokevirtual void java.io.PrintStream.println(java.lang.Object) // line 39 return } ... }
When disassembled using the builder format, a valid Java source file is generated which when compiled and run, rebuilds the original class. This demonstrates how to use Cojen, and it also allows Java classes to be modified when source code is not available.
Even if the generated class file builder is run without modification, the emitted class file will likely produce a different binary representation than the original class. This is because Cojen re-orders the class constant pool and reduces local variable usage.
java org.cojen.classfile.DisassemblyTool -f builder org.cojen.util.BeanIntrospector
import org.cojen.classfile.ClassFile; import org.cojen.classfile.CodeBuilder; import org.cojen.classfile.FieldInfo; import org.cojen.classfile.Label; import org.cojen.classfile.LocalVariable; import org.cojen.classfile.Location; import org.cojen.classfile.MethodInfo; import org.cojen.classfile.Modifiers; import org.cojen.classfile.Opcode; import org.cojen.classfile.TypeDesc; /** * Builds ClassFile for org.cojen.util.BeanIntrospector * * @author auto-generated */ public class ClassFileBuilder { public static void main(String[] args) throws Exception { // public class org.cojen.util.BeanIntrospector ClassFile cf = createClassFile(); if (args.length > 0) { File file = new File(args[0]); if (file.isDirectory()) { writeClassFiles(cf, file); } else { OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); cf.writeTo(out); out.close(); } } } private static void writeClassFiles(ClassFile cf, File dir) throws Exception { File file = new File(dir, cf.getClassName().replace('.', '/') + ".class"); file.getParentFile().mkdirs(); OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); cf.writeTo(out); out.close(); ClassFile[] innerClasses = cf.getInnerClasses(); for (int i=0; i<innerClasses.length; i++) { writeClassFiles(innerClasses[i], dir); } } public static ClassFile createClassFile() { ClassFile cf = new ClassFile("org.cojen.util.BeanIntrospector", "java.lang.Object"); cf.setTarget("1.0"); cf.setSourceFile("BeanIntrospector.java"); createStaticInitializer(cf); // // Create fields // cf.addField(Modifiers.PRIVATE.toStatic(true), "cPropertiesCache", TypeDesc.forClass("java.util.Map")); FieldInfo fi = cf.addField(Modifiers.NONE.toStatic(true), "class$java$lang$Object", TypeDesc.forClass("java.lang.Class")); fi.markSynthetic(); // // Create constructors // // public void <init>() createConstructor_1(cf); // // Create methods // // public static void main(java.lang.String[]) createMethod_1(cf); // public static java.util.Map getAllProperties(java.lang.Class) createMethod_2(cf); ... return cf; } private static void createStaticInitializer(ClassFile cf) { MethodInfo mi = cf.addInitializer(); CodeBuilder b = new CodeBuilder(mi); b.mapLineNumber(35); TypeDesc type_1 = TypeDesc.forClass("org.cojen.util.WeakIdentityMap"); b.newObject(type_1); b.dup(); b.invokeConstructor("org.cojen.util.WeakIdentityMap", null); TypeDesc type_2 = TypeDesc.forClass("java.util.Map"); b.storeStaticField("cPropertiesCache", type_2); b.returnVoid(); } // public void <init>() private static void createConstructor_1(ClassFile cf) { MethodInfo mi = cf.addConstructor(Modifiers.PUBLIC, null); CodeBuilder b = new CodeBuilder(mi); b.mapLineNumber(33); b.loadThis(); b.invokeSuperConstructor(null); b.mapLineNumber(307); b.returnVoid(); } // public static void main(java.lang.String[]) private static void createMethod_1(ClassFile cf) { MethodInfo mi = cf.addMethod(Modifiers.PUBLIC_STATIC, "main", null, new TypeDesc[] {TypeDesc.STRING.toArrayType()}); mi.addException(TypeDesc.forClass("java.lang.Exception")); CodeBuilder b = new CodeBuilder(mi); LocalVariable var_1 = b.getParameter(0); b.mapLineNumber(38); TypeDesc type_1 = TypeDesc.forClass("java.io.PrintStream"); b.loadStaticField("java.lang.System", "out", type_1); b.loadLocal(var_1); b.loadConstant(0); b.loadFromArray(TypeDesc.OBJECT); TypeDesc type_2 = TypeDesc.forClass("java.lang.Class"); TypeDesc[] params_1 = new TypeDesc[] {TypeDesc.STRING}; b.invokeStatic("java.lang.Class", "forName", type_2, params_1); TypeDesc type_3 = TypeDesc.forClass("java.util.Map"); TypeDesc[] params_2 = new TypeDesc[] {type_2}; b.invokeStatic("getAllProperties", type_3, params_2); TypeDesc[] params_3 = new TypeDesc[] {TypeDesc.OBJECT}; b.invokeVirtual("java.io.PrintStream", "println", null, params_3); b.mapLineNumber(39); b.returnVoid(); } ... }