OpenJDK17-JVM 源码阅读 - ZGC - 并发标记 | 京东物流技术团队
ZGC简介:
ZGC是Java垃圾回收器的前沿技术,支持低延迟、工具大容量堆、调试调试染色指针、工具读屏障等特性,调试调试自JDK起作为试验特性,工具网上源码下载JDK起支持Windows,调试调试JDK正式投入生产使用。工具在JDK中已实现分代收集,调试调试预计不久将发布,工具性能将更优秀。调试调试
ZGC特征:
1. 低延迟
2. 大容量堆
3. 染色指针
4. 读屏障
并发标记过程:
ZGC并发标记主要分为三个阶段:初始标记、工具并发标记/重映射、调试调试重分配。工具本篇主要分析并发标记/重映射部分源代码。调试调试
入口与并发标记:
整个ZGC源码入口是ZDriver::gc函数,其中concurrent()是一个宏定义。并发标记函数是concurrent_mark。
并发标记流程:
从ZHeap::heap()进入mark函数,使用任务框架执行任务逻辑在ZMarkTask里,具体执行函数是work。工作逻辑循环从标记条带中取出数据,直到取完或时间到。此循环即为ZGC三色标记主循环。之后进入drain函数,从栈中取出指针进行标记,直到栈排空。标记过程包括从栈取数据,尾盘买 源码标记和递归标记。
标记与迭代:
标记过程涉及对象迭代遍历。标记流程中,ZGC通过map存储对象地址的finalizable和inc_live信息。map大小约为堆中对象对齐大小的二分之一。接着通过oop_iterate函数对对象中的指针进行迭代,使用ZMarkBarrierOopClosure作为读屏障,实现了指针自愈和防止漏标。
读屏障细节:
ZMarkBarrierOopClosure函数在标记非静态成员变量的指针时触发读屏障。慢路径处理和指针自愈是核心逻辑,慢路径标记指针,快速路径通过cas操作修复坏指针,并重新标记。
重映射过程:
读屏障触发标记后,对象被推入栈中,下次标记循环时取出。ZGC并发标记流程至此结束。
问题回顾:
本文解答了ZGC如何标记指针、三色标记过程、如何防止漏标、指针自愈和并发重映射过程的问题。
扩展思考:
ZGC在指针上标记,当回收某个region时,如何得知对象是否存活?答案需要结合标记阶段和重分配阶段的代码。
结束语:
本文深入分析了ZGC并发标记的源码细节,对您有启发或帮助的话,请多多点赞支持。龙头公式源码作者:京东物流 刘家存,来源:京东云开发者社区 自猿其说 Tech。转载请注明来源。
这究竟是为什么呢?都说JVM能实际使用的内存比-Xmx指定的少,头大
这确实是个挺奇怪的问题,特别是当最常出现的几种解释理由都被排除后,看来JVM并没有耍一些明显的小花招:
要弄清楚这个问题的第一步就是要明白这些工具的实现原理。通过标准APIs,我们可以用以下简单语句得到可使用的内存信息。
而且确实,现有检测工具底层也是用这个语句来进行检测。要解决这个问题,首先我们需要一个可重复使用的测试用例。因此,我写了下面这段代码:
这段代码通过将new int[1__]置于一个循环中来不断分配内存给程序,然后监测JVM运行期的当前可用内存。当程序监测到可用内存大小发生变化时,通过打印出Runtime.getRuntime().maxMemory()返回值来得到当前可用内存尺寸,输出类似下面语句:
实际情况也确实如预估的那样,尽管我已经给JVM预先指定分配了2G对内存,在不知道为什么在运行期有M内存不见了。你大可以把 Runtime.getRuntime().maxMemory()的返回值2,,K 除以来转换成MB,那样你将得到1,M,正好和M差M。
在成功重现了这个问题之后,我尝试用使用不同的GC算法,果然检测结果也不尽相同。
除了G1算法刚好完整使用了我预指定分配的2G之外,其余每种GC算法似乎都不同程度地丢失了一些内存。web源码教程
现在我们就该看看在JVM的源代码中有没有关于这个问题的解释了。我在CollectedHeap这个类的源代码中找到了如下的解释:
我不得不说这个答案藏得有点深,但是只要你有足够的好奇心,还是不难发现的:有时候,有一块Survivor区是不被计算到可用内存中的。
明白这一点之后问题就好解决了。打开并查看GC logging 信息之后我们发现,在Serial,Parallel以及CMS算法回收过程中丢失的那些内存,尺寸刚好等于JVM从2G堆内存中划分给Survivor区内存的尺寸。例如,在上面的ParallelGC算法运行时,GC logging信息如下:
由上面的信息可以看出,Eden区被分配了,K,两个Survivor区都被分配到了,K,老年代(Old space)则被分配了1,,K。把Eden区、老年代以及一个Survivor区的尺寸求和,刚好等于2,,K,说明丢失的那M(,K)确实就是剩下的那个Survivor区。
总结而言,当JVM在运行时报告的可使用内存小于-Xmx指定的内存时,差值通常对应于一块Survivor区的大小。对于不同的GC算法,这个差值可能有所不同。
jvmè°è¯å·¥å ·ç±»ä½¿ç¨ (jvisualvm.exe)
ç®æ ï¼ä½¿ç¨JDKèªå¸¦çJVMçæµå·¥å ·è°è¯å å使ç¨æ åµåå æ é®é¢ææ¥ç®è¦è¯´æï¼å¨å®é 项ç®å¼åè¿ç¨ä¸ï¼å¦æ使ç¨å¤çº¿ç¨ï¼ä½æ¯æ²¡ææ§å¶å¥½çº¿ç¨æ°éçæ åµä¸ï¼å°±ä¼åºç°å å å溢åºé®é¢ï¼å¯¼è´åè½æå¡å®æºï¼å¦æ严éå¾å¯è½å¯¼è´æå¡å¨å®æºé®é¢ãå½åºç°å å溢åºæ¶ï¼åªè½çå°ç®åçå å溢åºæ¥å¿ï¼ææ¥é®é¢æ¯«æ 头绪ï¼ä¸ç¥éåªé线ç¨åºç°é®é¢ï¼è¿æ ·å°±å¾é¾è§£å³é®é¢ï¼
è¿æ¶æ们就å¯ä»¥éè¿JDKèªå¸¦çJVMçæ§å·¥å ·æ¥çæ¯ä¸ªçº¿ç¨ççå½å¨æ以åç¸å ³æºç 追溯ï¼è¿æ ·å°±å¯ä»¥æ¸ æ¥æäºççæ¸ é®é¢åºç°å¨åªéï¼ç¶åæ ¹æ®å®é æ åµè§£å³é®é¢ï¼
éè¿ä¸å¾å¯ä»¥çå°æ¬å°æå¡ä¸ææç线ç¨åç¸å ³ç¶æï¼å¦æ线ç¨åºç°é®é¢éè¦ææ¥æ¶ï¼éè¦æ¥çå ·ä½æ§è¡çæ¹æ³ï¼é£ä¹å°±éè¦å¿«ç §æ¹å¼æ¥çï¼å ·ä½æ¹å¼å¦ä¸ï¼
ç¹å»æ½æ ·å¨ï¼ç¶åéæ©CPUæ½æ ·ï¼ç¹å»åæ¢ï¼å¨ç¹å»ä¸é¢çå¿«ç §æé®ï¼å°±å¯ä»¥è·åææææ线ç¨çä¸æ¬¡å¿«ç §ï¼ç¶åå°±å¯ä»¥çå°æ¯ä¸ªçº¿ç¨æ§è¡çæºç ï¼å ·ä½æä½å¦ä¸å¾ï¼
éè¿ä¸è¿°çæä½å³å¯æ¥ç线ç¨å ·ä½æ¶åçæºç ï¼ä»èææ¥é®é¢ï¼
ä¸é¢è¯´çæ¯æ¬å°æå¡çæµï¼ä½æ¯æå¾å¤æ åµæ¬å°æå¡æ¯ææ¥ä¸å°é®é¢çï¼åªæå¨æå¡å¨ä¸é¢æè½çåºé®é¢ï¼é£ä¹æ们就éè¦è¿ç¨è¿æ¥æå¡å¨ä¸é¢æå¡ï¼è¿è¡çæ§ï¼æ¥çå ·ä½çº¿ç¨çè¿è¡æ åµåæºç åæ
è¿ç¨é ç½®éè¦å¨å¯å¨Javaæå¡çæ¶åï¼å¨å¯å¨å½ä»¤ä¸é¢æ·»å æå®å¯å¨åæ°ï¼è¿éæä¾çå½ä»¤æ¯æ£å¸¸æ åµä¸å®æ´çå¯å¨jarå çå½ä»¤ï¼å ·ä½å½ä»¤åæ°ä¹å¾æ¸ æ¥ï¼å½ä»¤å¦ä¸ï¼
ps:portæ¯çæ§æéç端å£ï¼ä¹å°±æ¯å¯å¨æå¡æå®ç端å£ï¼ä½æ¯ç«¯å£è¦å¯¹å¤å¼æ¾ï¼ä¸è¬çæ®éæå¡ç«¯å£æ¯ä¸ä¼å¯¹å®å¼æ¾çï¼è¿ä¸ç¹éè¦æ³¨æ
hostnameæ¯å¯¹åºçæ§çipï¼æè¿éç¨çå°±æ¯æå¡å¨ipï¼å¦æè¿æ¥ä¸ä¸çæ åµä¸ï¼å¯ä»¥å°è¯ä½¿ç¨ hostname -i è·åç对åºipï¼å ·ä½æ åµå ·ä½åæ
ç¶åå¯å¨æå¡ä¹åï¼éä¸è¿ç¨å³é®æ·»å è¿ç¨ä¸»æºï¼è¾å ¥è¿ç¨ä¸»æºipåç¡®å®å³å¯ï¼ç¶åéæ©ä¸»æºipï¼å³é®æ·»å JMXè¿æ¥ï¼è¾å ¥è®¾å®ç端å£å·ï¼ç¹å»ç¡®å®å³å¯ï¼ç¶åå°±å¯ä»¥çæ§è¿ç¨æå¡å¨äºï¼æ¥ä¸æ¥çæ¥ç线ç¨çæ åµãçæ§æå¡æ åµåææ¥é®é¢ä½¿ç¨å¿«ç §ï¼å°±åä¸é¢æ¬å°çæä½ä¸æ ·äºï¼
ç»è¿ä¸è¿°æä½å°±å¯ä»¥éè¿JDKèªå¸¦ççæ§è½¯ä»¶ï¼è¿è¡çæ§Javaç¨åºçè¿è¡æ åµä»¥åæå¡å¨çè¿è¡æ åµå¦ï¼
æ¬äººåèï¼å¦æé®é¢æ¬¢è¿å¤§å®¶ææ£ï¼å ±åè¿æ¥ï¼
分享一个调试Java程序生产问题工具:Lightrun
在本文中,我将分享 Lightrun,猜拳源码赚钱这是我最近在开发RevoGain时发现的一个非常有用的工具,用于调试生产中出现的问题。
Lightrun提供了动态日志记录、运行时快照和动态指标等功能,允许我们在运行时动态插入日志条目、捕获快照,甚至在不更改生产代码的情况下注入指标,这在调查客户报告的问题时特别有用。
设置Lightrun非常简单,配置它只需要不到5分钟。对于本地Windows环境,可以通过代理提供。对于生产系统,可以使用基于Linux的命令。动态日志记录允许我们添加消息,并通过定义过滤条件来控制是否记录该消息。
在解析交易报表时,如果交易余额加起来不出来,需要具有交易对账单。添加动态日志条目将帮助我们在用户执行可以复制问题的操作时发现问题。通过定义特定条件,如id值为1的用户,可以仅显示特定消息。
查看如何根据我们从对账单中解析的交易操作计算余额。如果计算的余额与语句提供的余额值不匹配,我们可以向客户确定导致问题的原因。没有Lightrun,我们不能只是调试生产系统,因为整个服务器将停止,从而影响可用性。
除了动态日志记录,Lightrun还提供了运行时快照功能,这些快照包含堆栈跟踪和拍摄快照时可用的变量。这可以帮助我们一次聚合多个信息,而不必使用单个日志。
我们还可以动态添加指标,而无需更改我们正在监控的源代码。例如,我使用此功能来计算使用 Stop Forum Spam API验证电子邮件地址需要多长时间。这很重要,因为我正在为我的客户提供实时聊天,我可以在我们的实时对话中调试他们的生产问题。
Lightrun易于使用,但功能非常强大,因为它允许我们使用指标注入日志、收集快照或检测我们的代码,而无需更改需要重新部署的生产源代码。这有助于我为客户提供卓越的支持。
更多与Java性能工具相关的内容,包括JVM调优工具、顶级Java才懂的长尾请求hack工具、使用JDK中自带的JVM分析工具解决内存溢出问题、如何使用Eclipse内存分析工具定位内存泄漏、排查死锁的4种工具、用crash工具分析Linux内核死锁的一次实战、6个Java工具轻松分析定位JVM问题、JVM源码分析之jstat工具原理完全解读、如何使用JVisualVM进行故障排查以及学会这个Thread Dump分析工具,让您秒变性能分析大师等。
《面试1v1》JVM调试
我叫 javapub,一名Markdown程序员兼八股文种子选手。在一次面试中,面试官向我提问关于JVM调优的掌握程度。我首先对JVM调优的理解进行了谦虚的描述,承认自己还在学习阶段,但日常工作中有接触JVM参数与监控工具,算是有入门水平。
面试官接着询问了我对JVM调优具体的方法和手段。我回答,JVM调优主要通过调整JVM参数和使用监控工具来进行。我日常工作中最常用的JVM参数和监控工具,帮助我在日常的JVM调优和问题排查中发挥了很大作用。尽管如此,我还需要继续深入学习JVM调优的更深层次理论和实践。
面试官对我的回答给予了肯定,认为我已经掌握了JVM调优的基础知识和日常工具的使用,是一个不错的入门水平。随后,面试官又问到了我作为JVM调优的进阶学习计划。我详细地介绍了我的学习计划,包括深入学习JVM调优的理论知识、实践技能等,需要通过不断学习和实践来提升。
最近,我正在更新《面试1v1》系列文章,以场景化的方式讲解在面试中遇到的问题,旨在帮助工程师们拿到心仪的offer。文章内容涵盖了JVM调优、数据结构与算法、Mybatis、搜索LuceneElasticsearch、Spring等技术点,以对话的形式、口语化描述技术点,涉及高频面试题、工作中如何使用,还穿插了部分源码解析。
《面试1v1》文章通过真实的面试场景模拟,帮助候选人如何自然地对答,避免紧张导致的知识点遗忘。文章以实际面试情况编写,使用大白话描述技术难题,避免背诵式回答。读者可以在这里找到面试中常考的知识点,甚至一些源码细节,以更好地准备面试。
《面试1v1》文章由我完全免费提供,并持续更新中。读者可以通过搜索“JavaPub”直接查看全系列文章。我将根据读者反馈和市场需要,持续更新和改进《面试1v1》系列文章,以帮助更多工程师们掌握面试技巧,顺利拿到心仪的offer。
如果你对《面试1v1》系列文章感兴趣,欢迎关注我 @JavaPub,获取最新的文章更新和学习资源。希望我的分享能够帮助你在面试中表现出色,实现职业发展的目标。
idea编译java后中文乱码怎么解决
解决IDEA编译Java后中文乱码问题的方法:一、确保源码文件编码正确
在编写Java代码时,确保你的源码文件编码为UTF-8。IDEA可以自动识别文件编码,但有时需要手动设置或检查。可以通过查看文件状态栏来确认编码。如果不是UTF-8,建议将文件另存为UTF-8编码格式。
二、检查项目编码设置
在IDEA中,你需要检查项目的编码设置。在项目的根目录下,右击选择“Mark Directory as”然后选择“Sources Root”。确保在“File Encoding”设置中选择了正确的编码方式,通常为UTF-8。这样可以确保IDEA在处理项目文件时使用正确的编码。
三、检查JVM编码设置
在编译和运行Java程序时,要确保JVM使用正确的字符编码。可以通过在命令行参数中设置JVM的默认字符编码来解决乱码问题。例如,在启动Java程序时,使用`-Dfile.encoding=UTF-8`参数来指定UTF-8编码。
四、检查控制台输出编码
如果在控制台输出中出现了乱码,可能是因为控制台使用的编码与程序输出的编码不一致。可以尝试修改IDEA控制台输出的编码设置。在IDEA的“Run”菜单中,选择“Edit Configurations”,然后在相应配置下设置“VM options”,添加或修改编码相关的参数。
综上所述,解决IDEA编译Java后中文乱码问题,主要需要从源码文件编码、项目编码设置、JVM编码设置以及控制台输出编码等方面进行检查和调整。确保所有涉及编码的地方都使用正确的UTF-8编码,可以有效解决中文乱码问题。
2024-12-28 18:54
2024-12-28 18:34
2024-12-28 18:31
2024-12-28 18:31
2024-12-28 17:09