JVM - 内存及垃圾回收
1、jvm运行时数据区域
-
方法区
线程共享
存储加载的Class信息、常量、静态变量,
也称为永久代(perm区)
内存无法扩展时,抛出OutOfMemoryError
-
虚拟机栈
线程私有
每个方法被执行时都会创建,存储局部变量表、操作数栈、动态链接、方法出口等。局部变量表存放的基本数据类型及对象引用
如果线程请求的栈深度大于jvm允许的深度,抛出*Error;如果虚拟机栈动态扩展时无法申请到足够的内存,抛出OutOfMemoryError
-
本地方法栈
- 与虚拟机栈类似,但是为Native方法服务,虚拟机栈为Java方法服务
-
堆
线程共享
存储所有对象实例及数组
细分为新生代和老年代,新生代包括Eden,From Survivor,To Survivor
内存无法扩展时,抛出OutOfMemoryError
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 )
新生代中,默认:Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 )
-
程序计数器
线程私有
较小内存,当前线程执行的字节码的行号指示器,没有规定OOM
2、GC
2.1、 判断对象是否可用
当对象到GC Roots没有任何引用链时,则对象不可达,即对象不可用
-
GC Roots的对象:
虚拟机栈中的引用的对象
方法去中类静态属性引用的对象
方法区中常量引用的对象
native方法引用的对象
2.2、引用
-
强引用
- 最常用的引用,只要存在,对象就不会被回收
-
软引用(Soft Reference)
用来描述还有用,但并非必需的对象
对于软引用的对象,系统将要发生内存溢出之前,将会把这类对象进行二次回收
-
弱引用(Weak Reference)
- 弱引用的对象只能存活到下一次垃圾收集发生之前,当垃圾回收时,弱引用的对象会被回收掉
2.3、垃圾收集算法
-
复制算法
用于新生代
分配内存时,每次使用Eden和S0,回收时,将存活的对象拷贝到S1,最后清理掉Eden和S0
-
标记-整理算法
用于老年代
先标记需要清理的内存,将存活的对象都向一端移动,然后清理掉边界意外的内存
2.4、内存分配及回收策略
对象优先在Eden分配,当Eden区没有足够的空间时,会发起一次Minor Gc
大对象直接进入老年代
长期存活的对象将进入老年代,对象在Survivor每熬过一次Minor GC,年龄就加1,年龄达到一定值(年龄阈值默认15,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域