在没有源的情况下更改已编译的1.6 Java类中的整数字段的最佳方法

时间:2011-05-05 23:31:04

标签: java jvm bytecode decompiling bytecode-manipulation

使用java 1.6设置编译的类文件有两个字段,我需要将其设置为更高的值。

private Integer days = 7;
private Integer running = 30;

不幸的是,我无法访问正确版本的代码,只能使用类文件。

这是我已经尝试过的:我一直在玩BCEL,asm和javassist,但这似乎并不是微不足道的。我找不到合适的字节码编辑器(jbe看起来真的很混乱,类编辑器没有显示Integer对象的值)。尝试保存时,Eclipse Bytecode类文件查看器会出现问题。使用十六进制编辑器来操作值是不可能的,因为它们将具有比现在更多的数字。我也查看了javap并用jasmin重新编译它 - 这似乎不可能。

所以最终 - 拜托,拜托,哦 - 有没有人能够以一种可以想象的方式做到这一点?

7 个答案:

答案 0 :(得分:2)

您是否尝试过反编译,编辑,然后重新编译?据我所知,JD工作得很好。

http://java.decompiler.free.fr/

答案 1 :(得分:2)

您可以像前面的答案一样使用反射设置它们。这是一个例子:

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;}
    }

}

答案 2 :(得分:0)

我无法想象为什么你没有这个来源。

我不会经历那么多痛苦。如果这很困难,也许这表明你不应该这样做。

我宁愿使用JAD,对.class文件进行反编译,进行更改,然后继续使用它。

答案 3 :(得分:0)

这看起来很有希望:

http://classeditor.sourceforge.net/

答案 4 :(得分:0)

看看JD-Core。 eclipse的插件允许我查看一些未记录的库,以帮助我更好地理解它。它不适用于所有已编译的java类,但它几乎为我打开了所有内容。

答案 5 :(得分:0)

就个人而言,我希望我们ASMifier(或Eclipse Bytecode Outline)生成java类,当使用java -cp asm-all.jar MyAsmClass运行时,它将产生必要类的新版本。有问题的值必须在所有构造函数中更新,并且将在visitLdcInsn()调用中。

答案 6 :(得分:0)

使用字节码编辑器非常简单。该字段将具有关联的DefaultValue属性,或者您将在()V中找到类似于:

的字段
aload_0
bipush 7
invokestatic java/lang/Integer#valueOf (I)Ljava/lang/Integer;
putfield Blah#days Ljava/lang/Integer;

应该清楚这里要解决的问题。