深入理解jvm 一 垃圾收集器与内存分配策略

1、对象生与死(判断对象存活依据)

典型的判断对象存活的算法:引用计数算法

每当有一个地方引用该对象,该对象计数器加1,引用失效减1,任何时刻计数为0的对象都是待宰的。

特点高效,简单,但是互相引用时会出现对象一直存活的情况。

由此java选择可达性分析算法来判断对象生死

基本思路:通过GC Roots对象做起点,从节点往下搜索,搜索路径成为引用链。如果从GC Roots到对象不可达,则判死缓

何为死缓:可达性分析中判定为不可达的对象会被标记为不可达,之后要进行第二次筛选,筛选条件判断此对象是否有必要执行finalize方法。如果对象没有覆盖finalize方法或者finalize方法被虚拟机调用过(只调一次),都将被视为没有必要执行!    如果这个对象被判定有必要执行finalize方法,那么这个对象会被放置在FQueue队列,并由一个虚拟机自动建立的低优先级的finalizer线程去执行,如果该线程发生了死循环,运行缓慢等因素,也会被干掉。如果执行成功,即与引用链的任意对象建立关联,都会成功活下来

可作为GC Roots的对象:

虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区的类静态属性引用对象
方法区中常量引用的对象
本地方发展中Native方法引用的对象

如果引用的数量过多仍然会导致GC出发回收行为,由此产生引用强度的分级。按照分级来决定回收哪些引用。

强引用  new创建出的引用只要存在永不回收  永不回收
软引用  还有用但是并非必须的对象  内存溢出前将这些对象进行回收
弱引用  非必需对象  无论内存是否足够,都会回收
虚引用

 一个对象是否有虚引用的存在,完全不会对其生存时间够成影响

。也无法通过虚引用来取得一个对象实例。

为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知

 回收时发通知

永久带(方法区)进行垃圾回收是困难并且条件苛刻的!

永久带主要回收的两部分内容:废弃常量无用的类

废弃常量回收:如果没有任何对象引用常量池的常量,并且也没有其它地方引用该字面量,如果内存回收并且必要的话,这个常量会被回收。

无用类回收:1、该类所有实例都被回收。2、加载该类的classloader被回收。3、该类对应的java.lang.class对象没有在任何地方被引用,并且诶无法在任何地方通过反射的方式访问该类。满足上面三条就会被回收


2、垃圾收集算法

算法名称 算法描述 优点 缺点 存在代区域  
标记-清除算法

首先标记出所有需要回收的对象,其次统一回收标记对象。


简单

1、标记和清除效率低下

2、大量不连续空间

老年代  
复制算法

 将内存分成大小相同的两个块儿,每次使用一块,当内存满了时候,将存活对象复制到另一块上,再把之前的那一块儿清除掉。

后来改进:

将内存分成一块儿Eden和两块儿Survivor区域。空间比例为8:1。当survivor空间不足,需要通过类似银行贷款似的分配担保机制借老年代空间并按时偿还

 没有内存不连续的情况,简单,高效  大大缩小了内存的空间  新生代  
标记-整理算法  类似标记清除,只不过清除后所有存活对象移动到空白内存区域,以创建连续的内存空间  能创造连续空间  效率问题  老年代  
分代收集算法  根据新生代和老年代的特点,选择合适的算法如新生代复制算法+老年代标记清除或者标记整理算法  连续的新生代和老年代空间  老年代效率问题  新老代  
           

3、垃圾收集器

收集器名称 线程 算法 特点 场景
serial
单线程 复制算法 新生代 必须停止所有线程工作直至收集完成 Client
PerNew 多线程 复制算法 新生代 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作; Server模式
Parallel Scavenge 多线程 复制算法 新生代  Parallel Scavenge收集器的目标则是达一个可控制的吞吐量(Throughput); 后台进行计算,而不需要与用户进行太多交互
Serial Old 单线程 标记-整理 老年代 Serial Old是 Serial收集器的老年代版本; Client模式
Parallel Old 多线程 标记-整理 老年代   Parallel Old垃圾收集器是Parallel Scavenge收集器的老年代版本; Server模式
CMS 多线程并发 标记-清除 老年代 初始标记:仅标记一下GC Roots能直接关联到的对象,需要"Stop The World"。
并发标记:进行GC Roots Tracing的过程,刚才产生的集合中标记出存活对象。
重新标记: 为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录,需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短。
并发清除: 回收所有的垃圾对象。
整个过程中耗时最长的并发标记和并发清除都可以与用户线程一起工作;
所以总体上说,CMS收集器的内存回收过程与用户线程一起并发执行;
用户交互较多
G1 多线程并行与并发 标记-整理算法 /
复制算法
/ 并行与并发, 能独立管理整个GC堆(新生代和老年代),
而不需要与其他收集器搭配;将整个堆划分为多个大小相等的独立区域,
结合多种垃圾收集算法,空间整合,不产生碎片
可预测的停顿:低停顿的同时实现高吞吐量
  面向服务端应用

猜你喜欢

转载自blog.csdn.net/qq_31615049/article/details/80279816
今日推荐