我使用javap
命令检查了我的类文件,我无法理解下面的部分
Classfile /D:/WaitNotifyExample.class
Last modified Dec 20, 2013; size 622 bytes
MD5 checksum 4781f8cf8062fa75efa30c76adc25cfb
Compiled from "WaitNotifyExample.java"
public class WaitNotifyExample
SourceFile: "WaitNotifyExample.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #12.#24 // java/lang/Object."<init>":()V
#2 = Class #25 // java/lang/String
#3 = String #26 // I am hidden
#4 = Methodref #2.#27 // java/lang/String."<init>":
(Ljava/lang/String;)V
#5 = Fieldref #11.#28 // WaitNotifyExample.s1:Ljava/lang/String;
#6 = String #29 // I am diving into Pool
#7 = Fieldref #11.#30 // WaitNotifyExample.s2:Ljava/lang/String;
#8 = Fieldref #31.#32 // java/lang/System.out:Ljava/io/PrintStream;
#9 = String #33 // hello World
#10 = Methodref #34.#35 // java/io/PrintStream.println:
(Ljava/lang/String;)V
#11 = Class #36 // WaitNotifyExample
#12 = Class #37 // java/lang/Object
#13 = Utf8 s1
#14 = Utf8 Ljava/lang/String;
#15 = Utf8 s2
#16 = Utf8 <init>
#17 = Utf8 ()V
#18 = Utf8 Code
#19 = Utf8 LineNumberTable
#20 = Utf8 main
#21 = Utf8 ([Ljava/lang/String;)V
#22 = Utf8 SourceFile
#23 = Utf8 WaitNotifyExample.java
#24 = NameAndType #16:#17 // "<init>":()V
#25 = Utf8 java/lang/String
#26 = Utf8 I am hidden
#27 = NameAndType #16:#38 // "<init>":(Ljava/lang/String;)V
#28 = NameAndType #13:#14 // s1:Ljava/lang/String;
#29 = Utf8 I am diving into Pool
#30 = NameAndType #15:#14 // s2:Ljava/lang/String;
#31 = Class #39 // java/lang/System
#32 = NameAndType #40:#41 // out:Ljava/io/PrintStream;
#33 = Utf8 hello World
#34 = Class #42 // java/io/PrintStream
#35 = NameAndType #43:#38 // println:(Ljava/lang/String;)V
#36 = Utf8 WaitNotifyExample
#37 = Utf8 java/lang/Object
#38 = Utf8 (Ljava/lang/String;)V
#39 = Utf8 java/lang/System
#40 = Utf8 out
#41 = Utf8 Ljava/io/PrintStream;
#42 = Utf8 java/io/PrintStream
#43 = Utf8 println
{
public java.lang.String s1;
flags: ACC_PUBLIC
public java.lang.String s2;
flags: ACC_PUBLIC
public WaitNotifyExample();
flags: ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #2 // class java/lang/String
8: dup
9: ldc #3 // String I am hidden
11: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
14: putfield #5 // Field s1:Ljava/lang/String;
17: aload_0
18: new #2 // class java/lang/String
21: dup
22: ldc #6 // String I am diving into Pool
24: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
27: putfield #7 // Field s2:Ljava/lang/String;
30: return
LineNumberTable:
line 2: 0
line 4: 4
line 5: 17
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
5: ldc #9 // String hello World
7: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
10: return
LineNumberTable:
line 7: 0
line 8: 2
line 9: 10
}
修改 下面是相应的java代码。
public class WaitNotifyExample {
public String s1 = new String("I am hidden");
public String s2 = new String("I am diving into Pool");
public static void main(String[] args) {
int mainLiteral = 0;
System.out.println("hello World");
}
}
我不理解上面的类文件中的以下内容:
答案 0 :(得分:3)
stack = 4,locals = 1,args_size = 1
字节码中的值存储在局部变量槽和操作数堆栈中。每个插槽最多可以有2 ^ 16 - 1个插槽,但出于效率原因,您需要在堆栈和本地设备上指定限制,以便在您实际不使用它时不会浪费所有空间。
在编译代码中,编译器会自动将其计算为函数中实际使用的最小值。在这种情况下,它在操作数堆栈中使用4个插槽,在局部变量表中使用1个插槽。我不确定arg_size是什么,但我猜这只是参数的总大小(即参数的数量)。无论如何,这并不对应于类文件格式的任何特性,所以不管它是什么,javap都在计算并手动插入它。
LineNumberTable:section
LineNumberTable是保存元数据以进行调试的可选属性之一。在这种情况下,它指定字节码中的哪些偏移对应于原始源代码中的每一行。这对于打印信息量更大的堆栈跟踪以及提供调试器中的单步功能非常有用。
答案 1 :(得分:2)
Code:
stack=2, locals=2, args_size=1
Stack
指的是执行方法所需的堆栈深度,arg_size
指的是,它需要多少参数,locals
指的是,需要在局部变量表中保留多少个局部变量槽。并且
LineNumberTable: section
LineNumberTable是保存元数据以进行调试的可选属性之一。它指定字节码中的哪些偏移对应于原始源代码中的每一行。这对于打印信息量更大的堆栈跟踪以及提供调试器中的单步功能非常有用。
有关这两项的更多详情,请参阅this。
答案 2 :(得分:0)
你没有得到什么?它的字节码。如果你理解字节代码,那么你很容易理解输出的内容。 javap'解组'代码而不是反编译它。所以这就是说你有一个WaitNOtifyExample构造函数,一个main方法和两个公共字符串引用。在这些方法和构造函数定义中,遵循这些的字节代码,它描述了这两个项目正在做什么(以字节代码形式)。