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

发布于 2024-11-05 12:32:41 字数 431 浏览 2 评论 0原文

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

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

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

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

所以最终 - 拜托,哦拜托 - 有没有人有一个很好的例子,如何以任何可以想象的方式做到这一点?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦里°也失望 2024-11-12 12:32:41

您是否尝试过反编译,编辑,然后重新编译?据我所知,京东经营得很好。

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

Have you tried decompiling, editing, then recompiling? As far as I know, JD is working pretty well.

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

梦情居士 2024-11-12 12:32:41

您可以使用反射来设置它们,就像之前的答案指出的那样。这是一个例子:

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

}

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

}
萌无敌 2024-11-12 12:32:41

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

我不会经历所有的痛苦。如果这件事很困难,也许这表明你不应该这样做。

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

I can't imagine why you don't have the source.

I wouldn't go through all that pain. If it's difficult, perhaps it's a sign that you shouldn't do it.

I'd rather use JAD, de-compile the .class file, make my change, and get on with it.

扎心 2024-11-12 12:32:41

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

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.

不打扰别人 2024-11-12 12:32:41

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

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.

海夕 2024-11-12 12:32:41

使用字节码编辑器非常简单。该字段要么具有关联的 DefaultValue 属性,要么您会在 ()V 中找到类似以下内容的内容:

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

应该清楚此处要修复的内容。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文