Как использовать -XX: + UnlockDiagnosticVMOptions -XX: CompileCommand = опция печати с помощью JVM HotSpot - программирование
Подтвердить что ты не робот

Как использовать -XX: + UnlockDiagnosticVMOptions -XX: CompileCommand = опция печати с помощью JVM HotSpot

Я пытаюсь использовать командные строки -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod, как описано в этом сообщении.

Кажется, что он доступен с open-jdk (https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly).

Как использовать эти параметры (или аналогичные эквиваленты) с помощью oracle JDK7 и JVM HotSpot?

4b9b3361

Ответ 1

Эти инструкции относятся к Linux (Ubuntu 10.04.4 LTS), но должны быть применимы для вашей ОС. После загрузки Oracle JDK 7u3 и соответствующей настройки переменных окружения JAVA_HOME и PATH выполните следующие действия, чтобы проверить доступные параметры:

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

Вы должны увидеть, что доступны опции UnlockDiagnosticVMOptions, CompileCommand и 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 plugin readme говорит:

Чтобы использовать плагин с JVM, вам нужна новая версия, которая может ее загрузить. Если режим продукта вашей JVM не принимает -XX: + PrintAssembly, у вас нет новой версии.

Для создания этого проекта вам понадобится копия GNU binutils для сборки против.

В теории это должно строиться на Windows, но получать рабочие Среда создания GNU в Windows оказалась сложной задачей.

Мы уже подтвердили, что Oracle JDK 7u3 поддерживает PrintAssembly. Я выполнил инструкции readme reads 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.so в каталог hsdis 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;
    }
}

Ответ 2

в моем случае, чтобы увидеть дизассемблированный скомпилированный код:

$ 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 (по умолчанию 10 000 для -server), чтобы увидеть наш дизассемблированный скомпилированный код.