我该如何检查Java代码的汇编输出?

9

3
Java 不会输出汇编代码。 - user1864610
3
确实如此:). 只需查看 https://www.beyondjava.net/blog/java-programmers-guide-assembler-language/ 或者下面的回答即可。 - Stephan Rauh
2个回答

21

Java使用字节码和机器码两种语言。这是一个两步过程。第一步是将Java源代码编译成字节码,正如@elliott-frisch所指出的那样。在运行时,JVM监视程序中经常使用的部分。如果某个方法“运行热点”,则将它编译成机器码。这又是一个多步骤的过程,包括许多优化和用更快速的代码替换快速代码。我几年前在BeyondJava.net中描述了这一过程。

如果您有45分钟时间,我还建议观看Charles Nutter的演讲。"Down the rabbit hole"是Java编译成汇编语言的很好的介绍。

至于您的问题:您需要向启动应用程序的命令添加一些参数:

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

你还需要下载一个特殊的DLL并将其存储在jre文件夹中。此外,还可以参考Chris Newland的文章了解如何为OS X编译此文件。


2
已经有一个“如何在JVM中查看JIT编译代码?”(https://dev59.com/53I_5IYBdhLWcg3wJfkM)的问答,其中提供了相同的选项建议。 - Peter Cordes
它不会将任何内容编译成汇编代码,而是直接转换为机器码。你可以在汇编中获得可打印的输出,但那只是打印过程的副产品。Java不浪费时间运行汇编器。 - user207421
1
你说得对。我已经纠正了这段文字。在我看来,汇编代码和机器码有点类似,因为当我在机器码级别上编程时,我使用的是汇编器。 - Stephan Rauh

4

Java使用字节码。最相似的是javap,根据链接的Oracle文档,javap命令反汇编一个或多个类文件。它的输出取决于所使用的选项。

package com.stackoverflow;

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

如果我将其编译为 Main.class,然后运行 javap -v Main.class,我会得到以下结果。
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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接