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;
}
}
To nie jest zbyt trudne, aby spróbować –
Ofc Próbowałem, ale to nie działa, moje pytanie brzmi, jak je sprawić? Będę edytować. –
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." –