JVM内存空间组成+GC回收机制

JVM

1. 程序计数器
一块较小的线程私有空间, 可以当作当前线程所执行字节码的行号显示器, 通过改变计数器的值选择执行的字节码.
2. 虚拟机栈
一块线程私有的内存空间, 每起一个线程就会起一个线程栈, 而在一个线程中可以调用多个方法, ,每起一个方法就会起一个栈帧, 所以一个线程栈中有多个栈帧. 每一个方法从调用到执行完成的过程, 就代表一个栈帧在虚拟机栈中入栈到出栈的过程. 每一个栈帧存放着局部变量, 操作函数等信息. 当线程请求的栈的深度大于当前虚拟机栈的深度时, 就会触发StackOverFlowError.
3. 本地方法栈
Java访问C语言等其他语言所用到的栈, 原理上与虚拟机栈类似
4. 堆
最大JVM内存, 线程共享, 只能存储对象.
5. 方法区
线程共享的内存区. 用于存储已经被加载的类信息, 常量,静态变量等
6. 运行时常量
方法区的一部分, 类文件中有一项信息时常量池, 用来存储编译器生成的字面量和符号引用.
7. 直接内存
不是Java虚拟机中定义的内存区域

GC

1. 确定垃圾
a. 引用基数算法
给对象中添加一个引用计数器, 每当由一个地方引用它的时候, 计数器就+1; 当引用失效时, 计数器就-1, 计数器为0的对象不被使用.
但是这个算法无法解决对象之间的相互引用关系
b. 正向可达算法
得到堆内存中一定不是垃圾的根的对象,GCRoots, 顺着GCRoots引用往下找, 能顺藤摸瓜找到的就是好瓜,否则就是垃圾
2. 垃圾回收算法
a. 标记清除: 两个阶段: 1. 标记阶段, 通过正向可达算法 2.清除阶段
缺点: 内存不连续, 碎片化
b. 复制算法:一般在新生代中使用
将原有内存空间啊分为两块, 每次使用一块, 垃圾回收时将正在使用的内存块中存活对象复制到未使用的那一块内存中, 之后清除正在使用的内存快中所有空间
c. 标记-压缩算法: 一般用在老年代
通过正向可达算法, 将所有存活的对象压缩到内存空间的一端, 之后清理边界外的所有空间
d. 分代算法 : JVM使用
将内存分为新生代和老生代
新生代由于存活对象不多, 使用复制算法
老生代存活率高, 使用标记-压缩算法

猜你喜欢

转载自blog.csdn.net/weixin_42383575/article/details/84886869