如何在 JVM HotSpot 中使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项

How to use -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print option with JVM HotSpot(如何在 JVM HotSpot 中使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项)

本文介绍了如何在 JVM HotSpot 中使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod 命令行questions/9336704/jvm-option-to-optimize-loop-statements#answer-9337542">这篇文章.

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

如何在 oracle JDK7 和 JVM HotSpot 中使用这些选项(或类似选项)?

解决方案

这些说明适用于 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 -versionjava版本1.7.0_03"Java(TM) SE 运行时环境 (build 1.7.0_03-b04)Java HotSpot(TM) 服务器虚拟机(build 22.1-b02,混合模式)$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main编译器Oracle:打印 *Main.mainJava HotSpot(TM) 服务器虚拟机警告:汇编代码打印已启用;打开 DebugNonSafepoints 以获得额外的输出编译方法 (c2) 68 1 % Main::main @ 4 (49 字节)堆中的总数 [0xb3a97548,0xb3a979ec] = 1188重定位 [0xb3a97610,0xb3a97624] = 20主代码 [0xb3a97640,0xb3a97840] = 512存根代码 [0xb3a97840,0xb3a97850] = 16哎呀 [0xb3a97850,0xb3a97858] = 8范围数据 [0xb3a97858,0xb3a97898] = 64范围 pcs [0xb3a97898,0xb3a979e8] = 336依赖项 [0xb3a979e8,0xb3a979ec] = 4无法加载 hsdis-i386.so;库不可加载;PrintAssembly 已禁用OopMapSet 包含 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: 错误: sysdep.h: 没有这样的文件或目录

为了纠正这个问题,我使用以下补丁更改了 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 2012 年 2 月 23 日星期四 09:26:37 -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目录下即可.p>

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

$ java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' Main编译器Oracle:打印 *Main.mainJava HotSpot(TM) 服务器虚拟机警告:汇编代码打印已启用;打开 DebugNonSafepoints 以获得额外的输出编译方法 (c2) 68 1 % Main::main @ 4 (49 字节)堆中的总数 [0xb3999548,0xb39999ec] = 1188重定位 [0xb3999610,0xb3999624] = 20主代码 [0xb3999640,0xb3999840] = 512存根代码 [0xb3999840,0xb3999850] = 16哎呀 [0xb3999850,0xb3999858] = 8范围数据 [0xb3999858,0xb3999898] = 64范围 pcs [0xb3999898,0xb39999e8] = 336依赖项 [0xb39999e8,0xb39999ec] = 4从 [snip]/jdk1.7.0_03/jre/lib/i386/hsdis-i386.so 加载反汇编程序解码编译方法0xb3999548:代码:[反汇编为 mach='i386'][入口点][验证入口点][常数]# {method} 'main' '([Ljava/lang/String;)V' in 'Main'0xb3999640:调用 0xb6ff8510 ;{runtime_call}0xb3999645: 数据 32 xchg %ax,%ax0xb3999648: 移动 %eax,-0x3000(%esp)0xb399964f:推送 %ebp0xb3999650: 低于 $0x38,%esp0xb3999656: 移动 %ecx,%esi0xb3999658: 移动 0x4(%esi),%ebp0xb399965b: 移动 0x8(%esi),%edi0xb399965e: 移动 (%ecx),%esi0xb3999660: 移动 %ecx,(%esp)0xb3999663: 调用 0xb7078cf0 ;*iload_3[剪辑]0xb399983e: hlt0xb399983f: hlt[异常处理程序][存根代码]0xb3999840:jmp 0xb39981e0;{no_reloc}[Deopt 处理程序代码]0xb3999845:推送$0xb3999845;{section_word}0xb399984a:jmp 0xb397e220;{runtime_call}0xb399984f:.byte 0x0OopMapSet 包含 1 个 OopMaps#0OopMap{off=468}

我用过的测试类是:

公共类 Main {公共静态无效主要(最终字符串[]参数){长 x = 0;for (int i = 0; i <1000000; i++) {x += 计算(i);}System.out.println("x=" + x);}私人静态长计算(最终int i){返回 (long)i * (long)i;}}

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?

解决方案

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

这篇关于如何在 JVM HotSpot 中使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何在 JVM HotSpot 中使用 -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print 选项

上一篇: 方法区和 PermGen
下一篇: 为什么JVM启动慢?

基础教程推荐