2012-02-18 22 views
18

Estoy tratando de usar las líneas de comando -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod como se describe en this post.Cómo usar -XX: + UnlockDiagnosticVMOptions -XX: CompileCommand = opción de impresión con HotSpot JVM

Parece que está disponible con open-jdk (https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly).

¿Cómo puedo utilizar esas opciones (o equivalentes similares) con Oracle JDK7 y JVM HotSpot?

+0

no parece demasiado difícil de probar –

+0

Ofc Lo he intentado pero no funciona, mi pregunta es ¿cómo hacer que funcionen? Voy a editar –

+0

Ha intentado "Si no obtiene ningún resultado, use -XX: + PrintCompilation para verificar que su método se haya compilado en absoluto." –

Respuesta

26

Estas instrucciones se aplican a Linux (Ubuntu 10.04.4 LTS), pero deberían ser aplicables para su sistema operativo. Después de descargar Oracle JDK 7u3 y adecuada configuración de las variables de entorno y JAVA_HOMEPATH, ejecuta el siguiente para comprobar las opciones disponibles:

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

debería ver el UnlockDiagnosticVMOptions, CompileCommand y PrintAssembly opciones están disponibles. El uso de la opción CompileCommand también habilitará la opción PrintAssembly. Sin embargo, necesitará el plugin desensamblador de HotSpot para PrintAssembly para funcionar; sin ella, es posible que vea algo como lo siguiente:

$ 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 

Para obtener el plugin de HotSpot desensamblador, tendrá que construirlo. En cuanto a la fuente de 7u2 OpenJDK, el hsdis plugin readme dice:

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.

Hemos confirmado anteriormente que 7u3 Oracle JDK apoya PrintAssembly. Seguí las instrucciones del readme del plugin hsdis, descargué GNU binutils 2.22, lo coloqué en el directorio hsdis build/binutils y ejecuté make. Esto a la larga produce el siguiente error:

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

Para corregir esto, he cambiado hsdis.c utilizando el siguiente parche:

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> 

corriendo make fue entonces exitoso. Ahora solo copie el complemento hsdis-i386.so en el directorio hsdis build en el directorio Oracle JDK 7u3 jre/lib/i386.

ahora se puede ver el código compilado desmontado:

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

La clase de prueba que he usado es:

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

Muchas gracias por la respuesta , Tengo un problema para entender dónde encontré hsdis y cómo lo instalo? No entiendo dónde debería crear este directorio de compilación. A partir de ahora, tengo los archivos aquí http://hg.openjdk.java.net/ jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/y tengo download binutils-2.22. Cuando hablas de 'binutils' es todo el directorio el directorio secundario llamado binutils? –

+0

@ alain.janinm Desde el archivo hsdis: 'El archivo MAKE busca las fuentes en build/binutils o puede especificar su ubicación en el archivo MAKE mediante BINTUILS = path.' Build/binutils' es relativo al directorio en el que se encuentran los archivos hsdis. Desde este directorio , podrías probar algo como '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'. O intente con 'BINUTILS = path_to_where_y_extracted_binutils make'. –

+0

¡Eres increíble, funciona a la perfección! ¡Muchas gracias! –

1

en mi caso para ver el código compilado desmontado:

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

en el ejemplo anterior tiene ciclo: for (int i = 0; i < 1 000 000; i++) {...}, es por eso en nuestro caso sin 1 000 000 iteraciones, necesitamos la opción -XX:CompileThreshold=1 (de forma predeterminada 10 000 para -server) para ver nuestro código compilado desensamblado.

Cuestiones relacionadas