1. class 文件内容
class 文件包含JAVA程序执行的字节码;数据严格按照格式紧凑排列在class文件中的二进制流,中间无任何分隔符;文件开头有一个 0xcafebabe(16进制) 特殊的一个标志。
class文件中包含了很多内容:
- 版本
- 访问标志
- 常量池
- 当前类
- 超级类
- 接口
- 字段
- 方法
- 属性
2. JVM运行时数据区
JVM运行时数据区- 线程独占: 每个线程都会有它独立的空间,随线程生命周期而创建和销毁
- 线程共享:所有线程能访问这块内存数据,随虚拟机或者GC而创建和销毁
2.1 方法区
JVM用来存储加载的类信息、常量、静态变量、编译后的代码等数据虚拟机规范中这是一个逻辑区划。具体实现根据不同虚拟机来实现。如: oracle的HotSpot在java7中方法区放在永久代,java8放在元数据空间,并且通过GC机制对这个区域进行管理
2.2 堆内存
堆内存堆内存还可以细分为:老年代、新生代(Eden、From Survivor、To Survivor)JVM启动时创建,存放对象的实例。垃圾回收器主要就是管理堆内存。如果满了,就会出现OutOfMemoryError,更详细内容后续再延伸。
2.3 虚拟机栈
虚拟机栈,每个线程都在这个空间有一个私有的空间。线程栈由多个栈帧(Stack Frame)组成。一个线程会执行一个或多个方法,一个方法对应一个栈帧。栈帧内容包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息等。栈内存默认最大是1M,超出则抛出StackOverflowError.
2.4 本地方法栈
和虚拟机栈功能类似,虚拟机栈是为虚拟机执行JAVA方法而准备的,本地方法栈是为虚拟机使用Native本地方法而准备的。虚拟机规范没有规定具体的实现,由不同的虚拟机厂商去实现。HotSpot虚拟机中虚拟机栈和本地方法栈的实现是一样的。同样,超出大小以后也会抛出StackOverflowError.
2.5 程序计数器
程序计数器(Program Counter Register)记录当前线程执行字节码的位置,存储的是字节码指令地址,如果执行Native方法,则计数器值为空。每个线程都在这个空间有一个私有的空间,占用内存空间很少。CPU同一时间,只会执行一条线程中的指令。JVM多线程会轮流切换并分配CPU执行时间的方式。为了线程切换后,需要通过程序计数器,来恢复正确的执行位置。
3. 查看class文件内容
- demo1.java
public class Demo1{
public static void main(String[] args){
int x = 500;
int y = 100;
int a = x / y;
int b = 50;
System.out.println(a + b);
}
}
- 编译文件
javac Demo1.java
- javap 查看内容
javap -v Demo1.class > Demo1.txt
- Demo1.txt
Classfile /G:/neteasy/subject-2/2.1-java程序运行原理/1.1.1-JAVA程序运行原理分析-资料包 - 副本/Demo1.class
Last modified 2022年5月24日; size 414 bytes
SHA-256 checksum 469b303454945dbe757e43d1f687116173c0d2fff5c37d461e6175b16194b45b
Compiled from "Demo1.java"
public class Demo1
minor version: 0
major version: 57
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #19 // Demo1
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, 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 = Methodref #14.#15 // java/io/PrintStream.println:(I)V
#14 = Class #16 // java/io/PrintStream
#15 = NameAndType #17:#18 // println:(I)V
#16 = Utf8 java/io/PrintStream
#17 = Utf8 println
#18 = Utf8 (I)V
#19 = Class #20 // Demo1
#20 = Utf8 Demo1
#21 = Utf8 Code
#22 = Utf8 LineNumberTable
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 SourceFile
#26 = Utf8 Demo1.java
{
public Demo1();
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 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=5, args_size=1
0: sipush 500
3: istore_1
4: bipush 100
6: istore_2
7: iload_1
8: iload_2
9: idiv
10: istore_3
11: bipush 50
13: istore 4
15: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_3
19: iload 4
21: iadd
22: invokevirtual #13 // Method java/io/PrintStream.println:(I)V
25: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 7
line 6: 11
line 7: 15
line 8: 25
}
SourceFile: "Demo1.java"
-
版本号/访问控制
版本号/访问控制
版本号规则:JDK5,6,7,8分别对应49,50,51,52
访问标志
标志名称 | 标志值 | 含义 |
---|---|---|
ACC_PUBLIC | 0x0001 | 是否为public类型 |
ACC_FINAL | 0x0010 | 是否被声明为final,只有类可设置 |
ACC_INTERFACE | 0x0020 | 是否允许使用invokespecial字节码指令,JDK1.2之后编译出来的类的这个标志为true |
ACC_INTERFACE | 0x0200 | 标志这个是一个接口 |
ACC_ABSTRACT | 0x0400 | 是否为abstract类型,对于接口或抽象类来说,此标志值为true,其他值为false |
AcC_SYNTHETIC | 0x1000 | 标志这个类并非由用户产生的 |
ACC_ANNOTATION | 0x2000 | 标识这个一个注解 |
ACC_ENUM | 0x4000 | 标识这个一个注解 |
- 常量池 Constant pool
// 常量池
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 = Methodref #14.#15 // java/io/PrintStream.println:(I)V
#14 = Class #16 // java/io/PrintStream
#15 = NameAndType #17:#18 // println:(I)V
#16 = Utf8 java/io/PrintStream
#17 = Utf8 println
#18 = Utf8 (I)V
#19 = Class #20 // Demo1
#20 = Utf8 Demo1
#21 = Utf8 Code
#22 = Utf8 LineNumberTable
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 SourceFile
#26 = Utf8 Demo1.java
类信息包含的静态常量,编译之后就能确认
常量 | 含义 |
---|---|
CONSTANT_utf8_info | UTF-8编码的字符串 |
CONSTANT_Integer_info | 整形字面量 |
CONSTANT_Float_info | 浮点型字面量 |
CONSTANT_Long_info | 长整型字面量 |
CONSTANT_Double_info | 双精度浮点型字面量 |
CONSTANT_Class_info | 类或接口的符号引用 |
CONSTANT_String_info | 字符串类型字面量 |
CONSTANT_Fieldref_info | 字段的符号引用 |
CONSTANT_Methodref_info | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 字段或方法的符号引用 |
CONSTANT_MothodType_info | 标志方法类型 |
CONSTANT_MethodHandle_info | 表示方法句柄 |
CONSTANT_lnvokeDynamic_info | 表示一个动态方法调用点 |
- 构造方法
public Demo1();
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 1: 0
Demo1这个示例中,我们并没有写构造函数。由此可见,没有定义构造函数时,会有隐式的无参构造函数。
- 程序入口main方法
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=5, args_size=1
0: sipush 500
3: istore_1
4: bipush 100
6: istore_2
7: iload_1
8: iload_2
9: idiv
10: istore_3
11: bipush 50
13: istore 4
15: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_3
19: iload 4
21: iadd
22: invokevirtual #13 // Method java/io/PrintStream.println:(I)V
25: return
解析参考
4. 程序完整运行分析:
程序完整运行分析一程序完整运行分析二
i程序完整运行分析三
JVM指令码表 (多图预告,后续有空再更新为表格样式吧~~~~~,某云一上就容易被锁定)
image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png如果觉得有收获就点个赞吧,更多知识,请点击关注查看我的主页信息哦~
网友评论