Reputation: 156
A class file that was compiled with java 1.6 settings has two fields which I need to set to higher values.
private Integer days = 7;
private Integer running = 30;
unfortunately, I don't have access to the code of the correct revision anymore, and only posess the class file.
Here is what I already tried: I've been toying around with BCEL,asm and javassist, but this doesn't seem to be trivial at all. I couldn't find a suitable bytecode editor either (jbe looks really confusing,class editor doesn't show the value of the Integer objects). The Eclipse Bytecode Class file viewer crahes when trying to save. Using a hex editor to manipulate the values is out of the question since they will have more digits than now. I also looked into javap and recompiling it with jasmin - which doesn't seem possible.
So ultimately - please, oh please - does anybody have a good example how this can be done in any imaginable way?
Upvotes: 1
Views: 1867
Reputation: 29646
Using a bytecode editor is extremely easy. Either the field will have an associated DefaultValue attribute or you'll find in ()V something like:
aload_0
bipush 7
invokestatic java/lang/Integer#valueOf (I)Ljava/lang/Integer;
putfield Blah#days Ljava/lang/Integer;
It should be clear what to fix here.
Upvotes: 0
Reputation: 2642
Personally I would us ASMifier (or the Eclipse Bytecode Outline) to produce the java class that when run with java -cp asm-all.jar MyAsmClass
would produce the new version of the necessary class. The values in question have to be updated in all constructors and will be in a visitLdcInsn()
call.
Upvotes: 0
Reputation: 857
You can set them using reflection like the earlier answer points out. Here is an example:
public class TestSetPrivateFields extends TestCase {
public void testSetFields() throws Exception {
Legacy legacyObj = new Legacy();
// get the fields using reflection
Field[] fields = {
legacyObj.getClass().getDeclaredField("days"),
legacyObj.getClass().getDeclaredField("running")
};
for (Field field : fields) {
field.setAccessible(true);
Integer value = (Integer) field.get(legacyObj);
// set their value
field.set(legacyObj, value+1);
}
Legacy expected = new Legacy();
assertEquals(expected.getDays()+1, legacyObj.getDays()+0);
assertEquals(expected.getRunning()+1, legacyObj.getRunning()+0);
}
public static class Legacy {
private Integer days = 7;
private Integer running = 30;
public Integer getDays() {return days;}
public Integer getRunning() { return running;}
}
}
Upvotes: 2
Reputation: 53606
Take a look at JD-Core. The plugin for eclipse allowed me to peek into some undocumented library to help me better understand it. It doesn't work on all compiled java classes, but it pretty much opened everything so far for me.
Upvotes: 0
Reputation: 51955
Have you tried decompiling, editing, then recompiling? As far as I know, JD is working pretty well.
http://java.decompiler.free.fr/
Upvotes: 2