当前位置: 首页 > 面试题库 >

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

夏长卿
2023-03-14
问题内容

我试图使用-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod命令行中的说明这篇文章。

似乎多数民众赞成在open- jdk(https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly)上可用。

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


问题答案:

这些说明适用于Linux(Ubuntu 10.04.4 LTS),但应适用于您的OS。在下载Oracle JDK
7u3
并适当设置了您JAVA_HOMEPATH环境变量之后,执行以下步骤检查可用选项:

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

您应该看到UnlockDiagnosticVMOptionsCompileCommand并且PrintAssembly选项可用。使用该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-i386.sohsdis build目录中的插件复制到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;
    }
}


 类似资料:
  • 问题内容: 我读到numpy在四舍五入方面没有偏见,并且它的工作方式与其设计方式相同。那就是“如果您总是将0.5舍入到下一个最大数字,那么一堆舍入数字的平均值可能会比未舍入数字的平均值稍大:这种偏差或漂移可能会对某些数值算法产生非常不利的影响,使它们不准确。” 忽略此信息并假设我总是想四舍五入,如何在numpy中做到这一点?假设我的数组可能很大。 为了简单起见,假设我有数组: 小数看起来像: 整体

  • 我使用Java已经有一段时间了,足够长的时间来开始使用GUI生成自己的程序,而不仅仅是在Eclipse中运行的教科书中的小示例程序。我希望通过将可执行Jar封装到EXE中,使我的程序对用户(特别是Windows用户)更加友好。所以我找到了Launch4j,它似乎做了一个相当好的工作,但我不知道该程序中一半以上的选项是什么意思(我花了一个小时才弄清楚如何让它做一个功能性的Exe)。我把它交给一个fr

  • 问题内容: 我已经搜索过Google,但找不到任何东西。 我有这个代码。 有这样的数据 输出是这样的。 如何将数据中的第一个选项设置为默认值,这样您将得到这样的结果。 问题答案: 您可以像这样简单地使用ng-init

  • 问题内容: 在以下代码中使用SimpleDateFormatter.format时,startDateText TextView中12:00和12:59之间的小时显示为00:00到00:59,而从13:00开始,它们正确显示为13:xx,14: xx直到23:59。 -—根据要求重构代码当dtold.parse(…)中的字符串为in时,示例的输出小时为00:00,当其为“ 13:00”时,则正确为

  • 我的test.feature文件: 我的test_steps.py文件:

  • 问题内容: 我正在学习Python中的绳索。当我尝试使用该函数打印类的对象时,得到如下输出: 有没有办法设置类及其对象的打印行为(或字符串表示形式)?例如,当我调用类对象时,我想以某种格式打印其数据成员。如何在中实现? 如果你熟悉类,则可以通过为类ostream添加方法来实现上述目的。 问题答案: 该方法是在打印时发生的事情,该方法是在使用功能时(或在交互式提示下查看它时)发生的事情。如果这不是最