java虚拟机内存管理小总结
一、概述
1、可达性分析算法
这个算法是用来来判定对象是否存活。基本思路积水通过一系列的称为“GCROOTs”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用连,当一个对象到 GC ROOTS没有任何引用链相连时,则证明此对象不可用。在java语言中,可以作为GCRoots的对象有:1、虚拟机栈中引用的对象,方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI(即一般说的NATIVE方法)引用的对象、(常量池中的对象引用、方法区中局部变量区的对象引用、在Java操作栈中的对象引用、在本地方法中持有的对象引用、类的class对象)
2、再谈引用
再JDK1.2之后Java对引用概念进行了拓展,将引用分为:
强引用:类似 object obj =new object(),这类的引用,只要强引用存在,垃圾收集器永远不会回收掉被引用的对象。
软引用:用来描述一些还有用,但不是必需的对象。对于软引用关联的对象,在系统将要发生内存溢出之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够额内存,才会抛出内存溢出。在JDK1.2之后,提供了softReference类来实现软引用。
弱引用:也是来描述非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾回收之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2之后,提供了weakreference类来实现弱引用。
虚引用:也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2之后,提供了PhantomReference类来实现虚引用。
3、对象生存还是死亡
即使在可达性分析算法中不可达的对象,也并非非死不可。
一个对象死亡要经过两次标记的过程:
第一次:如果对象在进行可达性分析后发现没有与gc Roots相连的引用链,那它将会被第一次标记并且进行一次筛选。|| 筛选的条件是此对象是否有必要执行finalize()方法。虚拟机将视为没有必要执行的方法:当对象没有覆盖finalize(),或者finalize()方法已经被调用了。
第二次:如果这个对象呗判定为又必要执行finalize(),那么这个对象将会放置在一个叫F-QUEUE的队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。
4、回收方法区
方法区(HOTSpot虚拟机中的永久代)主要回收两部分内容:废弃常量和无用的类。
回收废弃的常量:与回收java堆中的对象非常类似。
回收无用的类:无用的类的定义,一、该类的所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。二、加载该类的classLoader已经被回收。三、该类对应的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
5、垃圾收集算法
标记--清除算法
首先标记需要回收的对象,标记完后统一回收被标记的对象。
不足:效率不高,产生大量不连续的内存碎片,导致大内存分配不足
复制算法
将可用内存分为几份,每次只使用一块,。当一块用完后,就将还存活的对象复制到另一块上去,,然后再把使用过的空间一次性清理掉。
标记-整理算法
根据老年代的特点,标记过程依样与标记算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动。然后直接清理掉边界以外的内存
Serial收集器
Serial收集器是最基本、发展历史最悠久的收集器,是一个单线程的收集器,不仅仅说明是它只会使用一个CPU或者一条收集线程去完成垃圾收集工作,跟重要的是它进行垃圾收集的必须暂停所有的工作线程,直到它收集结束吧。
ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本,可使用多线程进行垃圾收集。。
Parallel Scavenge收集器
是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器。。是一个吞吐量优先的收集器
其特点是达到一个可控制的吞吐量。虚拟机总攻运行100分钟,其中垃圾收集花掉2分钟,那吞吐量就是98%。动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略。
Serial Old收集器
是Serial收集器的老年版本,他同样是一个单线程收集器,使用标记整理算法
Parallel old收集器
Parallel old是Parallel Scavenge收集器的老年版本,使用多线程和标记整理算法。
CMS收集器
CMS收集器是一种以获取最短回收时
包括:
1、初始标记
2、并发标记
3、重新标记
4、并发清除
其中初始标记、重新标记这两个步骤依然需要stop the world,由于整个过程耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,总体上来看CMS收集器的内存回收过程是与用户线程一起的,所以,从总体上来看,CMS收集器的内存回收过程是与用户线程一起并发执行的。
缺点:
CMS收集器对CPU资源非常敏感。
CMS收集器无法处理浮动垃圾,可能出现Concurrent Mode Failure失败导致另一次FULL GC的产生。
CMS收集器使用标记清除的算法导致大量空间碎片。
G1收集器
1、并行并发:能充分利用CPU来缩短停顿时间
2、分代收集 :虽然G1不需要其他收集器配合就能实现分代收集。
3、空间整合:从整体上来说是基于标记整理出来的,从局部来说是采用(两个REGIN之间)采用复制的算法实现的,这两种算法都不会产生空间碎片
4、可预测的停顿:它有计划地避免在整个JAVA堆进行全区域的垃圾收集,G1跟踪各个Region里面的垃圾堆积德价值大小,在后台维护一个优先列表,每次根据如许时间,优先收集价值最大的Region,保证了在有效时间内可以获取高的效率。
它将整个JAVA堆分为多个大小相等的独立区域,虽然还保留有新生代和老年代的概念,但新生代和老年代不在物理隔离了,他们都是一部分regin的结合
包括:
1、初始标记
2、并发标记
3、最终标记
4、筛选回收
6、内存分配与回收策略
1、对象优先在Eden分配
2、大对象直接进入老年代
3、长期存活的对象奖进入老年代
4、动态年对象龄判定
5、空间分配担保