1.OpenJDK17-JVM 源码阅读 - ZGC - 并发标记 | 京东物流技术团队
2.Kswapd 源码解析
3.uniapp二手手机回收租赁小程序源码/旧手机在线估价回收商城源码
4.Hermes源码分析(二)——解析字节码
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。工作逻辑循环从标记条带中取出数据,肖像分割python opencv源码直到取完或时间到。此循环即为ZGC三色标记主循环。之后进入drain函数,从栈中取出指针进行标记,直到栈排空。标记过程包括从栈取数据,标记和递归标记。
标记与迭代:
标记过程涉及对象迭代遍历。标记流程中,ZGC通过map存储对象地址的finalizable和inc_live信息。map大小约为堆中对象对齐大小的二分之一。接着通过oop_iterate函数对对象中的指针进行迭代,使用ZMarkBarrierOopClosure作为读屏障,实现了指针自愈和防止漏标。
读屏障细节:
ZMarkBarrierOopClosure函数在标记非静态成员变量的指针时触发读屏障。慢路径处理和指针自愈是核心逻辑,慢路径标记指针,快速路径通过cas操作修复坏指针,并重新标记。
重映射过程:
读屏障触发标记后,对象被推入栈中,金融理财源码手机下次标记循环时取出。ZGC并发标记流程至此结束。
问题回顾:
本文解答了ZGC如何标记指针、三色标记过程、如何防止漏标、指针自愈和并发重映射过程的问题。
扩展思考:
ZGC在指针上标记,当回收某个region时,如何得知对象是否存活?答案需要结合标记阶段和重分配阶段的代码。
结束语:
本文深入分析了ZGC并发标记的源码细节,对您有启发或帮助的话,请多多点赞支持。作者:京东物流 刘家存,来源:京东云开发者社区 自猿其说 Tech。转载请注明来源。
Kswapd 源码解析
kswapd是Linux内核中的一个内存回收线程,主要用于内存不足时回收内存。初始化函数为kswapd_init,内核为每个节点分配一个kswapd进程。每个节点的pg_data_t结构体中维护四个成员变量,用于管理kswapd线程。社群类小程序源码
在初始化后,每个节点的kswapd线程进入睡眠状态。唤醒时机主要在被动唤醒和主动唤醒两种场景:被动唤醒是内存分配进程唤醒并完成异步内存回收后,对节点内存环境进行平衡度检查,若平衡则线程短暂休眠ms后主动唤醒。主动唤醒是内存回收策略调用kswapd,对节点进行异步内存回收,让节点达到平衡状态。
内存回收包括快速和直接两种方式,但系统周期性调用kswapd线程平衡不满足要求的节点,因为有些任务内存分配不允许阻塞或激活I/O访问,回收内存相当于亡羊补牢,系统利用空闲时间进行内存回收是必要的。
kswapd线程通过module_init(kswapd_init)创建,一般处于睡眠状态等待被唤醒,当系统内存紧张时,会唤醒kswapd线程,调整不平衡节点至平衡状态。
kswapd函数包含alloc_order、reclaim_order和classzone_idx三个变量,用于控制线程执行流程。php url短网址源码kswapd_try_to_sleep函数判断是否睡眠并让出CPU控制权,同时是线程唤醒的入口。balance_pgdat函数是实际内存回收操作,涉及内存分配失败后唤醒kswapd线程,调用此函数对指定节点进行异步内存回收。
kswapd_shrink_node函数通过shrink_node对低于sc->reclaim_idx的非平衡zone区域进行回收。
总结kswapd执行流程,其生命周期与Linux操作系统相似,平时处于睡眠状态让出CPU控制权。在内存紧张时被唤醒,有被动唤醒和周期性主动唤醒两种时机。被动唤醒发生在内存分配任务获取不到内存时,表明系统内存环境紧张,主动唤醒则是内存回收策略的执行。线程周期性唤醒在被动唤醒后的短暂时间内,原因在于系统内存环境紧张,需要在这段时间内进行内存回收。
uniapp二手手机回收租赁小程序源码/旧手机在线估价回收商城源码
这套源码集成了uniapp和thinkphp技术栈,提供了一套功能丰富的二手手机回收租赁和在线估价商城解决方案。移动端App、小程序端以及公众服务号端的整合,确保了用户在不同设备上都能获得一致的使用体验。代码全开源,这意味着开发者可以基于此源码进行二次开发,以满足特定的业务需求或添加新功能。
功能特点方面,源码支持用户在线估价旧手机,提供详细的回收价格信息,简化了交易流程。用户可以快速上传手机信息或,系统自动进行估价。对于回收服务,源码提供了便捷的预约和上门回收选项,保证了用户的便利性和安全性。同时,租赁功能使得用户可以根据需求租借手机,提供灵活多样的使用方案。
源码还具备库存管理、订单处理、用户评价、数据分析等功能,帮助运营者更好地管理业务流程,提升用户体验。此外,源码支持多语言和多货币设置,适应全球市场的需求。它还具备安全防护机制,确保交易过程中的信息安全。
此源码适用于二手手机回收、租赁及在线估价的商家,无论是初创企业还是已有业务需要扩展的公司,都能通过此源码快速搭建起专业的二手电子产品交易平台。源码的灵活性和开放性,使其不仅局限于手机,还可以应用于各种数码3C产品,如电脑、平板、相机等。
Hermes源码分析(二)——解析字节码
前面一节 讲到字节码序列化为二进制是有固定的格式的,这里我们分析一下源码里面是怎么处理的这里可以看到首先写入的是魔数,他的值为
对应的二进制见下图,注意是小端字节序
第二项是字节码的版本,笔者的版本是,也即 上图中的4a
第三项是源码的hash,这里采用的是SHA1算法,生成的哈希值是位,因此占用了个字节
第四项是文件长度,这个字段是位的,也就是下图中的为0aa,转换成十进制就是,实际文件大小也是这么多
后面的字段类似,就不一一分析了,头部所有字段的类型都可以在BytecodeFileHeader.h中看到,Hermes按照既定的内存布局把字段写入后再序列化,就得到了我们看到的字节码文件。
这里写入的数据很多,以函数头的写入为例,我们调用了visitFunctionHeader方法,并通过byteCodeModule拿到函数的签名,将其写入函数表(存疑,在实际的文件中并没有看到这一部分)。注意这些数据必须按顺序写入,因为读出的时候也是按对应顺序来的。
我们知道react-native 在加载字节码的时候需要调用hermes的prepareJavaScript方法, 那这个方法做了些什么事呢?
这里做了两件事情:
1. 判断是否是字节码,如果是则调用createBCProviderFromBuffer,否则调用createBCProviderFromSrc,我们这里只关注createBCProviderFromBuffer
2.通过BCProviderFromBuffer的构造方法得到文件头和函数头的信息(populateFromBuffer方法),下面是这个方法的实现。
BytecodeFileFields的populateFromBuffer方法也是一个模版方法,注意这里调用populateFromBuffer方法的是一个 ConstBytecodeFileFields对象,他代表的是不可变的字节码字段。
细心的读者会发现这里也有visitFunctionHeaders方法, 这里主要为了复用visitBytecodeSegmentsInOrder的逻辑,把populator当作一个visitor来按顺序读取buffer的内容,并提前加载到BytecodeFileFields里面,以减少后面执行字节码时解析的时间。
Hermes引擎在读取了字节码之后会通过解析BytecodeFileHeader这个结构体中的字段来获取一些关键信息,例如bundle是否是字节码格式,是否包含了函数,字节码的版本是否匹配等。注意这里我们只是解析了头部,没有解析整个字节码,后面执行字节码时才会解析剩余的部分。
evaluatePreparedJavaScript这个方法,主要是调用了HermesRuntime的 runBytecode方法,这里hermesPrep时上一步解析头部时获取的BCProviderFromBuffer实例。
runBytecode这个方法比较长,主要做了几件事情:
这里说明一下,Domain是用于垃圾回收的运行时模块的代理, Domain被创建时是空的,并跟随着运行时模块进行传播, 在运行时模块的整个生命周期内都一直存在。在某个Domain下创建的所有函数都会保持着对这个Domain的强引用。当Domain被回收的时候,这个Domain下的所有函数都不能使用。
未完待续。。。