Java虚拟机的Heap监狱

俗说 GC 之 Heap 区内存模型的演进 1 篇首 最近看到 GC 这个异常古老的话题又被抛了出来,OpenJDK11 中出现了大道至简、返璞归真的 Epsilon GC 垃圾回收器,ZGC,Shenandoah GC 作为在 G1 的基础之上的两个分别合入了 OpenJDK11 和 OpenJDK12 的项目,两个项目的代号分别为分别为 JEP333、JEP189,这两款目前正在发展中的垃圾回收器成为了与 CMS、G1 两款早期并发回收器进行性能对比的主角。然后我就突然找到了一个主题,那就是比较两款垃圾回收器的性能就是在比较什么?要比较的究竟是哪 阅读详情

在Java虚拟机中,我是一个位高权重的大管家,他们都很怕我,尤其是那些Java 对象,我把他们圈到一个叫做Heap的“监狱”里,严格管理,生杀大权尽在掌握。

中国人把Stack翻译成“栈”,把Heap翻译成“堆”, 还有人会把Stack翻译成“堆栈”,唉,真不知道他们是怎么想的, 不过这么多年都过来了,你们明白就好。

碰巧我会对Heap中的Java 对象做垃圾回收,这个“堆”总是让我联想到垃圾堆。

说起垃圾回收,这实在是一个大负担,原因很简单,那些写Java程序的人类只管把对象给new出来,扔到Heap 中, 但是从来不管把他delete 掉, 删掉这些对象的责任就落到了我的头上,我不严格管理怎么行?

有时候我挺羡慕C和C++, 必须得手动地分配和释放内存,出了错都是程序员来背锅。

在我这里,如果任由这些对象对象肆意妄为,我那容量不高的,Java虚拟机启动后就无法更改的Heap“监狱”很快就会被填满, 所以我必须得派出我的得力助手,专门找到并且清理那些不用的Java 对象, 把他们占据的空间给释放掉。

为了找到这些捣乱分子,我发明了一个叫做“可达性分析”的算法,这个算法估计大部分人已经知道了,我就不再啰嗦了,下面这张图说明了背后的思想,聪明的你一眼就能看出来, 橙色的对象都是不可达对象,可以回收。

640?wx_fmt=png

有个叫刘欣的家伙写了一篇文章《我是一个Java Class》 ,发表在码农翻身公众号上,文章说我还在用引用计数这种办法,实在是可笑。 我抗议了很多次,让他修改, 他说微信公众号只能改五个字,改不了,唉,真是没辙。

Heap监狱

好吧,现在详细说一下我管理的Heap“监狱”。

你可以把它想象成一大片空间,为了方便管理, 我把Heap“监狱”划分成多个区域,然后把那些Java对象在其中搬来搬去。

640?wx_fmt=gif

640?wx_fmt=png

我定的规矩就是: 新来的家伙们都要进入新生代待着,新生代住不下了,我就派出清理者进行垃圾回收(Minor GC),回收以后还住不下,那就把年龄大的老家伙们赶到养老院(老年代)去。

每个在Heap中的Java对象我都会设置一个年龄计数器,每次Java对象熬过一次GC,就把年龄加1, 如果老到一定程度,对不起,请进入养老院(老年代)。  实际上我还会做动态的年龄判断,这里按下不表。

你可能会觉得奇怪,为什么在新生代里分出了Eden, Survivor1, Survivor2这样奇怪的区域?

那是因为我想在这里实现一个所谓的“复制”算法。

最早的时候, 我是把一个内存的区域划分成大小相当的两个区域,每次只用其中的一个。

640?wx_fmt=png

区域1用完了,我就做垃圾回收,把存活的都搬到另外一个区域。

注意:搬过去以后,他们都会紧紧地挨在一起居住,这样以来,被清理掉的那些红色碎片就会重新平整成一大块空间,方便后续使用,尤其是针对大块头对象来了以后。

这么来回颠倒着使用两个区域,虽然效率高,没有碎片,但是浪费的空间很巨大:每次只能用一半。

后来人类发现,大部分在新生代的对象都活不了多长时间,基本上一次垃圾回收就删除得差不多了。

所以就改进了这个只用一半的复制算法, 把新生代分成三个部分:Eden , Survivor1, Survivor2 , 他们的比例是8:1:1。

每次只使用Eden 和其中一个Survivor , 当垃圾回收时,把这两块区域中还活着的对象复制到另外一个Survivor, 如果Survivor放不下,请进养老院(老年代)吧。

如果很不幸, 连养老院都住满了,那只好搞一次Full GC了,这是个很慢的操作,你们最好祈祷它不要频繁发生。

“监狱”之外,大有可为

虽然我可以在Heap监狱内作威作福,有时候我也得接触下监狱之外的世界。

有一次要通过Socket向外发送数据,我明明把数据准备好了,就在我的Heap中,可是JVM老大竟然把数据复制了一份到Heap之外的内存中去,然后才能通过Socket发送。

我问他这到底是怎么回事,为什么要多此一举,难道是对我这个Heap监狱的大管家不放心?

JVM老大说确实是不放心,人家底层的Socket都是C语言写的, 关注的是物理内存的地址, 你垃圾回收的时候把Java对象在什么Eden, Survivor, 老年代之间挪来挪去,对象的地址也会变来变去, 我怎么告诉人家到底发哪个地址的数据啊?

想想也是这个理儿,有得必有失,你程序员不用管理内存,但是底层还得和内存打交道,并且还额外多了一道工序:Copy 。

老大还说:“可能你还不知道,除了你的Heap监狱,其实我在Java进程中还有一块儿叫做“Off-Heap内存’的地方,数据就会复制到这里。 为了和你区分开,我把它叫做堆外内存。”

640?wx_fmt=png

640?wx_fmt=gif

没想到这里还有一块我都管不着的“飞地”!

不过它和我也没有什么竞争关系,由它去吧。

可是没过几天,JVM老大再次给我带来了“惊喜”。

他说:“复制数据太麻烦了,我想了个办法,可以在Java代码中直接分配一块属于Off-Heap的内存。”

我觉得头皮发蒙:“直接在堆外内存分配?到底怎么分配?”

老大给了我一段代码:“看看,这不就分配了128M的堆外存吗? 对这个buffer的读写操作会直接写入堆外内存, 不用再经过你来复制了。”

ByteBuffer buffer = ByteBuffer.allocateDirect(1024*1024*128);

该死的面向接口编程,这个ByteBuffer分配出来的堆外内存,就像一个普通的Java对象在使用,丝毫看不出它在堆内还是在堆外。

完了,这块内存我是彻底管不了了。

老大看出我情绪不对,安慰道: “这个buffer也是个Java对象啊, 就在你的Heap中存着,只不过它保存了那128M内存的信息而已。”

640?wx_fmt=gif

640?wx_fmt=png

这还差不多 ! 既然它是个Java对象,那就得放到我的Heap监狱中,被我控制!

可以想象,这个对象被垃圾回收的时候, 它指向的直接内存才会被释放。

我突然有了一个邪恶的想法:如果这样的对象越来越多,并且一直不被垃圾回收,那对应的直接内存岂不也是不能释放,然后Out of Memory ?

老大似乎看穿了我的思想:“对于这些对象,得特别小心,一定得确保能释放。”

直接分配堆外内存的功能正式推出了,我发现分配起堆外内存要比堆内内存要慢一点,心想估计没有多少人使用吧。 可没想到的是它特别适合那些分配次数少,读写操作很频繁的场景。于是就受到了Netty这些通信类系统的热烈欢迎。

为了减少创建堆外内存的开销,Netty 还引入了对象池的技术,就像数据库连接池一样,先分配一些堆外内存, 然后不断地复用他们。

我没想到堆外内存能玩出这么多的花样,但是一想到他们还是Java程序,还得用Java对象包装,无论如何都跳不出我的手掌去,也就释然了。

(完)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017文章精华》


码农翻身

用故事讲述技术

640?wx_fmt=jpeg

女子监狱狱政管理系统 毕业论文,女子监狱狱政管理系统。想要的直接拿。。改吧改吧就能用。 立即下载

相关推荐

Shell编程规范及变量

文章目录一.Shell脚本1.1Shell概述1.2Shell脚本 一.Shell脚本 1.1Shell概述 Shell是Linux系统中开机自动加载的一个特殊程序,它将用户输入的指令,转换成Linux内核可以识别的语言,从而让内核执行调用硬件。 Bash是Linux系统中默认使用shell的程序,它位于/bin/bash。 1.2Shell脚本 将需要执行的命令保存到一个文件中,按照顺序执行,它不需要编译,它是解释型的 ...

夏颜的博客 3677

java 垃圾回收 参数_JVM实用参数(五)新生代垃圾回收

原文链接 作者: PATRICK PESCHLOW ;译者:严亮本部分,我们将关注堆(heap) 中一个主要区域,新生代(young generation)。首先我们会讨论为什么调整新生代的参数会对应用的性能如此重要,接着我们将学习新生代相关的JVM参数。单纯从JVM的功能考虑,并不需要新生代,完全可以针对整个堆进行操作。新生代存在的唯一理由是优化垃圾回收(GC)的性能。更具体说,把堆划分为新生...

weixin_33171271的博客 254

Ansys Zemax实战:5步搞定衍射光学元件(DOE)设计,附赠超透镜(metalens)避坑指南

本文详细介绍了使用Ansys Zemax进行衍射光学元件(DOE)和超透镜(metalens)设计的5步实战流程。从基础光学系统搭建到相位面设计验证,再到制造准备与实测对比,全面解析了OpticStudio中的关键技巧和常见避坑指南,帮助工程师高效完成复杂光学元件设计。

orange的博客 626

JVM年轻代(young generation)老年代(old generation tenured)持久代(permanent generation)GC

当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。

m0_67402236的博客 2639

TK抓包协议分析:So层逆向

第三个参数是一个回调函数,这里他的返回值1表示成功,0表示失败,那我们手动把他Hook为0,让他不支持quic协议,实现降级。等,我们是为了解决抓包问题,那很有可能是在net目录下(network),那来搜索一下。开了抓包以后APP直接是网络无连接了,并且抓到的请求也是不正常的,下面我们就开始定位。看了半天感觉也没啥有用的东西,那下面我们整理一下已经有信息,来猜测一下,后续怎么进行。那可以猜测,我们真正需要Hook的那个函数也有可能是这样加载的,可以字符串搜索一下。

2503_90751938的博客 3421

uni-app蓝牙MTU设置失效探因:从20字节限制到跨设备兼容性实战

本文深入探讨了uni-app蓝牙开发中MTU设置失效的常见问题,特别是20字节限制的成因及解决方案。通过分析设备兼容性、蓝牙协议栈特性和系统版本差异,提供了智能延迟策略、设备特征检测和渐进式MTU提升等实战方案,帮助开发者优化蓝牙数据传输效率。

weixin_29289821的博客 289

记录一次线上机器JVM调优的历程

其实这件事已经发生很久了,因为最近想开始总结,所以想把这个过程记录下来,也算自己的总结。 在上半年四月份左右,经历了项目交接,我们在维护新项目的过程中,发现一个问题,有一个系统的线上机器在上线后一周左右,接口变得很慢,TP99等各种性能指标飙升。这是一个很典型的问题,应该很多同学也遇到过,最直接的解决办法就是将服务器重启,这个我们也试过,但是治标不治本。经过我们的观察发现系统上线一段时间以后就会...

qq_29919983的博客 582

9.6华为OD机试真题 新系统 - 少儿爬山闯关积分游戏 (Java/Py/C/C++/Js/Go)

2026 华为OD机试真题9月6日华为OD上机新系统考试真题 100 分题型。

算法大师! 861

Java当中jvm运行时区域新生代、老年代、永久代和Garbage Collection垃圾回收机制【杭州多测师】【杭州多测师_王sir】...

1、本地方法栈和程序计数器 ==》偏底层一般不会接触到 2、方法区 ==》对应为永久代 3、虚拟机栈(stack) ==》对应为栈 4、堆(heap) ==》对应里面有新生代+老年代 stack(栈内存) heap(堆内存) 永久代 5、栈内存1)线程私有2)生命周期和线程相同3)主要存放内...

多测师_王sir的博客 1371

基于深度学习的活体人脸检测系统:YOLOv5、YOLOv6、YOLOv7、YOLOv8实现与UI界面设计

本博客详细介绍了如何基于YOLOv5、YOLOv6、YOLOv7、YOLOv8模型实现一个完整的活体人脸检测系统。系统包括数据集准备、模型训练、UI界面设计以及实时检测功能的实现。通过YOLO系列模型的应用,我们能够高效、准确地进行人脸检测和活体验证。未来,随着YOLOv9和其他新一代目标检测模型的出现,我们可以进一步提高检测精度和速度。此外,集成更多的传感器数据(如深度传感器、红外线传感器)可以使活体检测系统更加安全和稳定。

YOLO 544

SAP HANA 中的 Union Node Pruning:让 Calculation View 少走弯路的关键优化

摘要:SAP HANA的Union Node Pruning技术通过在执行前排除无关数据源来优化查询性能。该技术主要采用三种方式:Constant Mapping(适用于规则稳定的场景)、Pruning Configuration Table(灵活性高)和Column-Based Pruning(基于列可用性)。典型应用场景包括分层存储的数据查询,如区分当前和历史销售数据。需要注意的是,当查询发生Unfolding且不含聚合时,Pruning可能失效,此时可通过NO_CALC_VIEW_UNFOLDING提

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 875

java虚拟机的heap监狱_Java虚拟机的Heap监狱

原标题:Java虚拟机的Heap监狱 文章转自公众号:码农翻身在Java虚拟机中,我是一个位高权重的大管家,他们都很怕我,尤其是那些Java 对象,我把他们圈到一个叫做Heap的“监狱”里,严格管理,生杀大权尽在掌握。中国人把Stack翻译成“栈”,把Heap翻译成“堆”, 还有人会把Stack翻译成“堆栈”,唉,真不知道他们是怎么想的, 不过这么多年都过来了,你们明白就好。碰巧我会对Heap中的...

weixin_28749363的博客 98

向华为学习——IPD流程体系之IPD术语

《IPD体系核心概念与业务术语解析》摘要: IPD(集成产品开发)是一种以市场为导向的结构化产品开发管理模式,通过跨部门协作、异步开发、CBB(通用构建模块)和管道管理等手段,实现产品全生命周期高效管理。体系包含七大核心要素:跨部门团队(如IPMT决策层、PDT执行层)、结构化流程(分阶段评审)、端到端项目管理(WBS分级计划)、客户需求分析、投资组合优化及质量管控(TR技术评审)。各业务领域术语涵盖财务(NPV、IRR)、开发(需求分解、基线化)、制造(可制造性设计)、采购(Sourcing团队)及市场(

cdfunlove的博客 483

Java虚拟机的Heap监狱(JVM、新生代、Minor GC、老年代、Full GC)

转自:码农翻身(微信号:coderising) 在Java虚拟机中,我是一个位高权重的大管家,他们都很怕我,尤其是那些Java 对象,我把他们圈到一个叫做Heap的“监狱”里,严格管理,生杀大权尽在掌握。 中国人把Stack翻译成“栈”,把Heap翻译成“堆”, 还有人会把Stack翻译成“堆栈”,唉,真不知道他们是怎么想的, 不过这么多年都过来了,你们明白就好。 碰巧我会对Heap中的Java ...

书写人生 203

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Java老年代 full gc_Java虚拟机的Heap监狱(JVM、新生代、Minor GC、老年代、Full GC)...

转自:码农翻身(微信号:coderising)在Java虚拟机中,我是一个位高权重的大管家,他们都很怕我,尤其是那些Java 对象,我把他们圈到一个叫做Heap的“监狱”里,严格管理,生杀大权尽在掌握。中国人把Stack翻译成“栈”,把Heap翻译成“堆”, 还有人会把Stack翻译成“堆栈”,唉,真不知道他们是怎么想的, 不过这么多年都过来了,你们明白就好。碰巧我会对Heap中的Java 对象做...

weixin_36455339的博客 104

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: 端午节送粽子了!
下一篇: 从世界杯竞猜骗局谈二分法
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值