JVM内存结构和垃圾回收

JVM运行时数据区

方法区:永久代 线程共享 用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。

堆(Heap):新生代,老年代 线程共享 所有的对象实例以及都要在堆上分配。

虚拟机栈:VM Stack 线程私有 Java方法执行的内存模型:方法执行时创建栈帧(Stack Frame)用户存储局部变量表、操作数栈、动态链接、方法入口等信息。每个方法从调用直至执行完成的过程就对应着一个栈帧在VMStack 中的入栈和出栈过程

本地方法栈:Native Method Stack 与VM Stack 类似,区别在于VM Stack为虚拟机执行Java方法(字节码)服务,而Native Method Stack则是VM使用到的Native方法服务

程序计数器:Program CounterRegister 线程私有 可看作是当前线程所执行的字节码行号指示器

所有的对象实例以及都要在堆上分配。
The heap is the runtime data area from which memory for all class instances and arrays is allocated.

垃圾回收

垃圾回收主要发生在堆中。

引用计数:难以解决对象之间的相互循环引用的问题,一般JVM不用,但是Pythoon中会用到

可达性分析算法
JVM一般使用可达性分析算法带判断垃圾
使用GC Roots作为起始点,向下搜索,当发现与GC Roots没有关联则判定为可以回收的对象

可作为GC Roots的对象
1. VM Stack(栈帧中的本地变量表)中引用的对象
2. 方法区中类静态属性引用的对象
3. 方法区中常量引用的对象
4. 本地方法栈中JNI引用的对象

垃圾收集算法
1.标记清除(Mark-Sweep):最基础的算法,两点不足:1.效率问题,标记和清除效率都不高 2.空间问题,会产生大量不连续的内存碎片

2.复制算法
把heap分为两块,有用的复制到另一个块,清除原来的块
现代商业JVM都采用这种算法来回收新生代:
将内存划分为较大的Eden和Survivor,HotSpot默认是8:1

3.标记整理

4.分代收集

内存分配与回收策略
1. 对象优先在Eden分配
2. 大对象直接进入老年代(很长的字符串和数组,写代码应当避免短命大对象)
3. 长期存活的对象直接进入老年代
4. 动态对象年龄判断(在Survivor空间中,如果相同年龄所以对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象直接进入老年代)
5. 空间分配担保

参考文献
深入理解Java虚拟机:JVM高级特性与最佳实践/周志明著。-2版

猜你喜欢

转载自blog.csdn.net/qq_33374476/article/details/80909225