JVM
文章平均质量分 83
860MHz
这个作者很懒,什么都没留下…
展开
-
JDK19虚拟线程初探(三)
总共花三篇文章大概介绍了JDK19中新增的虚拟线程,从LOOM Project的纤程、阿里的wisp和wisp2、到今天JEP 425中的虚拟线程,官方提供的生产可用的用户态线程方案距离我们越来越近了。原创 2022-11-12 16:27:57 · 792 阅读 · 0 评论 -
JDK19虚拟线程初探(二)
在上一篇文章中,我们已经简单的介绍了JEP 425: Virtual Threads (Preview),以及如何使用虚拟线程编写例程,本文中将继续介绍虚拟线程的底层机制和核心源码。原创 2022-11-11 21:32:38 · 937 阅读 · 1 评论 -
JDK19虚拟线程初探(一)
经过多年的等待后,JEP 425: Virtual Threads (Preview)终于带来了虚拟线程,这一轻量级的线程模型对标其他语言中的协程,能够显著的减少编写、维护和观察高并发应用程序的工作量。原创 2022-10-30 15:05:34 · 548 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(八)GC阶段之并发转移
1. 简介ZGC最后一个阶段就是并发转移,在之前的阶段已经标记出了活跃对象和需要转移的page。因此并发转移阶段,GC并发的将转移集中的活跃对象迁移到新页面,并在转移完成后回收旧页面。2. 源码分析2.1 入口并发转移的转移的入口也在zHeap。hotspot/share/gc/z/zHeap.cppvoid ZHeap::relocate() { // Relocate relocation set _relocate.relocate(&_relocation_set);原创 2021-09-17 20:04:53 · 486 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(七)GC阶段之转移集
1. 简介在并发处理完强引用和非强引用后,ZGC就进入了转移阶段。本文将介绍转移阶段开始的两个小步骤,重置转移集和选择转移集。2. 源码分析2.1 重置转移集在标记阶段介绍后,所有的引用都已经指向对象迁移后的新地址,ZForwardingTable中的数据已经全部失效。此时需要重置转移集,为下一轮GC做准备。hotspot/share/gc/z/zHeap.cppvoid ZHeap::reset_relocation_set() { // 重置forwarding table ZRe原创 2021-09-15 13:43:28 · 276 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(六)GC阶段之非强引用处理
1. 简介在并发标记结束后,ZGC进入非强引用的并发标记和处理阶段。主要负责处理软引用、弱引用、虚引用、FinalReference(实现了Finalize方法的类的实例)。2. 引用2.1 引用的基本概念引用的类型memory/referenceType.hppenum ReferenceType { REF_NONE, // 正常的类 REF_OTHER, // java/lang/ref/Reference的子类,但不在下面里面 REF_SOFT,原创 2021-09-10 13:44:20 · 311 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(五)GC阶段之并发标记
1. 简介并发标记是ZGC的第2个阶段,此阶段中,GC worker与Mutator并发工作,GC worker执行标记、load barrier和relocate。并发线程从带标记对象列表开始,递归遍历对象及对象的成员变量并标记。2. 源码分析2.1 入栈标记栈的size受ZMarkStackSpaceLimit参数控制,默认8G,合法值32MB到1TB之间。share/gc/z/z_globals.hpp product(size_t, ZMarkStackSpaceLimit, 8*G原创 2021-09-03 14:06:38 · 597 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(四)GC阶段之初始标记
1. 简介GC回收周期大体如下图所示:与早期版本不同,ZGC回收周期调整为9个子阶段:phase 1:初始标记,需要STWphase 2:并发标记phase 3:标记结束,需要STWphase 4:并发处理软引用、弱引用phase 5:并发重置Relocation Setphase 6:验证phase 7:并发选择Relocation Setphase 8:开始Relocate,STWphase 9:并发Relocate出于回收效率的考虑,remap过程放在下一个回收周期的并发标记原创 2021-08-28 20:11:48 · 671 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(三)读屏障Load Barrier
1. 简介对于并发GC来说,最复杂的事情在于GC worker在标记-整理,而Java线程(Mutator)同时还在不断的创建新对象、修改字段,不停的更新对象引用关系。因此并发GC一般采用两种策略Incremental Update(增量更新、CMS) 和SATB(snapshot at beginning、G1) ,两种策略网上介绍文章很多,此处不再赘述。SATB关注引用关系的删除,可以参考我之前的博客JVM G1 源码分析(四)- Dirty Card Queue Set,而Incremental原创 2021-08-21 19:28:54 · 1159 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(二)对象分配
1. 简介自从JDK10中的引入了JEP 304: Garbage Collector Interface 后,OpenJDK定义了一整套关于GC的虚方法,供具体的GC算法实现。极大了简化了开发难度和代码的可维护性。JEP 304定义了CollectedHeap类,每个GC都需要实现。CollectedHeap类负责驱动HotSpot的GC,以及和其他模块的交互。GC应当实现如下功能:CollectedHeap的子类BarrierSet集合类的实现,提供在运行时各种屏障功能。CollectorP原创 2021-08-17 19:34:51 · 402 阅读 · 0 评论 -
OpenJDK16 ZGC 源码分析(一)内存管理
1. 概览ZGC在JDK11中作为实验性功能引入后,已经经过了5个版本的演进,目前较之前版本有了较大的变化。本文及其后几篇文章,将分析ZGC的设计思想和原理。关于ZGC的介绍,可以参考OpenJDK ZGC 源码分析(一)概览2. 简介ZGC为了支持TB级内存,采用了基于Page的分页管理(类似于G1的Region)。同时,为了加快内存访问速度,快速的进行并发标记和relocate,ZGC新引入了Color Pointers;Color Pointers与Shenandoah GC使用的Bro原创 2021-08-05 08:34:26 · 649 阅读 · 0 评论 -
Runtime.getRuntime().availableProcessors()方法在Docker容器中遇到的问题和解决方案
问题最近在线上环境遇到一个奇怪的问题,仅仅20qps的压测,产生非常多的毛刺,立刻判断出毛刺是由于YGC导致。线上环境为docker容器,4核8G内存,openjdk8u排查过程于是登录线上机器查看GC日志,发现GC Workers: 63,但压测服务器仅4核,不可能有63个GC线程。[GC pause (G1 Evacuation Pause) (young), 0.0054131 secs] 10 [Parallel Time: 3.6 ms, GC Workers: 63] 11原创 2021-03-05 00:33:50 · 6255 阅读 · 1 评论 -
Lambda表达式实现机制的分析
1. 背景几年前曾经写过一篇Lambda表达式实现机制的分析,现在回头看错误很多,有误导嫌疑,因此重写一版订正。2. Lambda表达式的字节码分析下面代码为一个Lambda表达式的例子package demo;import java.util.LinkedList;import java.util.List;import java.util.stream.Collectors;public class Test1 { public void func1(List<Inte原创 2020-10-04 23:58:15 · 398 阅读 · 0 评论 -
JEP 353: Reimplement the Legacy Socket API(JDK 13)
1. 简介JDK中的java.net.Socket 和 java.net.ServerSocket实现非常古老,可以上溯到JDK 1.0,该实现是混合了JAVA和C代码,非常难于维护和调试。另外,该实现使用线程堆栈作为I/O缓冲区,这带来一系列的移植性和可用性问题。因此JDK 13中实现了新的java.net.SocketImpl的实现类sun.nio.ch.NioSocketImpl,以替代...原创 2019-12-03 17:10:01 · 317 阅读 · 0 评论 -
JEP-351 ZGC: Uncommit Unused Memory(JDK 13)
1. 简介将GC后的内存返回给OS这一能力,在云计算场景中将节省用户的支出。因此G1和Shenandoah均实现了该能力,在JDK 13中,ZGC也具备了该能力。由于ZGC的堆被划分为一个个的ZPage,返回OS将以ZPage为单位执行,实现较为简单,下文中将详细说明。2. 分析2.1 页缓存ZGC中使用ZPageCache缓存ZPage,ZPageCache中维护了三个LRU链表分别缓...原创 2019-11-28 14:20:31 · 812 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(五)对象分配
1. 简介ZGC的对象分配流程大体与G1类似。分配流程图在JVM G1 源码分析(二)- 对象的堆空间分配内。主要代码在src/hotspot/share/gc/shared目录下,为多个GC算法的共用代码。ZGC定制逻辑由gc shared代码调用ZCollectedHeap、ZHeap等ZGC派生类实现。2. 源码分析2.1 allocate_new_tlab当线程的TLAB可用内...原创 2019-08-15 09:44:08 · 498 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(六)GC回收
1. 简介GC回收周期大体如下图所示:GC回收周期包括如下11个子阶段:phase 1:初始标记,需要STWphase 2:并发标记phase 3:标记结束,需要STWphase 4:并发处理软引用、弱引用phase 5:并发重置Relocation Setphase 6:并发销毁可回收页phase 7:内存验证phase 8:并发选择Relocation Setphas...原创 2019-08-16 09:56:18 · 966 阅读 · 0 评论 -
Java中的字符串存储方式
1. 简介十一放假期间在脉脉上看见一道面试题讨论的很火热:Java中字符串是如何存储的?这一问题看似简单,但是背后却隐藏了很多深层机制,本文将逐一介绍相关技术原理。2. 字符串类字符串广泛应用于Java编程中,在Java中字符串属于对象,Java提供了String 类来创建和操作字符串。2.1 java.lang.Stringjava.lang.String成员变量如下:pub...原创 2019-10-10 15:27:21 · 1268 阅读 · 0 评论 -
JVM G1 源码分析(一)- 分区Heap Region
1. 简介G1(Garbage-First Collector)是一种垃圾回收算法,最早在JDK 6 Update 14中作为实验性功能加入,并在JDK 7 Update 4正式JDK,之后在JDK 9 中成为默认垃圾回收算法,在JDK 10中优化了Full GC性能。G1是面向服务器的垃圾收集器,针对于多核处理器、大堆的服务器场景。它可以满足短停顿的同时支持高吞吐量。本文及随后几篇文章将分...原创 2019-07-22 14:54:42 · 3036 阅读 · 0 评论 -
Java instanceof 关键字是如何实现的?
HotSpot VM具体使用了长度为8的缓存数组,记录某个类从继承深度0到7的超类。HotSpot把类继承深度在7以内的超类叫做“主要超类型”(primary super),把所有其它超类型(接口、数组相关以及超过深度7的超类)叫做“次要超类型”(secondary super)。对“主要超类型”的子类型判断不需要像Kaffe或JamVM那样沿着super链做遍历,而是直接就能判断子类型关系是转载 2016-08-01 23:33:12 · 2800 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(四)分页
1. 简介与G1的分区类似,ZGC将堆划分成Page进行管理,不同的是ZGC中Page大小不是固定的,而是分为三种Small、Medium、Large三类。本文将详细介绍ZGC的分页机制。2. 代码分析2.1 Page的类型ZGC有3种不同的页面类型:小型(2MB),中型(32MB)和大型(2MB的倍数)。zGlobals_linux_x86.hppconst size_t Z...原创 2019-08-14 09:57:27 · 453 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(一)概览
1. 前言G1是JDK中最新最成熟的垃圾回收器,其稳定性和性能得到了广泛的认可。但是,一方面随着硬件的发展,堆空间越来越大,几十GB、上百GB的内存在生产环境逐渐出现;另一方面,对于停顿时间的需求日益严苛,从最初的秒级到百毫秒级,再到十毫秒级和毫秒级。G1对于这种情况逐渐力不从心,下一代低延迟垃圾回收器主要有ZGC和Shenandoah。本文将详细介绍ZGC相关原理。2. 历史Oracle在...原创 2019-08-07 14:40:27 · 1311 阅读 · 0 评论 -
JVM G1 源码分析(三)- Remembered Sets
1. 简介记录集Remembered Sets简称RSet,用于记录对象在不同分区之间的引用关系,目的是为了加速垃圾回收的速度,主要是加速标记阶段。本文将详细介绍RSet的结构。通常的,有两种记录引用关系的方式,PointOut和PointIn。如果obj1.field1=obj2,如果是PointOut方式,则在obj1所在region的RSet记录obj2的位置;如果是PointIn方...原创 2019-07-25 17:26:37 · 3583 阅读 · 0 评论 -
Lambda表达式与匿名内部类的区别分析
背景最近面试中与几个候选人探讨过类似的问题,发现多数人对这一概念仍然比较模糊,本文将从字节码的角度简单介绍一下两者的区别匿名内部类匿名内部类其实就是没有名字的内部类,但是其必须要实现一个接口或者继承一个父类,通常是用来简化代码例程如下:先定义一个IAnimal然后定义测试类NestedClassTest进入classes目录,我们可以发现出现了三个class文件IAnimal.classNeste...原创 2018-07-13 11:40:51 · 2086 阅读 · 0 评论 -
JDK 11中的ZGC-一种可扩展的低延迟垃圾收集器
# 背景正如我们所知道的在JDK 11中即将迎来ZGC(The Z Garbage Collector),这是一个处于实验阶段的,可扩展的低延迟垃圾回收器。本文整合了外网几篇介绍ZGC的文章和代码。# 目标* 每次GC STW的时间不超过10ms* 能够处理从几百M到几T的JAVA堆* 与G1相比,吞吐量下降不超过15%* 为未来的GC功能和优化利用有色对象指针(colored oops)和加载屏...翻译 2018-07-13 11:36:15 · 7892 阅读 · 2 评论 -
哪个更快:Java堆还是本地内存
使用Java的一个好处就是你可以不用亲自来管理内存的分配和释放。当你用new关键字来实例化一个对象时,它所需的内存会自动的在Java堆中分配。堆会被垃圾回收器进行管理,并且它会在对象超出作用域时进行内存回收。但是在JVM中有一个‘后门’可以让你访问不在堆中的本地内存(native memory)。在这篇文章中,我会给你演示一个对象是怎样以连续的字节码的方式在内存中进行存储,并且告诉你是应该怎样转载 2016-10-31 09:43:24 · 854 阅读 · 0 评论 -
TLAB
2. TLABJVM在内存新生代Eden Space中开辟了一小块线程私有的区域,称作TLAB(Thread-local allocation buffer)。默认设定为占用Eden Space的1%。在Java程序中很多对象都是小对象且用过即丢,它们不存在线程共享也适合被快速GC,所以对于小对象通常JVM会优先分配在TLAB上,并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践转载 2016-09-28 22:18:32 · 4247 阅读 · 1 评论 -
Java 8 HashMap键与Comparable接口
这篇文章主要介绍了 Java 8 在 HashMap 哈希冲突处理方面的新特性。相对之前的版本,Java 8 在许多方面有了提升。其中有很多类被更新了,HashMap 作为最常使用的集合类之一也不例外。这篇文章将介绍 Java 8 中的 HashMap 在处理哈希冲突时的新特性。让我们从头开始。最容易使 HashMap 发生哈希冲突的方法是什么呢?我们可以创建一个类,让它的哈希函数转载 2016-06-12 09:51:21 · 570 阅读 · 0 评论 -
Java集合框架
Java集合工具包位于Java.util包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。学习Java集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。Java集合类的整体框架如下:从上图中可以看出,集合类主要分为两大类:Coll转载 2016-05-25 10:09:27 · 375 阅读 · 0 评论 -
通过Java字节码发现有趣的内幕之初始化篇(下)
关于类初始化过程网上有很多相关的文章,其实也算是学习语言时一个基础知识,但今天我想从字节码表现上更深入的来理解各种场景下的实例初始化过程是怎么样的,从简单到复杂大体分为下面几个场景 。1、成员+构造函数2、成员+代码块+构造函数3、 静态变量+静态代码块4、 继承和多态首先明确下运行环境:我们先来看一下第一个场景: 成员+构造函数,也是我们最转载 2016-03-29 09:40:11 · 398 阅读 · 0 评论 -
通过Java字节码发现有趣的内幕之String篇(中)
1、字面量相加首先来看两个字面量字符串相加发生了什么情况,Java代码:12345678packagecom.jaffa.test.string; publicclass StringOptTest { publicsta转载 2016-03-29 09:38:59 · 554 阅读 · 0 评论 -
通过Java字节码发现有趣的内幕之String篇(上)
很多时候我们在编写Java代码时,判断和猜测代码问题时主要是通过运行结果来得到答案,本博文主要是想通过Java字节码的方式来进一步求证我们已知的东西。这里没有对Java字节码知识进行介绍,如果想了解更多的Java字节码或对其感兴趣的朋友可以先阅读字节码基础:JVM字节码初探。String字面量可以通过’==’判断两个字符串是否相同,是因为大家都知道’==’是用来判断两个对象的值引用地址是否转载 2016-03-29 09:38:32 · 566 阅读 · 0 评论 -
JAVA 10源码阅读笔记之JEP-307(G1的并行Full GC)
# 1. 背景JEP-307解决了G1垃圾回收器的一个严重的问题,截止到Java 9,G1的Full GC采用的是单线程算法,严重影响性能,无法利用到多核能力进行垃圾回收。JEP-307修复了此问题,发生Full GC时允许使用多个线程进行并行回收。# 2. G1的简单介绍在Java 6/7 时代,大量线上服务采用CMS垃圾回收算法,以牺牲吞吐量为代价获得较少的STW时间。但是由于CMS的...原创 2018-09-27 20:29:27 · 955 阅读 · 0 评论 -
JAVA 学习笔记之JEP-193(变量句柄)
1. 背景变量句柄(Variable Handles)早在JDK9中就引入的特性,之前一直没有太关注,最近看代码的时候发现已经有项目在使用了,研究了一下并写下此笔记备忘。2. 变量句柄的介绍与目标目的变量句柄的目的是定义一个标准的用法来操作对象字段和数组元素,等效于java.util.concurrent.atomic 和 sun.misc.Unsafe。并且提供了一系列标准的内存屏障操作...原创 2018-11-28 20:47:57 · 731 阅读 · 0 评论 -
JDK 11 之JEP 321 HTTP Client(Standard)
1. 摘要JEP 321 标准化了JDK 9引入孵化的HTTP Client(JEP 110)2. 动机JDK8中的HttpURLConnectionAPI及其实现存在许多问题:URLConnection API是设计时考虑了多种协议,几乎所有这些都是现在已经不存在(ftp,gopher,等)。API早于HTTP / 1.1并且过于抽象。难于使用,很多没有文档化的行为仅能在阻塞模式...翻译 2019-03-11 17:21:01 · 1098 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(三)内存管理
1. 简介ZGC与传统GC不同,标记阶段标记的是指针(colored pointer),而非传统GC算法中的标记对象。ZGC借助内存映射,将多个地址映射到同一个内存文件描述符上,使得ZGC回收周期各阶段能够使用不同的地址访问同一对象。本文将详细介绍ZGC的内存管理。2. 代码分析2.1 指针结构目前ZGC仅支持Linux/x64,指针是64位的,ZGC重新定义了指针结构。zGlobal...原创 2019-08-13 14:48:48 · 1110 阅读 · 0 评论 -
OpenJDK ZGC 源码分析(二)触发GC的时机
1. 简介ZGC的回收周期触发时机与其他GC算法略有不同,VM内部有个线程轮询定期检查是否满足开始回收的条件,如果满足则开始回收。ZGC提供四种策略,其中一种满足条件即触发回收:rule_timer,定时策略,距离上次GC时间超过interval即触发GCrule_warmup,VM启动后,如果从来没有发生过GC,则在堆内存使用超过10%、20%、30%时,分别触发一次GC,以收集GC数...原创 2019-08-08 12:22:10 · 1080 阅读 · 0 评论 -
JVM G1 源码分析(六)- 混合式GC
1. 简介YGC整个过程都在STW下进行,出于减少停顿时间的考量,对于老年代的回收显然需要与Mutator同时进行,G1引入了混合式GC,与CMS算法类似,均采用了并发标记。混合式回收主要分为如下子阶段:初始标记子阶段并发标记子阶段再标记子阶段清理子阶段垃圾回收2. 算法概览2.1 标记算法概览由于混合式GC使用的是并发标记,Mutator可能会随时改变对象引用关系,从而导...原创 2019-08-01 15:18:05 · 1680 阅读 · 1 评论 -
JVM G1 源码分析(七)- Full GC
1. 简介当晋升失败、疏散失败、大对象分配失败、Evac失败时,有可能触发Full GC,在JDK10之前,Full GC是串行的,JEP 307: Parallel Full GC for G1之后引入了并行Full GC。本文主要介绍并行Full GC机制。2. 源码分析Full GC的入口在g1CollectedHeap.cpp的G1CollectedHeap::do_full_col...原创 2019-08-05 16:10:47 · 2997 阅读 · 0 评论 -
JVM G1 源码分析(二)- 对象的堆空间分配
1. 简介当开发者使用JAVA语言实例化一个对象时,排除JIT的标量替换等优化手段,该对象会在JAVA Heap上分配存储空间。分配空间时,为了提高JVM的运行效率,应当尽量减少临界区范围,避免全局锁。G1的通常的应用场景中,会存在大量的Mutator同时执行,为减少锁冲突,引入了TLAB(线程本地分配缓冲区 Thread Local Allocation Buffer)机制。G1支持基于T...原创 2019-07-23 14:15:16 · 1945 阅读 · 1 评论