当我看到JVM规范时,它说每个类最多具有一个类初始化方法,即“ clinit”,因此我认为我们应该有一些命令来查看此方法在.class文件中的编码方式。

起初我以为使用javap可以,但是我发现它没有用。

最佳答案

javap命令显示<init><clinit>方法...尽管它不使用这些名称。 (请参见下面的public Test();static {};“方法”。)

或者,您也可以使用其他反汇编程序。例如,Krakatau将在其输出中显示内部名称"<init>""<clinit>"


  我一直认为<clinit>文件中有一个方法名称.class


你是对的。这些名称将出现在方法的.class文件表示中。并且您可以在<init>打印的常量表中看到内部方法名称<clinit>javap

只是javap的实现者选择了不在方法部分中显示那些方法名称。他们使用了不同的表示法。

(为什么?我的猜测是,他们认为如果这样做的话,大多数人会更容易理解javap输出!对吗?我不知道,但是无论如何这都是没有意义的。)



$ cat Test.java
public class Test {
  static String foo = "hello";
}


$ javap -p -c -s -v Test
Classfile /tmp/Test.class
  Last modified Feb 23, 2019; size 293 bytes
  MD5 checksum 724ea13308a150d0cc5730edcf4db616
  Compiled from "Test.java"
public class Test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#15         // java/lang/Object."<init>":()V
   #2 = String             #16            // hello
   #3 = Fieldref           #4.#17         // Test.foo:Ljava/lang/String;
   #4 = Class              #18            // Test
   #5 = Class              #19            // java/lang/Object
   #6 = Utf8               foo
   #7 = Utf8               Ljava/lang/String;
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               <clinit>
  #13 = Utf8               SourceFile
  #14 = Utf8               Test.java
  #15 = NameAndType        #8:#9          // "<init>":()V
  #16 = Utf8               hello
  #17 = NameAndType        #6:#7          // foo:Ljava/lang/String;
  #18 = Utf8               Test
  #19 = Utf8               java/lang/Object
{
  static java.lang.String foo;
    descriptor: Ljava/lang/String;
    flags: ACC_STATIC

  public Test();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #2                  // String hello
         2: putstatic     #3                  // Field foo:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 2: 0
}
SourceFile: "Test.java"

10-08 09:32