How do I check assembly output of Java code?
Asked Answered
J

2

9

I found this question that answered it for C++:
How do you get assembler output from C/C++ source in gcc?

Janinajanine answered 19/6, 2015 at 2:5 Comment(2)
Java doesn't output assembly code.Restaurant
Oh, it does indeed :). Just have a look at beyondjava.net/blog/java-programmers-guide-assembler-language or my answer below.Listlessness
P
4

Java uses bytecode. The most similar would be javap, per the linked Oracle documentation, the javap command disassembles one or more class files. Its output depends on the options used.

package com.stackoverflow;

class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

If I compile that to Main.class and then run javap -v Main.class I get

Classfile /home/efrisch/workspace/StackOverflow/bin/com/stackoverflow/Main.class
  Last modified Jun 18, 2015; size 553 bytes
  MD5 checksum de4f987e783aa0f145e7245269504028
  Compiled from "Main.java"
class com.stackoverflow.Main
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Class              #2             // com/stackoverflow/Main
   #2 = Utf8               com/stackoverflow/Main
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/stackoverflow/Main;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Fieldref           #17.#19        // java/lang/System.out:Ljava/io/PrintStream;
  #17 = Class              #18            // java/lang/System
  #18 = Utf8               java/lang/System
  #19 = NameAndType        #20:#21        // out:Ljava/io/PrintStream;
  #20 = Utf8               out
  #21 = Utf8               Ljava/io/PrintStream;
  #22 = String             #23            // Hello, World!
  #23 = Utf8               Hello, World!
  #24 = Methodref          #25.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #25 = Class              #26            // java/io/PrintStream
  #26 = Utf8               java/io/PrintStream
  #27 = NameAndType        #28:#29        // println:(Ljava/lang/String;)V
  #28 = Utf8               println
  #29 = Utf8               (Ljava/lang/String;)V
  #30 = Utf8               args
  #31 = Utf8               [Ljava/lang/String;
  #32 = Utf8               SourceFile
  #33 = Utf8               Main.java
{
  com.stackoverflow.Main();
    descriptor: ()V
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/stackoverflow/Main;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #22                 // String Hello, World!
         5: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 5: 0
        line 6: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "Main.java"
Pozzy answered 19/6, 2015 at 2:12 Comment(0)
L
21

Java uses both bytecode and assembly language machine code. It's a two-step process. The first step is to compile the Java source code to bytecode, as @elliott-frisch pointed out. At runtime, the JVM watches which parts of the program are used a lot. If a method "runs hot", it's compiled to machine code. That, in turn, is a multi-step process itself, including many optimizations and replacing fast code with even faster code. I've described this in BeyondJava.net several years ago.

If you can spare 45 minutes, I also recommend watching the talk of Charles Nutter. "Down the rabbit hole" is a great introduction to how Java compiles to assembly language.

As for your question: you have to add some parameters to the command starting the application:

javaw.exe -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly Adder

You also have to download a special DLL and store it in the jre folder. Also see Chris Newlands article on how to compile this file for OS X.

Listlessness answered 3/2, 2018 at 16:50 Comment(3)
There's already a How to see JIT-compiled code in JVM? Q&A which suggests the same options.Customhouse
It doesn't compile anything to assembly code. It goes straight to machine code. You can get a printable output in assembly but that's a byproduct of the printing process. Java does not waste its time running an assembler.Seldun
You're right. I've corrected the text. In my mind assembly code and machine code are sort of synonyms, because when I'm programming on the machine code level, I'm using an assembler.Listlessness
P
4

Java uses bytecode. The most similar would be javap, per the linked Oracle documentation, the javap command disassembles one or more class files. Its output depends on the options used.

package com.stackoverflow;

class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

If I compile that to Main.class and then run javap -v Main.class I get

Classfile /home/efrisch/workspace/StackOverflow/bin/com/stackoverflow/Main.class
  Last modified Jun 18, 2015; size 553 bytes
  MD5 checksum de4f987e783aa0f145e7245269504028
  Compiled from "Main.java"
class com.stackoverflow.Main
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Class              #2             // com/stackoverflow/Main
   #2 = Utf8               com/stackoverflow/Main
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/stackoverflow/Main;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Fieldref           #17.#19        // java/lang/System.out:Ljava/io/PrintStream;
  #17 = Class              #18            // java/lang/System
  #18 = Utf8               java/lang/System
  #19 = NameAndType        #20:#21        // out:Ljava/io/PrintStream;
  #20 = Utf8               out
  #21 = Utf8               Ljava/io/PrintStream;
  #22 = String             #23            // Hello, World!
  #23 = Utf8               Hello, World!
  #24 = Methodref          #25.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #25 = Class              #26            // java/io/PrintStream
  #26 = Utf8               java/io/PrintStream
  #27 = NameAndType        #28:#29        // println:(Ljava/lang/String;)V
  #28 = Utf8               println
  #29 = Utf8               (Ljava/lang/String;)V
  #30 = Utf8               args
  #31 = Utf8               [Ljava/lang/String;
  #32 = Utf8               SourceFile
  #33 = Utf8               Main.java
{
  com.stackoverflow.Main();
    descriptor: ()V
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/stackoverflow/Main;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #22                 // String Hello, World!
         5: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 5: 0
        line 6: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "Main.java"
Pozzy answered 19/6, 2015 at 2:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.