JVM 学习笔记(二)——垃圾回收器和内存分配策略

       不好意思,因为最近新入职一个公司项目特忙,现在才想起有篇笔记未上传。。。让大家看了半截,万分抱歉。废话不多说,进入正题。

一.了解GC和内存分配的原因

  提高Java应用性能,排除问题。写出健壮性代码。

 

二.To Be Or Not To be(判断对象的存活)

1. 引用计数算法:

简介:对于创建的每一个对象都有一个与之相关联的计数器(类似于映射关系表),这个计数器记录这

每一个对象的使用次数,对扫描到的每一个对象判断它的计数器是否为0,若等于0,则释放该对象占用

的内存空间,同时将该对象引用的其它计数器进行减一操作。

 

实现方式:

一、侵入式

将引用计数器直接根植在对象内部,用C++的思想进行解释就是,在对象的构或者拷贝构造中进行加一

操作,在对象的析构中进行减一操作。

二、非侵入式

有一个单独的内存区域,用作引用计数器。

 

算法的优点:

使用引用计数,内存回收可以穿插在程序运行中,在程序运行中,如果发现某一个对象的引用计数器为

0时,可以立即对该对象占用的内存空间进行回收,这种方式可以避免FULL GC 带来的程序暂

(STOP THE WORLD).

 

算法的缺点:不能解决循环引用的问题,例如:一个对象A引用了对象B,而对象B又引用了A,形成相

互的循环引用(闭环)。这种情况会导致对象一直在JVM内存中(堆),无法进行回收。

 

2. 可达性分析

在主流的商用应用程序语言(Java ,C++,老爷爷Lisp)的主流实现中,都是称通过可达性分析

(Reachability Analysis)来判断对象是否存活的。这个算法的基本思想就是通过一系列的成为“GC

Roots”的对象作为起始点,从这些节点(GC Roots)开始向下搜索,搜索所走过的路径成为引用链

(Reference Chain),对一个对象到GC Roots 没有任何引用引用链相关联时(类似树状结构,关联不

到的就像断掉了的树枝),则证明此对象是不可用的。

在Java中,可作为GC Roots 的对象包括下面几种;

一、JVM栈(栈帧中本地变量表)中引用的对象。

二、方法区中:类静态属性引用的对象。

三、方法区中:常量引用对象(static final A=new A())。

四、本地方法栈中JNI(Native方法)引用的对象。

 

三.引用

1. 强引用(Strong SoftReference ):

程序中普遍存在的,类似于 Object obj = new Object(),这类的引用,只要强引用还在,GC永远不会回

收掉被引用的对象。

 

2. 软引用(JDK1.2 之后提供 SoftReference 有用非必须对象):

一般做缓存用,跟强引用区别:GC在回收时,JVM会根据当前系统的剩余内存来判断是否对软引用进

行回收,如果内存比较紧张回收软引用内存空间,如果富足则不会回收。意味着在没有足够内存空间发

生OOM(OutOfMemoryError)之前,JVM会把这些对象列进回收范围之中进行二次回收。

 

3. 弱引用(JDK1.2 之后提供 Weak Reference 有用非必须对象)

一般做缓存用,跟软引用类似,区别在于它的生命周期在下次GC回收之前一定会结束被回收掉。所以

它的生命周期在一个垃圾回收周期内。

 

4.需引用(Phantom Reference)

最弱的一种引用关系,一个对象是否有虚引用,不会影响其生存时间,也不能通过其来取得的一个对象

的实例。唯一作用:在一个对象回收时收到一个系统通知。

 

四.GC 回收算法

1. 标记——清除算法(Mark Sweep):

分为两个阶段 “标记”和“清除”两个阶段;首先标记出所有需要回收的对象,在标记完成后统一回收所有

被标记的对象(适合年老代)。

 

算法的缺点:

效率不高(标记 和 清除 过程费时),空间问题(内存碎片化--在分配较大内存时,如果无法找到足够

的连续内存会触发另一次GC回收动作)

 

2. 复制算法(Copying):

为解决标记——清除算法效率问题出现,以空间换时间,它将可用内存划分成两块相同大小的区域,每

次只使用一块内存,当这一块内存区域使用完了,就将这块内存区域存活的对象复制到另一块内存区

域,然后把已使用过的内存空间一次清理掉。这样每次回收都整个一半区域回收,不用考虑内存碎片

化。

 

算法的优点:

实现简单,运行高效,内存规整。

 

算法的缺点:

空间换时间。

 

注解:Copying算法一般用来回收新生代,因为新生代98%(一般场景)的对象都是可能会被回收的,不

需要按照1:1的比例还划分内存空间,而是将内存划分为一块较大的Eden空间和两块较小的

(A,B)Survivor,每次使用过只使用Eden 和 ASurvivor 。当回收时,将Eden 和 ASurvivo存活的对象一

次性复制到BSurvivor(如果存活对象内存大于BSurvivor,需要依赖年老代进行分配担保——Handle

Promotion),HotSpot 虚拟机Eden 和 Survivor和默认分配比例为8:1。

 

2. 标记——整理算法(Mark Compact):

因为Copying算法适用新生代,年老代对象的存活率较高,甚至可能达到100%存活的可能性。不适合年

老代,所以由Mark Sweep优化了另一种算法Mark Compact,把最后回收步骤变更为让所有对象想一端

移动,然后清除顶端指针以外的内存。(适合年老代)

 

算法的优点:

内存很规整。

 

算法的缺点:

因为需要需要移动对象,效率和内存会有所影响。

 

五.分代收集算法

垃圾收集器之间的关系链

 

 

一般Java把堆分为新生代、年老代两块。根据这两块区域的对象生命周期的长短,适用于不同的GC回

收算法(新生代——>Copying 、年老代——>Mark Compact、Mark Sweep)。

 

六.垃圾收集器

1. Serial 收集器:

单线程,适用于新生代(-Xmn)、使用复制算法(Copying)在进行回收工作时,其他线程会全部暂停

(STOP THE WORLD)直至它工作结束,由虚拟机后

台自动发起和结束(用户不可见、会出现程序停滞情况,对用户不友好)

运行示意图:

 

2. ParNew 收集器:

并行多线程 ,适用于新生代(-Xmn)、使用复制算法(Copying)Serial 的多线程版本。

运行示意图:

3. Parallel Scavenge 收集器:

新生代收集器、适用于新生代(-Xmn)、使用复制算法(Copying)并行多线程收集器,吞吐量优先收

集器,目的是达到一个可控的吞吐量(吞吐量 = 运行用户代码时间/(运行用户代码时间 + 垃圾收集时

间)),适合后台运算。

-XX:MaxGCPauseMills 最大垃圾收集器停顿时间(大于0值);

-XX:GCTimeRatio 吞吐量大小值

-XX:+UseAdaptiveSizePolicy动态调整新生代大小(-Xmn)、Eden于 Survivor 的比例,晋升老年代对

象大小等参数,以提供最合适的时间或者最大的吞吐量(GC 自适应的调节策略 (GC Ergonomics))

运行示意图:

 

4. Serial Old 收集器

单线程、适用于年老代、使用标记——整理 (Mark Compact)算法, Serial 的年老代版本。

运行示意图:

5. Parallel Old 收集器

并行的多线程、适用于年老代、使用标记——整理 (Mark Compact)算法, Parallel Scavenge 的年

老代版本。运行示意图:

6. CMS 收集器

并行并发收集器、适用于年老代、使用标记——清除 (Mark Sweep)算法,以获取最短回收停顿时间

为目标的收集器,重视服务器的响应速度,希望系统时间停顿最短,适用用web应用程序。

运作过程:

一、初始标记(CMS initial mark)

需要(STOP THE WORLD),仅仅只是标记一下GC Roots 能直接关联到的对象,速度快。

二、并发标记(CMS concurrent mark)

进行GC Roots Tracingd 过程。

三、重新标记(CMS remark)

需要(STOP THE WORLD),仅仅只是标记一下GC Roots 能直接关联到的对象,速度快。(修正在

并发期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录——停顿时间比CMS

initial mark长比CMS concurrent mark短)。

四、并发清除(CMS concurrent sweep)

基于标记记录,直接清理对象。

运行示意图:

7. G1 收集器

并行并发收集器、适用于年老代、新生代(-Xmn)使用标记——整理 (Mark Compact) + 化整为零

算法,以获取最短回收停顿时间。

 

以上就是全部内容了,g1的我只是简单看了一下,没有什么深入去了解,所有没简单提一下,不过个人感觉如果不是专门去做底层开发的只要简单了解一下就可以了,因为后期还有zgc这么一个更强大的收集器,现在资料少的可怜。需要大家自行去找找资料了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值