对什么区域进行垃圾回收?
- 1.堆
- 2.方法区中静态属性引用的对象
- 3.方法区中常量引用的对象
- 4.本地方法栈中JNI引用的对象
例如: private native void sort(int[] array);
栈是线程私有的,不需要回收
什么情况下回收?
- 1.当引用计数器为0(循环调用则会出问题)
- 2.可达性分析遍历不到的对象进行回收.
四种引用:
- 强引用:可达性分析不可达的情况下,会被GC
- 软引用:内存不足时,会被GC
- 弱引用:只能存活到下一次GC前
- 虚引用:不会对对象的生命周期有任何影响,无法通过它获取对象实例,唯一的作用就是在对象被GC回收前收到一个通知.
JVM内存分配策略:
1.对象优先在Eden分配
大多数情况下,对象在新生代Eden区中分配。
2.大对象直接进入老年代
大对象是指,需要大量连续内存空间的java对象(字符串,数组).-XX:PretenureSizeThreshold可以令大于这个值的对象直接在老年代分配内存,可以避免在Survivor区域发生大量的内存复制.
XX:PretenureSizeThreshold 该参数只能在ParNew和Serial两款收集器使用.
3.动态对象年龄判断
如果Survivor空间中的相同年龄的所有对象大小的总和大于Survivor空间的一半,大于该年龄的对象直接进入老年代.
4.长期存活的对象将进入老年代
对象在Survivor每熬过一次GC,对象年龄就会加1,当年龄到达默认值15,则进入老年代
5.空间分配担保
检测老年代的可用连续空间是否大于即将晋升到老年代的对象的大小,如果大于,则进行一次MinorGC,如果小于,或者设置不允许冒险,那次时需进行一次FullGC.
垃圾回收算法:
1.标记-清除算法
分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.
缺点:
- 效率不高
- 会产生不连续的内存碎片,空间碎片太多可能会导致以后在程 序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作
2.复制算法
将可用内存分为大小相等的两个区域,每次只使用其中一片区域.当这一片区域用完了,再将还活着的对象复制到另一块区域,将之前区域的对象清理掉.
缺点:
- 1.内存缩小为原来的一半,内存利用率太低
- 2.如果对象存活率高,复制浪费时间
3.标记-整理法
分为标记和整理两个阶段,先标记出所有需要回收的对象,然后将存活对象整理到内存的一端.然后清除回收的对象
4.分代回收算法
- 年轻代采用标记清除和整理算法
- 老年代采用复制算法