一分钟的深入思考抵得过一小时的盲目寻找

根据对Java对象生命周期的统计,大部分对象只存活一小段时间,存活下来的对象能存活很长时间。Java虚拟机分代回收的思想,也就是从这个统计进行设计的。分代设计就是将堆划分为年轻代和老年代,对象存活时间很短就在年轻代,存活很长时间,就把这个对象移动到老年代。基于分代,就可以针对不同区域使用不同的算法了。年轻代使用耗时较短的回收算法也就是所说的Minor GC,大量的存活下来的对象占据老年代,到一定量级,那么根据算法就会触发全堆扫描--》FULL GC,这个时候就是我们所说的 Stop-the-world。

根据分代思想,我们可以看看Java 虚拟机的堆划分。

JVM将新生代划分为三个区,一个Eden区,两个大小相同的Survivor区。我们新创建的对象,new出来的会放到Eden区中,Eden区中的临时对象会在这里,如果Eden区中的对象进行一次Minor Gc,不能被回收的对象会放到 Survivor的一个区中,每一次进行Minor GC都会进行一次对象的搬运,从Eden区搬运到Survivor区中某一个区域,对象每一次进行搬运都会计数一次,当计数到达15次后,就会把这个合格的对象搬运到永久代中。

卡表--老年代引用新生代对象的解决方案:

堆空间被划分为年轻代和老年代,由于新生代的垃圾收集通常很频繁,如果老年代对象引用了新生代的对象,

那么,需要跟踪从老年代到新生代的所有引用,从而避免每次Minor GC时扫描整个老年代,减少开销。

虽然做了分代,但是由于对象之间的相互调用,老对象又和新对象产生了引用关系,那么就得跑到老年代扫一遍

才能知道引用的新对象是否也该回收了,其实就是循着绳子找东西,本来院子里面的东西要搬走,但是屋子里面的有根绳子

连着院子里面的东西,那么就得到屋子里面寻摸一遍,看看绳子还连着根儿没有,能搬走不能。

对于HotSpot JVM,使用了卡标记(Card Marking)技术来解决老年代到新生代的引用问题。

具体是,使用卡表(Card Table)和写屏障(Write Barrier)来进行标记并加快对GC Roots的扫描。

这个操作在解释执行器中比较容易实现。但是在即时编译器生成的机器码中,则需要插入额外的逻辑。

这也就是所谓的写屏障(write barrier,注意不要和 volatile 字段的写屏障混淆)。

基于卡表(Card Table)的设计,通常将堆空间划分为一系列2次幂大小的卡页(Card Page)。

卡表(Card Table),用于标记卡页的状态,每个卡表项对应一个卡页。

HotSpot JVM的卡页(Card Page)大小为512字节,卡表(Card Table)被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。

当对一个对象引用进行写操作时(对象引用改变),写屏障逻辑将会标记对象所在的卡页为dirty。

首先,计算对象引用所在卡页的卡表索引号。将地址右移9位,相当于用地址除以512(2的9次方)。

可以这么理解,假设卡表卡页的起始地址为0,那么卡表项0、1、2对应的卡页起始地址分别为0、512、1024(卡表项索引号乘以卡页512字节)。

其次,通过卡表索引号,设置对应卡标识为dirty。

1.无条件写屏障带来的性能开销#

每次对引用的更新,无论是否更新了老年代对新生代对象的引用,都会进行一次写屏障操作。

显然,这会增加一些额外的开销。但是,与YGC时扫描整个老年代相比较,这个开销就低得多了。

不过,在高并发环境下,写屏障又带来了虚共享(false sharing)问题。

2.高并发下虚共享带来的性能开销#

在高并发情况下,频繁的写屏障很容易发生虚共享(false sharing),从而带来性能开销。

假设CPU缓存行大小为64字节,由于一个卡表项占1个字节,这意味着,64个卡表项将共享同一个缓存行。

HotSpot每个卡页为512字节,那么一个缓存行将对应64个卡页一共64*512=32KB。

如果不同线程对对象引用的更新操作,恰好位于同一个32KB区域内,这将导致同时更新卡表的同一个缓存行,从而造成缓存行的写回、无效化或者同步操作,间接影响程序性能。

一个简单的解决方案,就是不采用无条件的写屏障,而是先检查卡表标记,只有当该卡表项未被标记过才将其标记为dirty。

这就是JDK 7中引入的解决方法,引入了一个新的JVM参数-XX:+UseCondCardMark,在执行写屏障之前,先简单的做一下判断。如果卡页已被标识过,则不再进行标识。

简单理解如下:

Copy

if (CARD_TABLE [this address >> 9] != 0)

CARD_TABLE [this address >> 9] = 0;

与原来的实现相比,只是简单的增加了一个判断操作。

虽然开启-XX:+UseCondCardMark之后多了一些判断开销,但是却可以避免在高并发情况下可能发生的并发写卡表问题。通过减少并发写操作,进而避免出现虚共享问题(false sharing)。

垃圾回收算法还有很多,思路和思想都是提高回收效率,减少对系统的影响,另外还有一个空间利用率问题 。

备注:文中一部分是基于自己整理,一部分是对网络上的内容的摘录整合。

incompatible jvm_JVM垃圾回收回收算法详解相关推荐

  1. JVM之垃圾回收算法详解

    JVM之垃圾回收算法详解 现有的垃圾回收算法 分类 垃圾收集器的设计原则 标记-清除算法 缺点 标记-复制算法 "Apple回收策略" 缺点 标记-整理算法 缺点 总结 现有的垃圾 ...

  2. JVM底层原理+四大垃圾回收算法详解-周阳老师

    转载自,感谢原作者:https://www.jianshu.com/p/9e6841a895b4 注意:垃圾回收算法周阳老师讲的有错误,具体在p19,四大垃圾回收算法为复制算法.标记-整理算法.标记- ...

  3. 操作系统之银行家算法—详解流程及案例数据

    操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...

  4. JVM之垃圾收集机制四种GC算法详解

    JVM之四种GC算法详解 目录: 什么是GC? GC算法之引用计数法 GC算法之复制算法(Copying) GC算法之标记清除(Mark-Sweep) GC算法之标记压缩(Mark-Compact) ...

  5. 基于内容的推荐算法详解+问题思考

    前言 最近参加了一个推荐的比赛,就像了解一些推荐相关的技术,也跟着学习总结一下,相同的内容不同的理解,我也要记录下我的思考. 场景 我们假设一个电商的场景,电商有很多商品,怎么把商品推荐给用户 就是我 ...

  6. Matlab人脸检测算法详解

    这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...

  7. 图论-最短路Dijkstra算法详解超详 有图解

    整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...

  8. C++中的STL算法详解

    1.STL算法详解 STL提供能在各种容器中通用的算法(大约有70种),如插入.删除.查找.排序等.算法就是函数模板,算法通过迭代器来操纵容器中的元素.许多算法操作的是容器上的一个区间(也可以是整个容 ...

  9. 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码

    粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...

  10. 基础排序算法详解与优化

    文章图片存储在GitHub,网速不佳的朋友,请看<基础排序算法详解与优化> 或者 来我的技术小站 godbmw.com 1. 谈谈基础排序 常见的基础排序有选择排序.冒泡排序和插入排序.众 ...

最新文章

  1. 大厂AI面试官一语中的:一场面试暴露了你的机器学习水平
  2. JavaFX 2.0布局窗格– HBox和VBox
  3. JQuery实现广告效果(滚动切换)
  4. 【BZOJ】【3295】【CQOI2011】动态逆序对
  5. SQLi LABS Less-3 联合注入+报错注入
  6. esxi安装报错解决方案
  7. Linux-Kali——解决Gnome桌面右键菜单无法打开terminal终端的问题
  8. 5.2 BP误差逆传播
  9. 计算机怎么看事件管理,用事件查看器查看电脑使用记录
  10. 树型选择器/Browsing HDFS筛选文件类型
  11. 两只PNP晶体三极管和四个电阻组成恒流源电路
  12. 计算机为什么设ip,怎么设置电脑ip
  13. Latex角度输入(°)
  14. HTTP协议、【HTTP请求、响应格式】及一次HTTP请求的完整过程
  15. Docker-三剑客之machine、compose、swam集群、visualizer监控、stack部署集群、Portainer可视化
  16. JavaScript学习(十八)--鼠标事件(鼠标点击松开移动效果)
  17. 产品经理:想爱没那么简单
  18. 【CLYZ集训】买棉花糖【分治】【背包】
  19. 华为音频编辑服务,助力开发者高效创新
  20. paypal开发整理文档(14)——PayPal Orders API整理

热门文章

  1. javascript 获取DropDownList选定值的方法
  2. Windows批处理符号简介、常用Dos命令
  3. 【Android】17.1 Bound Services基本概念
  4. 事件EVENT与waitforsingleobject的使用以及Mutex与Event的区别
  5. WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变...
  6. 弹出模态窗口,关闭并刷新页面
  7. 获取jpg图片的x,y的分辨率dpi
  8. 转贴:匹配中文的正则表达式及其他
  9. 计算机参评高校168所,168所大学排行榜单!计算机科学与技术专业哪些高校专业实力最强!...
  10. OJ1078: a+b(多实例测试1)(C语言数组解题)