目录
1、在IDEA利用断点进行debug模式,观察栈帧的入栈出栈
2、在IDEA中使用javap指令对class文件进行解析
3、在IDEA中利用jclasslib插件解析.class文件
在IDEA中输入这样的代码
import java.util.function.DoubleToIntFunction;
/*
(1)现在设置的代码补全是alt+/
(2)快速注释是command+/
(3)快速格式化代码 alt+command+L
(4)利用断点进入debug模式,观察栈的栈帧和局部变量表,进栈出栈操作
进入都out/production/learnJVMdemo文件夹下,有一个当前类的.class文件,对它进行反编译
在Terminal界面下输入反编译指令:javap -v StackFrameTest.class,观察反编译的输出结果
*/
public class TestStackFrame {
public static void main(String[] args) {
System.out.println("这是main即将执行");
TestStackFrame tt = new TestStackFrame();
try {
tt.method1();
}catch (Exception e){
e.printStackTrace();
}
tt.method1();
System.out.println();
System.out.println("这是main执行完毕");
}
public void method1(){
System.out.println("这是method1即将执行");
int I=10;
int j=11;
method2();
//System.out.println(10/0); //这个会报出一个错误
System.out.println("这是method1执行完毕");
}
public void method2(){
System.out.println("这是method2即将执行");
int I=10;
int j=11;
method3();
System.out.println("这是method2执行完毕");
}
public void method3(){
System.out.println("这是method3即将执行");
int I=10;
int j=11;
System.out.println("这是method3执行完毕");
}
}
1、在IDEA利用断点进行debug模式,观察栈帧的入栈出栈
在代码某处加入红色断点

image.png
右键,进入debug模式

image.png
在下方可以观察debug窗口

image.png
点击箭头朝下的蓝色按钮,执行下一条语句

image.png
2、在IDEA中使用javap指令对class文件进行解析
对上面这段代码进行complie后,会生成.class文件,生成的.class文件在out/production文件夹下,其中learnJVMdemo是你创建的IDEA项目的名称。

image.png
在IDEA的Terminal输入指令

image.png
然后输入反编译指令,对class文件进行反编译

image.png
反编译输入的结果是(仔细分析反编译的结果,能看到学习jvm途中遇见的很多老朋友,例如常量池、局部变量表、<init>方法等):
a1234@MacBook-Pro learnJVMdemo % javap -v TestStackFrame.class
Classfile /Users/a1234/IDEA_project/learnJVMdemo/out/production/learnJVMdemo/TestStackFrame.class
Last modified 2020年5月21日; size 1446 bytes
SHA-256 checksum 5c1b47cc1ffe73348dbbc7c2713bff73502254e51e2e528f33c84315f11f2f17
Compiled from "TestStackFrame.java"
public class TestStackFrame
minor version: 0
major version: 58
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #21 // TestStackFrame
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 5, attributes: 1
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5:#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Fieldref #8.#9 // java/lang/System.out:Ljava/io/PrintStream;
#8 = Class #10 // java/lang/System
#9 = NameAndType #11:#12 // out:Ljava/io/PrintStream;
#10 = Utf8 java/lang/System
#11 = Utf8 out
#12 = Utf8 Ljava/io/PrintStream;
#13 = String #14 // 这是main即将执行
#14 = Utf8 这是main即将执行
#15 = Methodref #16.#17 // java/io/PrintStream.println:(Ljava/lang/String;)V
#16 = Class #18 // java/io/PrintStream
#17 = NameAndType #19:#20 // println:(Ljava/lang/String;)V
#18 = Utf8 java/io/PrintStream
#19 = Utf8 println
#20 = Utf8 (Ljava/lang/String;)V
#21 = Class #22 // TestStackFrame
#22 = Utf8 TestStackFrame
#23 = Methodref #21.#3 // TestStackFrame."<init>":()V
#24 = Methodref #21.#25 // TestStackFrame.method1:()V
#25 = NameAndType #26:#6 // method1:()V
#26 = Utf8 method1
#27 = Class #28 // java/lang/Exception
#28 = Utf8 java/lang/Exception
#29 = Methodref #27.#30 // java/lang/Exception.printStackTrace:()V
#30 = NameAndType #31:#6 // printStackTrace:()V
#31 = Utf8 printStackTrace
#32 = Methodref #16.#33 // java/io/PrintStream.println:()V
#33 = NameAndType #19:#6 // println:()V
#34 = String #35 // 这是main执行完毕
#35 = Utf8 这是main执行完毕
#36 = String #37 // 这是method1即将执行
#37 = Utf8 这是method1即将执行
#38 = Methodref #21.#39 // TestStackFrame.method2:()V
#39 = NameAndType #40:#6 // method2:()V
#40 = Utf8 method2
#41 = String #42 // 这是method1执行完毕
#42 = Utf8 这是method1执行完毕
#43 = String #44 // 这是method2即将执行
#44 = Utf8 这是method2即将执行
#45 = Methodref #21.#46 // TestStackFrame.method3:()V
#46 = NameAndType #47:#6 // method3:()V
#47 = Utf8 method3
#48 = String #49 // 这是method2执行完毕
#49 = Utf8 这是method2执行完毕
#50 = String #51 // 这是method3即将执行
#51 = Utf8 这是method3即将执行
#52 = String #53 // 这是method3执行完毕
#53 = Utf8 这是method3执行完毕
#54 = Utf8 Code
#55 = Utf8 LineNumberTable
#56 = Utf8 LocalVariableTable
#57 = Utf8 this
#58 = Utf8 LTestStackFrame;
#59 = Utf8 main
#60 = Utf8 ([Ljava/lang/String;)V
#61 = Utf8 e
#62 = Utf8 Ljava/lang/Exception;
#63 = Utf8 args
#64 = Utf8 [Ljava/lang/String;
#65 = Utf8 tt
#66 = Utf8 StackMapTable
#67 = Class #64 // "[Ljava/lang/String;"
#68 = Utf8 i
#69 = Utf8 I
#70 = Utf8 j
#71 = Utf8 SourceFile
#72 = Utf8 TestStackFrame.java
{
public TestStackFrame();
descriptor: ()V
flags: (0x0001) 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 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestStackFrame;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String 这是main即将执行
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: new #21 // class TestStackFrame
11: dup
12: invokespecial #23 // Method "<init>":()V
15: astore_1
16: aload_1
17: invokevirtual #24 // Method method1:()V
20: goto 28
23: astore_2
24: aload_2
25: invokevirtual #29 // Method java/lang/Exception.printStackTrace:()V
28: aload_1
29: invokevirtual #24 // Method method1:()V
32: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
35: invokevirtual #32 // Method java/io/PrintStream.println:()V
38: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
41: ldc #34 // String 这是main执行完毕
43: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
46: return
Exception table:
from to target type
16 20 23 Class java/lang/Exception
LineNumberTable:
line 13: 0
line 14: 8
line 16: 16
line 19: 20
line 17: 23
line 18: 24
line 20: 28
line 21: 32
line 22: 38
line 23: 46
LocalVariableTable:
Start Length Slot Name Signature
24 4 2 e Ljava/lang/Exception;
0 47 0 args [Ljava/lang/String;
16 31 1 tt LTestStackFrame;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 23
locals = [ class "[Ljava/lang/String;", class TestStackFrame ]
stack = [ class java/lang/Exception ]
frame_type = 4 /* same */
public void method1();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #36 // String 这是method1即将执行
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: bipush 10
10: istore_1
11: bipush 11
13: istore_2
14: aload_0
15: invokevirtual #38 // Method method2:()V
18: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
21: ldc #41 // String 这是method1执行完毕
23: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
26: return
LineNumberTable:
line 26: 0
line 27: 8
line 28: 11
line 29: 14
line 32: 18
line 33: 26
LocalVariableTable:
Start Length Slot Name Signature
0 27 0 this LTestStackFrame;
11 16 1 I I
14 13 2 j I
public void method2();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #43 // String 这是method2即将执行
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: bipush 10
10: istore_1
11: bipush 11
13: istore_2
14: aload_0
15: invokevirtual #45 // Method method3:()V
18: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
21: ldc #48 // String 这是method2执行完毕
23: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
26: return
LineNumberTable:
line 35: 0
line 36: 8
line 37: 11
line 38: 14
line 39: 18
line 40: 26
LocalVariableTable:
Start Length Slot Name Signature
0 27 0 this LTestStackFrame;
11 16 1 I I
14 13 2 j I
public void method3();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=3, args_size=1
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #50 // String 这是method3即将执行
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: bipush 10
10: istore_1
11: bipush 11
13: istore_2
14: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
17: ldc #52 // String 这是method3执行完毕
19: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return
LineNumberTable:
line 42: 0
line 43: 8
line 44: 11
line 45: 14
line 46: 22
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 this LTestStackFrame;
11 12 1 I I
14 9 2 j I
}
SourceFile: "TestStackFrame.java"
a1234@MacBook-Pro learnJVMdemo %
3、在IDEA中利用jclasslib插件解析.class文件
首先需要在IDEA中安装jclasslib插件。进入IDEA的设置

image.png
在marketpalce中搜索jclasslib然后进行安装

在marketpalce中搜索jclasslib然后进行安装
安装好之后jclasslib出现在installed界面

安装好之后jclasslib出现在installed界面
重启IDEA,然后打开一个项目代码,在view窗口有一个show bytecode with jclasslib

image.png
点击,出现下面的界面,就可以从中获取到class文件相关的信息了

image.png