2

I would like to see the current (bytecode) instruction stream of the JVM it is executing. After some googleing, I found that the jvm debug build offers the -XX:+TraceBytecodesoption (see here). However, the mentioned link to the hotspot JVM debug build is dead and I could not find a debug build online :/

Is there another way to trace the jvm bytecode stream or can someone point me in the right direction? I'm running 64 bit ubuntu 16.04.

P.S: I know, its going to be painfully slow to print out the complete instruction stream. However, I am curios

Community
  • 1
  • 1
user1228633
  • 521
  • 1
  • 6
  • 16
  • I'm not really I understood: you want to print (in a file or a console) the bytecode that is executed in real time ? – Asoub Oct 26 '16 at 08:45
  • It does not need to be in real time, but yeah. Thats pretty much what I am aiming for – user1228633 Oct 26 '16 at 09:31
  • fastdebug builds are not published anymore, but the source code is open so you can create one yourself if you want. JDK9's root repository is here http://hg.openjdk.java.net/jdk9/jdk9/. [This readme](http://hg.openjdk.java.net/jdk9/jdk9/raw-file/f2bdff2bd261/README-builds.html) is a fine place to start. – Stanislav Lukyanov Oct 26 '16 at 17:52
  • 1
    Also, if it is not necessary to see bytecode that is executed in the particular moment then `javap -v MyClassFile.class` should suffice. – Stanislav Lukyanov Oct 26 '16 at 17:54

2 Answers2

9

-XX:+TraceBytecodes option is exactly what are you looking for. It is available in debug builds of HotSpot JVM. You can easily build JVM yourself - just HotSpot, not even JDK.

  1. Clone hotspot repository from OpenJDK 8 project

    hg clone http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot
    
  2. Build 'fastdebug' JVM (assuming JDK is already installed at /usr/java/jdk1.8.0_102)

    cd hotspot/make
    make ALT_BOOTDIR=/usr/java/jdk1.8.0_102 ARCH_DATA_MODEL=64 fastdebug
    

    You may add HOTSPOT_BUILD_JOBS=N to run compilation in N parallel processes.

  3. Run it

    export ALT_JAVA_HOME=/usr/java/jdk1.8.0_102
    ../build/linux/linux_amd64_compiler2/fastdebug/hotspot -XX:+TraceBytecodes MainClass
    
apangin
  • 92,924
  • 10
  • 193
  • 247
  • Super interesting answer, thanks! Step 1 and 2 OK. For running, I hit: `Error: Cannot find the java launcher "/java/re/j2se/1.8.0/promoted/latest/binaries/linux-amd64/bin/java"`. Any hint? – Martin Monperrus Nov 03 '17 at 10:55
  • @MartinMonperrus This means `ALT_JAVA_HOME` env variable is not set. You need to set `ALT_JAVA_HOME` or modify path to JDK directly in `build/linux/linux_amd64_compiler2/fastdebug/hotspot` script. – apangin Nov 03 '17 at 21:29
0
can someone point me in the right direction

Well I'll try. The only thing I've found is using jdb. You'll have to create your own "printer".

Because you're asking this out of curiosity rather than need, I don't think you'll go as far as creatinf an application that does what yout want, but maybe you'll find other ressources that does it (I didn't find any) or at last ease the job .

From what I understand, jdb (java debugger) is a CLI program that uses the JDBA (Java Platform Debugger Architecture) and JVM TI (Java Virtual Machine Tooling Interface).

This is a how jdb works:

  • You compile your code with the -g option (not mandatory), start your main class with jdb (rather than java).
  • You can do step by step execution of your code using step command in the console, but this might run multiple bytecode instructions (all the ones corresponding to the instruction in the source code)
  • You can use stepi which only executes one bytecode line.
  • You must set a breakpoint to do step by step execution, and the cont option will go to the next breakpoint (just like in a IDE).
  • The list option allows you to see the code around your breakpoint/line (but not the bytecode).
  • You can also get the current line number in source file, and in bytecode (with wherei, I think).

The other tool is javap -c to get readable bytecode (but I think you already knew this).

Now with all these, I guess you see where I'm going. You create an application (java applicaiton, or some shell/dos) that uses jdb to do step by step bytecode execution, and you pick the matching line in your bytecode from javac -p to print it. Note that I don't know how you should do in multi-threaded environnements. There are also bytecode visualisation tools like ASM or dirtyJOE, but I don't think they offer bytecode debugging option.

I believe the JVM TI is used by IDE's debuggers, and might be more powerfull faster, and complex than jdb.

Some links that might interest you:

As for myself, I was also curious on how java debuging (and other stuff) worked, so this was kinda interesting.

Asoub
  • 2,273
  • 1
  • 20
  • 33