垃圾回收机制
垃圾回收:回收掉不被使用并占用内存空间的对象。
一.如何定位需要回收的对象?
1.引用计数算法
给对象添加一个引用计数器,每当一个对象被引用则+1,当引用被减少则—1,当计数为0时,任何被标记为0的对象都为可回收对象。
弊端:当两个对象互相引用而没有别的对象引用他们时,会出现无法回收的情况,因为他们的计数器不为0。
2.根可达性分析算法
将GC Roots 对象作为起点,从这些节点向下搜索引用的对象,找到的对象都标记为非垃圾对象,
二.收集器主要运用了哪些算法?
1.标记清除算法(Mark-Sweep)
标记和清除分为两个阶段
一 标记,通过根可达性,遍历可达对象标记为活动对象,
二 清除,在标记阶段完成后,回收器会遍历清除未标记对象,清除操作主要是将未标记对象的内存标记为可用内存,添加到可用内存列表,由于对象不连续会导致内存位置不连续产生磁盘碎片,无法存储较大对象。
弊端:位置不连续,产生磁盘碎片,在执行阶段其他线程暂停会造成卡顿的效果
2.标记整理算法(Mark-Compact)
一 标记,通过根可达性,遍历可达对象标记为活动对象,
二 整理,在标记结束后,根据标记状态进行位置调整,活动对象往前移,未标记对象往堆的末尾移动
弊端:效率较低,消耗资源
3.复制算法(Copying)
将内存分为两个区域,from和to区,首先将from区可达对象复制到to区,此时from区全部是垃圾,清空from区,将to区和from区交换位置,等待下一次回收
弊端:需要双倍空间,
三. 有哪些垃圾收集器?
- serial 串行化,(新生代),单线程收集器,使用标记复制算法完成收集,STW
- serial old 单线程收集器 (老年代)标记整理算法 STW
- parNew (新生代)多线程
- paralel scavenge (新生代) 多线程 复制标记算法
- paralel old 老年代 多线程,整理清理算法
- cms (ConcurrentMarkSweep)
获取最短回收停顿时间为目标的收集器,基于标记清除算法实现,用户线程不会暂停,会产生浮动垃圾。
注:
一 当线程过程中用户线程产生了垃圾没有被标记到这种现象称为浮动垃圾。
二 当对象已经被标记为垃圾对象后又被引用,这种称为漏标。所以在整个过程中会进行第二次标记。
流程:GC开始标记,初始标记,并发线程,重新标记,标记清除
jdk1.8 使用:parallelScavenge+parallerlOld
四.垃圾回收类型有哪些?
一. 部分收集
- 新生代收集 minor gc / young gc 只收集新生代
- 老年代收集 major gc / old gc。只收集老年代
- 混合收集 fixed gc 对整个新生代和部分老年代进行收集
二. 整堆收集
- full GC 收集整个堆和方法区
如何触发full gc?
新生代空间不足时,触发 minor gc,
当老年代空间不足时会先触发minor gc。如果空间仍然不足则进行full gc stw时间更长。
五. VM调优 可配置参数
参数 | 含义 |
---|---|
-Xms | 用于设置JVM初始分配的堆内存大小,即Java虚拟机启动时所占用的内存大小 |
-Xmx或–XX:MaxHeapSize=size | 设置最大 Java 堆大小,最大不应该超过总内存的70% |
-Xmn或(–XX:NewSize=size+ -XX:MaxNewSize=size) | 设置新生代大小。整个堆大小=新生代大小 + 年老代大小 + 常量池Sun官方推荐配置为整个堆的3/8 |
–XX:InitialSurvivorRatio=ratio和–XX:+UseAdaptiveSizePolicy | 根据应用使用情况,自动调整幸存区的比例。可以根据年轻代(Y)大小和初始幸存区比例®来计算幸存区初始空间(S)大小,公式:S=Y/(R+2)。公式中的 2 代表有2个幸存区,幸存区初始比例®越大,则幸存区初始空间越小。默认值 8。如果年轻代空间是 2MB,幸存区空间则为 0.2 MB。 |
-XX:SurvivorRatio=ratio | 设置 eden 区和幸存区 survivor 区比率。默认值 8。 |
-XX:MaxTenuringThreshold=threshold | 即年轻代晋升老年代的最大年龄阈值。默认值是15 |
-XX:+PrintGCDetails -verbose:gc | 用于打印输出详细的GC收集日志的信息 |
-XX:+PrintTenuringDistribution | 打印晋升年龄信息。默认禁用此选项。 |
-XX:+ScavengeBeforeFullGC | 新生代GC优先于Full GC执行 |
六. 回收流程
- 新生代分为 Eden区(8/10),Servivor From(1/10),Servivior To(1/10)三个区域
新建对象在eden区 - 在eden区满了以后执行引擎开启垃圾收集线程(GC线程)minorGC对新生代进行一次垃圾回收
- 使用根可达性分析算法判断是否为垃圾对象,如果可以找到则被分到Servivor From区域,对象计数+1
- 当再次进行GC时,eden区幸存对象放入ServivorFrom区,ServivorFrom也被扫描,幸存对象则被放到Servivor
To中,计数+2 - 当对象经过15次GC还被引用的时候,会被放入老年代
注
在GC中可以把堆分为两个区,新生代,老年代。
默认分配内存的新生代1/3,老年代2/3。
七. 部分名词解释
Stop-The-World机制–STW
Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)
OOM
当老年代满了会出现 OutOfMermonyException 内存溢出异常