Reputation: 181
Say I want to take a java class file, disassemble it, tweak the java bytecode output, and then reassemble it again.
I need to rename a symbol in the constant pool table. I also don't have access to the source code, and using a decompiler seems like overkill for this. I'm not trying to optimize anything - java does a fine job at that.
Is there... a simple way to do this? I've found several tools for either disassembly or reassembly, but none for both; or no pairs of tools which seem to use the same format for representing the bytecode in text.
Upvotes: 5
Views: 5058
Reputation: 39451
Krakatau provides an open source disassembler and assembler that make this very easy. Krakatau is designed to be a replacement for Jasmin. It uses a Jasmin like syntax for backwards compatibility but extends the format to support all the obscure features in the classfile format and fix bugs in Jasmin. It also lets you easily disassemble, modify, and reassemble classes.
The only real downside to Krakatau is that it currently doesn't documented very well. But if you have any questions, feel free to ask. (Disclosure: I wrote Krakatau).
Upvotes: 6
Reputation: 302
This question is a bit older now, but as I don't find this answered anywhere on stackoverflow, let me put it on record:
There's the standard jasper/jasmin combo that I have successfully used in the past:
The only annoyance with jasper is that it forgets to create a label for the switch default clause, and then jasmin will give you errors like
Main.j:391: JAS Error Label: LABEL0x48 has not been added to the code.
Which then means you have to go into the .j file, and manually fix it. "javap -c" might assist you there. For that bug I'd suggest you jasper and immediately jasmin, before any modifications, just to make sure that works.
You can actually fix that label bug by applying this patch to jasper:
--- Code_Collection.java.orig 1999-06-14 14:10:44.000000000 +0000
+++ Code_Collection.java 2011-02-05 07:23:21.000000000 +0000
@@ -1210,6 +1210,7 @@
-----------------------------------------------------------------------*/
void getLabel(Code_Collection code) {
for (int i = 0; i < count; i++) code.setLabel(pc+branch[i]);
+ code.setLabel(pc+tableDefault);
}
/*-----------------------------------------------------------------------
I submitted it to the author, but I got a feeling the project has not been worked on for many years, so I don't know if it'll get merged in.
Edit: Jasper with the above patch applied is now available at https://github.com/EugenDueck/Jasper
And then there's Eclipse Bytecode Outline, as described in this answer: java bytecode editor?
Upvotes: 5
Reputation: 5553
Did you check the ASM API?
Here is a code sample (adapted from the official documentation) explaining how to modify a class bytecode:
ClasssWriter cw = new ClassWriter();
ClassAdapter ca = new ClassAdapter(cw); // ca forwards all events to cw
// ca should modify the class data
ClassReader cr = new ClassReader("MyClass");
cr.accept(ca, 0);
byte[] b2 = cw.toByteArray(); // b2 represents the same class as MyClass, modified by ca
Then b2 can be stored in a .class file for future use. You can also use the method ClassLoader.defineClass(String,byte[],int,int)
to load it if you define your own classloader.
Upvotes: 6
Reputation: 12334
You are describing what modern compilers do already. In addition to that, most JVMs can (and try to) keep optimizing the byte code while the app is running.
Start with studying what existing compilers/JVM's are doing with the byte code. The best case is that you can improve on the the JVM's optimizer which is possible but a low probability and either way you may be reinventing the wheel. The worst case is your changes actually interfere with the the runtime optimizer and cause overall performance to go down.
[EDIT] Found a related post: Bytecode manipulation patterns
Upvotes: 0
Reputation: 88796
Wouldn't it just be easier to find the original source code, modify it, then recompile it? Or is this from some binary code you don't have the source to?
Pro tip: The source code to the built-in Java Class Library is available as part of the OpenJDK project, specifically in the OpenJDK 6 Source.
Upvotes: 0