如何将 -XX:UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项与 JVM HotSpot 一起使用

发布于 2025-01-07 00:35:08 字数 505 浏览 0 评论 0原文

我正在尝试使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod 命令行,如 这篇文章

看来它可以通过 open-jdk (https://wikis. oracle.com/display/HotSpotInternals/PrintAssembly)。

如何将这些选项(或类似的选项)与 oracle JDK7 和 JVM HotSpot 结合使用?

I 'm trying to use -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod command lines as described in this post.

It seems thats it's available with open-jdk (https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly).

How can I use those options (or similar equivalents) with oracle JDK7 and the JVM HotSpot?

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

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

发布评论

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

评论(2

贱贱哒 2025-01-14 00:35:08

这些说明适用于 Linux (Ubuntu 10.04.4 LTS),但也应适用于您的操作系统。下载 Oracle JDK 7u3 并正确安装后设置您的 JAVA_HOMEPATH 环境变量,执行以下命令来检查可用选项:

java -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version

您应该看到UnlockDiagnosticVMOptionsCompileCommandPrintAssembly 选项可用。使用CompileCommand选项还将启用PrintAssembly选项。但是,您需要 HotSpot 反汇编器插件才能使 PrintAssembly 正常工作;如果没有它,您可能会看到类似以下内容:

$ java -version
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) Server VM (build 22.1-b02, mixed mode)
$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main
CompilerOracle: print *Main.main
Java HotSpot(TM) Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c2)      68    1 %           Main::main @ 4 (49 bytes)
 total in heap  [0xb3a97548,0xb3a979ec] = 1188
 relocation     [0xb3a97610,0xb3a97624] = 20
 main code      [0xb3a97640,0xb3a97840] = 512
 stub code      [0xb3a97840,0xb3a97850] = 16
 oops           [0xb3a97850,0xb3a97858] = 8
 scopes data    [0xb3a97858,0xb3a97898] = 64
 scopes pcs     [0xb3a97898,0xb3a979e8] = 336
 dependencies   [0xb3a979e8,0xb3a979ec] = 4
Could not load hsdis-i386.so; library not loadable; PrintAssembly is disabled
OopMapSet contains 1 OopMaps

要获取 HotSpot 反汇编器插件,您需要构建它。查看 OpenJDK 7u2 源代码, hsdis 插件自述文件 说:

要在 JVM 中使用该插件,您需要一个可以加载它的新版本。
如果您的 JVM 的产品模式不接受 -XX:+PrintAssembly,
您没有足够新的版本。

要构建此项目,您[需要]一份 GNU binutils 的副本来构建。

从理论上讲,这应该可以在 Windows 上构建,但要获得工作
事实证明,Windows 上的 GNU 构建环境很困难。

上面我们已经确认Oracle JDK 7u3支持PrintAssembly。我按照 hsdis 插件自述文件说明,下载了 GNU binutils 2.22,将其放在 hsdis build/binutils 目录中并运行 make。这最终产生了以下错误:

hsdis.c:32:20: error: sysdep.h: No such file or directory

为了纠正这个问题,我使用以下补丁更改了 hsdis.c:

diff -r 6259c6d3bbb7 src/share/tools/hsdis/hsdis.c
--- a/src/share/tools/hsdis/hsdis.c Mon Dec 12 23:08:01 2011 -0800
+++ b/src/share/tools/hsdis/hsdis.c Thu Feb 23 09:26:37 2012 -0500
@@ -29,7 +29,7 @@

 #include "hsdis.h"

-#include <sysdep.h>
+#include <errno.h>
 #include <libiberty.h>
 #include <bfd.h>
 #include <dis-asm.h>

然后成功运行 make 。现在只需将 hsdis build 目录中的 hsdis-i386.so 插件复制到 Oracle JDK 7u3 jre/lib/i386 目录即可。

现在您可以看到反汇编的编译代码:

$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main
CompilerOracle: print *Main.main
Java HotSpot(TM) Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c2)      68    1 %           Main::main @ 4 (49 bytes)
 total in heap  [0xb3999548,0xb39999ec] = 1188
 relocation     [0xb3999610,0xb3999624] = 20
 main code      [0xb3999640,0xb3999840] = 512
 stub code      [0xb3999840,0xb3999850] = 16
 oops           [0xb3999850,0xb3999858] = 8
 scopes data    [0xb3999858,0xb3999898] = 64
 scopes pcs     [0xb3999898,0xb39999e8] = 336
 dependencies   [0xb39999e8,0xb39999ec] = 4
Loaded disassembler from [snip]/jdk1.7.0_03/jre/lib/i386/hsdis-i386.so
Decoding compiled method 0xb3999548:
Code:
[Disassembling for mach='i386']
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'main' '([Ljava/lang/String;)V' in 'Main'
  0xb3999640: call   0xb6ff8510         ;   {runtime_call}
  0xb3999645: data32 xchg %ax,%ax
  0xb3999648: mov    %eax,-0x3000(%esp)
  0xb399964f: push   %ebp
  0xb3999650: sub    $0x38,%esp
  0xb3999656: mov    %ecx,%esi
  0xb3999658: mov    0x4(%esi),%ebp
  0xb399965b: mov    0x8(%esi),%edi
  0xb399965e: mov    (%ecx),%esi
  0xb3999660: mov    %ecx,(%esp)
  0xb3999663: call   0xb7078cf0         ;*iload_3
[snip]
  0xb399983e: hlt    
  0xb399983f: hlt    
[Exception Handler]
[Stub Code]
  0xb3999840: jmp    0xb39981e0         ;   {no_reloc}
[Deopt Handler Code]
  0xb3999845: push   $0xb3999845        ;   {section_word}
  0xb399984a: jmp    0xb397e220         ;   {runtime_call}
  0xb399984f: .byte 0x0
OopMapSet contains 1 OopMaps

#0 
OopMap{off=468}

我使用的测试类是:

public class Main {
    public static void main(final String[] args) {
        long x = 0;
        for (int i = 0; i < 1000000; i++) {
            x += calculate(i);
        }
        System.out.println("x=" + x);
    }

    private static long calculate(final int i) {
        return (long)i * (long)i;
    }
}

These instructions apply to Linux (Ubuntu 10.04.4 LTS), but should be applicable for your OS. After downloading Oracle JDK 7u3 and appropriately setting your JAVA_HOME and PATH environment variables, execute the following to check available options:

java -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version

You should see the UnlockDiagnosticVMOptions, CompileCommand and PrintAssembly options are available. Using the CompileCommand option will also enable the PrintAssembly option. However, you will need the HotSpot disassembler plugin for PrintAssembly to work; without it, you might see something like the following:

$ java -version
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) Server VM (build 22.1-b02, mixed mode)
$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main
CompilerOracle: print *Main.main
Java HotSpot(TM) Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c2)      68    1 %           Main::main @ 4 (49 bytes)
 total in heap  [0xb3a97548,0xb3a979ec] = 1188
 relocation     [0xb3a97610,0xb3a97624] = 20
 main code      [0xb3a97640,0xb3a97840] = 512
 stub code      [0xb3a97840,0xb3a97850] = 16
 oops           [0xb3a97850,0xb3a97858] = 8
 scopes data    [0xb3a97858,0xb3a97898] = 64
 scopes pcs     [0xb3a97898,0xb3a979e8] = 336
 dependencies   [0xb3a979e8,0xb3a979ec] = 4
Could not load hsdis-i386.so; library not loadable; PrintAssembly is disabled
OopMapSet contains 1 OopMaps

To get the HotSpot disassembler plugin, you will need to build it. Looking at the OpenJDK 7u2 source, the hsdis plugin readme says:

To use the plugin with a JVM, you need a new version that can load it.
If the product mode of your JVM does not accept -XX:+PrintAssembly,
you do not have a version that is new enough.

To build this project you [need] a copy of GNU binutils to build against.

In theory this should be buildable on Windows but getting a working
GNU build environment on Windows has proven difficult.

We have confirmed above that Oracle JDK 7u3 supports PrintAssembly. I followed the hsdis plugin readme instructions, downloaded GNU binutils 2.22, placed it in the hsdis build/binutils directory and ran make. This eventually produced the following error:

hsdis.c:32:20: error: sysdep.h: No such file or directory

To correct this, I changed hsdis.c using the following patch:

diff -r 6259c6d3bbb7 src/share/tools/hsdis/hsdis.c
--- a/src/share/tools/hsdis/hsdis.c Mon Dec 12 23:08:01 2011 -0800
+++ b/src/share/tools/hsdis/hsdis.c Thu Feb 23 09:26:37 2012 -0500
@@ -29,7 +29,7 @@

 #include "hsdis.h"

-#include <sysdep.h>
+#include <errno.h>
 #include <libiberty.h>
 #include <bfd.h>
 #include <dis-asm.h>

Running make was then successful. Now just copy the hsdis-i386.so plugin in the hsdis build directory to the Oracle JDK 7u3 jre/lib/i386 directory.

Now you can see the disassembled compiled code:

$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main
CompilerOracle: print *Main.main
Java HotSpot(TM) Server VM warning: printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output
Compiled method (c2)      68    1 %           Main::main @ 4 (49 bytes)
 total in heap  [0xb3999548,0xb39999ec] = 1188
 relocation     [0xb3999610,0xb3999624] = 20
 main code      [0xb3999640,0xb3999840] = 512
 stub code      [0xb3999840,0xb3999850] = 16
 oops           [0xb3999850,0xb3999858] = 8
 scopes data    [0xb3999858,0xb3999898] = 64
 scopes pcs     [0xb3999898,0xb39999e8] = 336
 dependencies   [0xb39999e8,0xb39999ec] = 4
Loaded disassembler from [snip]/jdk1.7.0_03/jre/lib/i386/hsdis-i386.so
Decoding compiled method 0xb3999548:
Code:
[Disassembling for mach='i386']
[Entry Point]
[Verified Entry Point]
[Constants]
  # {method} 'main' '([Ljava/lang/String;)V' in 'Main'
  0xb3999640: call   0xb6ff8510         ;   {runtime_call}
  0xb3999645: data32 xchg %ax,%ax
  0xb3999648: mov    %eax,-0x3000(%esp)
  0xb399964f: push   %ebp
  0xb3999650: sub    $0x38,%esp
  0xb3999656: mov    %ecx,%esi
  0xb3999658: mov    0x4(%esi),%ebp
  0xb399965b: mov    0x8(%esi),%edi
  0xb399965e: mov    (%ecx),%esi
  0xb3999660: mov    %ecx,(%esp)
  0xb3999663: call   0xb7078cf0         ;*iload_3
[snip]
  0xb399983e: hlt    
  0xb399983f: hlt    
[Exception Handler]
[Stub Code]
  0xb3999840: jmp    0xb39981e0         ;   {no_reloc}
[Deopt Handler Code]
  0xb3999845: push   $0xb3999845        ;   {section_word}
  0xb399984a: jmp    0xb397e220         ;   {runtime_call}
  0xb399984f: .byte 0x0
OopMapSet contains 1 OopMaps

#0 
OopMap{off=468}

The test class I've used is:

public class Main {
    public static void main(final String[] args) {
        long x = 0;
        for (int i = 0; i < 1000000; i++) {
            x += calculate(i);
        }
        System.out.println("x=" + x);
    }

    private static long calculate(final int i) {
        return (long)i * (long)i;
    }
}
执着的年纪 2025-01-14 00:35:08

就我而言,查看反汇编的编译代码:

$ java -XX:CompileThreshold=1 -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand="compileonly pac/kage/MyClass myMethod" MyClass

在上面的示例中,有一个循环: for (int i = 0; i < 1 000 000; i++) {...},
这就是为什么在没有 1 000 000 次迭代的情况下,我们需要 -XX:CompileThreshold=1 选项(-server 默认为 10 000)来查看反汇编的编译代码。

in my case to see the disassembled compiled code:

$ java -XX:CompileThreshold=1 -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand="compileonly pac/kage/MyClass myMethod" MyClass

in example above has is cycle: for (int i = 0; i < 1 000 000; i++) {...},
that is why in our case without 1 000 000 iterations we need -XX:CompileThreshold=1 option (by default 10 000 for -server) to see our disassembled compiled code.

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