2012-02-18 10 views
18

Próbuję użyć linii poleceń -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod, jak opisano w this post.Sposób używania -XX: + UnlockDiagnosticVMOptions -XX: CompileCommand = opcja drukowania z JVM HotSpot

Wygląda na to, że jest dostępny z open-jdk (https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly).

Jak korzystać z tych opcji (lub podobnych odpowiedników) z Oracle JDK7 i hotspotem JVM?

+0

To nie jest zbyt trudne, aby spróbować –

+0

Ofc Próbowałem, ale to nie działa, moje pytanie brzmi, jak je sprawić? Będę edytować. –

+0

Czy próbowałeś "Jeśli nie otrzymujesz danych wyjściowych, użyj -XX: + PrintCompilation, aby sprawdzić, czy twoja metoda jest w ogóle kompilowana." –

Odpowiedz

26

Te instrukcje dotyczą systemu Linux (Ubuntu 10.04.4 LTS), ale powinny być odpowiednie dla systemu operacyjnego. Po pobraniu Oracle JDK 7u3 i odpowiednio ustawiając swoje JAVA_HOME i PATH zmienne środowiskowe, należy wykonać następujące czynności, aby sprawdzić dostępne opcje:

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

Powinieneś zobaczyć dostępne są opcje UnlockDiagnosticVMOptions, CompileCommand i PrintAssembly. Użycie opcji CompileCommand spowoduje również włączenie opcji PrintAssembly. Będziesz jednak potrzebował wtyczki deasemblera HotSpot do pracy na PrintAssembly; bez niej, można zobaczyć coś jak poniżej:

$ 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 

Aby pobrać wtyczkę HotSpot dezasembler, trzeba będzie go budować. Patrząc na OpenJDK 7u2 źródła, hsdis plugin readme mówi:

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.

Potwierdziliśmy powyżej tej Oracle JDK 7u3 obsługuje PrintAssembly. Postępowałem zgodnie z instrukcjami hsdis plugin readme, pobrałem GNU binutils 2.22, umieściłem go w katalogu hsdis build/binutils i uruchomiłem make. To w końcu produkowane następujący błąd:

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

Aby rozwiązać ten problem, zmieniłem hsdis.c stosując następującą poprawkę:

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 wtedy sukces. Teraz wystarczy skopiować wtyczkę hsdis-i386.so w katalogu hsdis build do katalogu Oracle JDK 7u3 jre/lib/i386.

Teraz można zobaczyć demontażu skompilowany kod:

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

Klasa testu użyłem jest:

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

Wielkie dzięki za odpowiedź , Mam problem ze zrozumieniem gdzie znalazłem hsdis i jak go zainstalować? Nie rozumiem, gdzie powinienem stworzyć ten katalog kompilacji. Od teraz mam pliki dl tutaj http://hg.openjdk.java.net/ jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/i mam do pobrania binutils-2.22. Kiedy mówisz o 'binutils', jego katalog to tylko podkatalog o nazwie binutils? –

+0

@ alain.janinm Z pliku hsdis readme: 'Makefile szuka źródeł w kompilacji/binutils lub możesz określić jego lokalizację do pliku Makefile za pomocą BINTUILS = path' 'build/binutils' odnosi się do katalogu, w którym znajdują się pliki hsdis. Z tego katalogu możesz spróbować czegoś takiego jak 'mkdir build, cd build; wget -O - http: //ftp.gnu.or g/gnu/binutils/binutils-2.22.tar.bz2 | tar xjvf -; ln -s binutils-2.2.22 binutils'. Lub spróbuj 'BINUTILS = path_to_where_you_extracted_binutils make'. –

+0

Jesteś niesamowitym facetem, który działa doskonale! Wielkie dzięki! –

1

w moim przypadku, aby zobaczyć demontażu skompilowany kod:

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

w powyższym przykładzie ma cykl: for (int i = 0; i < 1 000 000; i++) {...}, dlatego w naszym przypadku bez 1 000 000 iteracji potrzebujemy opcji -XX:CompileThreshold=1 (domyślnie 10 000 dla -serwera), aby zobaczyć nasz zdemontowany skompilowany kod.

Powiązane problemy