注: 码字辛苦, 转载请标注转载来源
jvm结构图: [1]
整个JVM架构包含三部分:
-
类加载
-
-
加载
-
- 双亲委派机制
-
链接
-
初始化
-
- 静态变量的初始值赋值
-
-
运行时数据区域
-
- 线程私有区域
- 线程共享区域
-
执行引擎
-
- 解释器
- JIT即时编译器
- GC
运行时数据区域
-
线程私有区域: 线程私有区域主要包含栈帧、程序计数器、本地方法栈。
-
-
栈帧: 栈帧中包含局部变量表、操作栈、动态链接、以及方法返回地址;
-
-
局部变量表:如常量池key-value形式:
-
- key是数据编号, value既可以是另外其他常量的编号, 也可以直接是字符串.
-
-
#1 = Class #22
#22 = Utf8 java/lang/object
-
-
- 操作栈: Java源码对应的字节码指令序列程序计数器中所存储的下一条指令就是操作栈指令的地址或下标
- 动态链接: 操作栈中的指令号(引用), 如通过#1的方式指向常量池某个具体的变量值或者某个指令可以有效减少冗余字节码的数量, 对字节码进行编号, 在使用时通过指令号的方式进行引用, 类似于代码编写时对一些通用的函数和变量值进行封装.
- 方法返回地址
-
栈帧的作用: 方法执行的载体, 解决程序如何运行的问题
-
- 为方法执行提供所需数据内存区域, 维系着方法执行中的各种计算所需要的数据
- 调用方法 = 创建栈帧+入栈, 方法结束 = 方法返回+出栈
-
常见问题:
-
- 栈帧空间不足: 超过预设的栈帧固定空间大小, 抛stackoverflowError
- 内存空间不足: 栈帧无法动态扩展, 抛OOM(outofmemory)
-
程序计数器:
- 基于操作栈来理解程序计数器更容易, 存储操作栈中的具体的指令号, 不会进行垃圾回收, 也不会有OOM问题
-
线程池共享区域
-
对象堆
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qe3RYGmF-1674796792445)(/Users/coyote-ll/Downloads/对象堆 (1)].png)
- 常见概念:
- young gc/minor gc: Young Gen垃圾回收
- major gc: 老年代垃圾回收
- full gc: 整堆垃圾回收: 整个堆+方法区
- mix gc: 混合回收, G1中的概念, 全部young gc加部分老年代回收
- 堆上对象分配
- 对象创建:
- 类引用定位与加载
- 对象分配内存
连续空间-->空间压缩整理(Serial/ParNew)--> 指针碰撞分配
非连续空间-->空间整理与SWEEP(CMS)-->空闲列表分配
- 对象引用安全并发变动:
CAS 并发修改机制
Thread Local Allocation Buffer(TLAB)
本地线程分配缓存
- 内存空间初始化, 对象字段初始化零值
- 对象init方法的调用, 对象初始化
- 对象进入老年代的四种情况
- 对象分配在Eden(新生代)中, 当Young Gen满了后就标记复制算法进行young gc
- 大对象直接进入老年代
- 长期存活的对象直接进入老年代
- 对象年龄动态判断
- S区无法存放, 通过
内存分配动态担保机制
提前进入老年代
- 内存分配动态担保机制
- 对象创建:
- 常见概念:
参考
- ^图片来源 https://dzone.com/articles/jvm-architecture-explained