学习日记2--JVM(下)

4 篇文章 0 订阅

前面复习了JVM加载过程和JVM的内存区域,其中我们讲到了堆。堆是我们程序员遇到问题最多的地方,也是面试必问的地方,因为堆是垃圾回收主要工作的地方,我们在堆上建立对象,垃圾回收机制负责回收我们不再用的对象,那么引出第一个问题,JVM怎么知道我们那个对象不用了?

如何判定对象为垃圾对象

引用计数法
原理:给对象加一个计数器,当对象被引用时,加1,当引用失效时减1,任何时刻,当计数器为0时,对象被回收。

优点:实现简单,判断效率高
确定:无法解决相互循环引用问题
关于相互循环引用的问题,简单举个例子

Husband hus = new HusBand();
Wife wife = new Wife();
hus.wife = wife;
wife.husband = hus;

上面代码JVM在回收hus时,就必须先回收wife,想回收wife就必须回收hus,这样就会造成相互循环依赖问题。所有我们需要另一种方法来判断对象是否为垃圾对象。

可达性分析法
Java就是根据可达性分析法来判断对象是否存活的。
原理:通过一些列被称为GC ROOT的对象作为起始点,从这些起点向下搜索,搜索的路径称为引用链。如果一个对象到GC ROOT没有任何引用链,则这个对象为垃圾对象。

在这里插入图片描述

如上图,对象1,3和GC ROOT之前存在引用链,所以这两个对象是存活的,相反对象2不存在任何引用链,所以会被垃圾回收

那些对象可以是GC ROOT:
1、 虚拟机栈(栈帧中局部变量表)中引用的对象
2、 方法区中类静态属性引用的对象
3、 方法区中常量引用的对象
4、 本地方法栈中引用的对象

我们知道怎么判定对象为垃圾对象,那么我们怎么去回收它呢?

回收策略

1、 分代收集算法
主要是一种思想,堆分为新生代和老年代,在那一代用那一代的方法。
2、 标记-清除算法
最基础的算法,先标记,标记完成后统一清理(主要运用于老年代)
不足点:
效率低,标记清理效率都低
清除之后,会出现大量不连续空间
3、 复制算法
(复制算法主要用于新生代),之前说过新生代有3个区域,Eden区域和两个s区,其中占比为8:1:1。每次分配内存的时候,会使用Eden和一个S区。垃圾回收时,一次性把活着的对象全部复制到另一个s区,最后清理掉Eden区和用过的s区。这种可以看到每次分配对象都有90%的空间可用,如果特殊情况存活对象超过10%,可能会使用到老年代。
原理:将内存区域分成两块,每次只使用其中一块。垃圾回收时,把活着的对象复制到另一块。在清理用过的那一块。

优点:实现简单,效率快
缺点:只能使用一般的内存
4、 标记-整理算法
(主要用于老年代)在对象存活率比较高的情况下,就会进行较多的复制。复制算法的效率就会变低。根据老年代的特点提出标记-整理算法。
原理:先标记需要回收的对象,然后存活的对象都向一端移动,然后直接清理掉标记的对象。

缺点:效率低
优点:不会造成大部分不连续区域

垃圾回收算法介绍过了,现在复习一下垃圾回收器

垃圾回收器

在这里插入图片描述

图中展示了七种垃圾回收器,其中的连线是表示两个回收器可以配合使用,所在的区域代表它们工作的主要区域。

新生代收集器:Serial,ParNew,Parallel Scavenge
老年代收集器:CMS,Serial old(MSC),Parallel old
正堆收集器:G1

在介绍垃圾收集器的时候,先复习一些概念,有助于我们理解。
(并行和并发区别:并行是你可以同时处理多个任务,并发是你可以处理多个任务,但不是同时,就像CPU执行线程看起来是同时,但是实际是交替执行)
并行收集:指多条垃圾回收线程并行工作,但此时用户线程还处于等待状态
并发收集:用户程序和垃圾线程同时工作(不一定是并行,可能是会交替执行)
吞吐量:CPU运行用户线程时间/CPU运行总时间

1、 Serial收集器
历史最悠久的收集器,单线程收集器
特点:单线程,回收效率快,但是垃圾回收时,用户线程不能运行
2、 ParNew收集器
Serial的多线程版,除了使用多线程,其他和Serial一样
特点:多线程,ParNew默认开启的线程和Cpu个数相同,在CPU个数非常多的情况下,可以使用XX:ParallelGCThreads参数控制,收集时用户线程也会停下(并发收集)
3、 Parallel Scavenge
与吞独量密切相关,故也称为吞吐量收集器
特点:属于新生代收集器用的是复制算法,多线程收集器,与其他收集器不同的是parallel Scavenge收集器的目标是达到一个可控的吞吐量,其他收集器是尽量缩短垃圾收集时用户停顿的时间。
4、 Serial old 收集器
Serial的老年代版本,使用标记-清理算法
5、 Parallel收集器
Parallel Scavenge老年代版本,使用标记-整理算法
6、 CMS收集器
并发收集器,一款以获取最短回收停顿时间为目标的收集器
特点:基于标记-清除算法,低停顿,并发收集。但是对Cpu资源非常敏感,并发收集不会停止用户的线程,但是还是会导致应用程序变慢,无法处理浮动垃圾。
7、 G1收集器
一款面向服务端应用的垃圾回收器,目前最厉害的一款垃圾回收器。
特点:
并行与并发:多线程,充分利用CPU,多个线程回收,缩短用户线程停顿时间。可并发在垃圾回收时不停止用户线程。
分代收集:在新生代和老年代都能用,采用不同的方式管理不同的区域
空间整合:运行期间不会产生不连续空间
可预测的停顿:G1除了追求低停顿,还建立了可预测的停顿时间模型。能让使用者明确指定在一个长度为M毫秒的时间段内,进行垃圾回收。

G1为什么能够建立可预测的停顿时间模型?
因为它有计划的避免在整个堆进行垃圾回收,它把堆分成多个大小相同的Region,G1跟踪每个Region的垃圾堆积大小,维护了一个优先维护列表。在允许的垃圾回收时间,优先收集回收价值最大的Region.

G1存在的问题
Region不可能是独立的,分配在Region的对象可能与任一对象有引用关系,用可达性分析法判断对象是否存活时,需要扫描整个堆,其他收集器也有这个问题,G1比较突出,效率低。

如何解决这个问题?
采用remembered set来避免扫描整个堆,G1每个Region中都有一个remembered set,当虚拟机发现程序对引用类型进行写操作时(就是使用引用),会产生一个write Barrier暂时中断写操作,检查该引用引用的对象是否存在于多个region(就是检查老年代是否引用了新生代的对象)。如果是,便通过CardTable把相关引用信息记录在remembered set中,当进行回收时,加入remembered set就避免了扫描整个堆。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值