【问题标题】:Why the disassembler plugin doesn't work in this case?为什么反汇编插件在这种情况下不起作用?
【发布时间】:2015-03-05 06:14:05
【问题描述】:

我正在尝试使用此命令在 Test 类下面进行反汇编:

java -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Test.main Test > log.txt


测试类

public class Test {
    static {
        System.out.println("loading Test");
    }
    public static void main(String[] args) {
        Aze a = new Aze(1,2,3);
        Baz b = new Baz();
    }

}

class Aze {
    private String toto ;
    private int titi ;
    private int tata ;

    public Aze(int a, int b, int c) {
        this.toto = "azertyu";
        this.titi = b;
        this.tata = c;
    }
}

class Baz extends Aze {        

    public Baz() {
        super(1,2,3);
    }
}

但结果不包含任何汇编代码:

编译器Oracle:打印 *Test.main Java HotSpot(TM) Client VM 警告:汇编代码打印已启用;打开 DebugNonSafepoints 以获得额外的输出 加载测试

如果我通过添加一些虚拟代码来修改我的主要方法:

        long x = 0;
        for (int i = 0; i < 100000; i++) {
            x += i*i;
        }
        System.out.println("x=" + x);

它突然起作用了,我得到的输出不仅与添加的代码有关。

例如,我发现了这样一条装配线:

0x026f1843: mov    $0x24655510,%edx   ;   {oop("azertyu")}

现在,如果我使用 for (int i = 0; i &lt; 10000; i++) 稍微修改一下 for 循环,我只有结果行 x=333283335000,但根本没有汇编代码。

所以我不明白为什么我无法获取所有程序的汇编代码?

注意:我使用Oracle wiki about PrintAssembly中链接的hsdis-i386.dll

【问题讨论】:

  • 注意:GNU 有一个 Java 编译器(“GCJ”),可以“提前”将 Java 编译为本地汇编器。我自己没有使用过,但也许你有兴趣尝试一下。见gcc.gnu.org/java
  • @geert3 好的,我去看看。

标签: java assembly jvm jit disassembly


【解决方案1】:

只显示“即时编译”的代码,因为那是唯一的汇编程序,其余的是解释的字节码。

对于最初的程序,要做的工作太少以至于什么都没有编译,也就是说,一切都只是解释。你在程序中做的循环和东西越多,编译到汇编器的就越多。

关于编译什么以及何时编译几乎没有(不是?)保证。

您的“azertyu”被组装的原因可能是因为它是“不变的”,优化器在运行for 循环时发现了这一点。

【讨论】:

  • 谢谢您的回答。我在脑海中添加了一些东西,但我仍然觉得它很奇怪。尤其是循环最大索引的东西。基本上它也可以被解释,因为结果永远不会改变。你也知道“强制”编译吗?
  • 不,我不知道如何“强制”它,但一个最低要求是拥有一个运行时间更长的程序。也许一开始的Thread.sleep(5000); 会启动它(还没有尝试过)。经常执行或易于优化的代码也可以更快地编译,例如复杂/长循环,可以内联的小方法调用......
猜你喜欢
  • 2017-11-26
  • 2010-12-29
  • 1970-01-01
  • 2021-08-05
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多