JVM内存结构分析:为什么需要S0和S1?

一、为什么会有年轻代

我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来。

二.年轻代中的GC

新生代大小(PSYoungGen total 9216K)=eden大小(eden space 8192K)+1个survivor大小(from space 1024K)

HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8(Eden):1(一个survivor),为啥默认会是这个比例,接下来我们会聊到。一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。
因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。
在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。
在这里插入图片描述

三、一个对象的这一辈子

我是一个普通的Java对象,我出生在Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就被迫去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。

四、为什么要有Survivor区

先不去想为什么有两个Survivor区,第一个问题是,设置Survivor区的意义在哪里?
在这里插入图片描述
如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)。老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。你也许会问,执行时间长有什么坏处?频发的Full GC消耗的时间是非常可观的,这一点会影响大型程序的执行和响应速度,更不要说某些连接会因为超时发生连接错误了。

好,那我们来想想在没有Survivor的情况下,有没有什么解决办法,可以避免上述情况:
在这里插入图片描述
显而易见,没有Survivor的话,上述两种解决方案都不能从根本上解决问题。

我们可以得到第一条结论:Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。

五、为什么要设置两个Survivor区

设置两个Survivor区最大的好处就是解决了碎片化,下面我们来分析一下。

为什么一个Survivor区不行?第一部分中,我们知道了必须设置Survivor区。假设现在只有一个survivor区,我们来模拟一下流程:
刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
我绘制了一幅图来表明这个过程。其中色块代表对象,白色框分别代表Eden区(大)和Survivor区(小)。Eden区理所当然大一些,否则新建对象很快就导致Eden区满,进而触发Minor GC,有悖于初衷。
在这里插入图片描述
碎片化带来的风险是极大的,严重影响Java程序的性能。堆空间被散布的对象占据不连续的内存,最直接的结果就是,堆中没有足够大的连续内存空间,接下去如果程序需要给一个内存需求很大的对象分配内存。。。画面太美不敢看。。。这就好比我们爬山的时候,背包里所有东西紧挨着放,最后就可能省出一块完整的空间放相机。如果每件行李之间隔一点空隙乱放,很可能最后就要一路把相机挂在脖子上了。

那么,顺理成章的,应该建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中。下图中每部分的意义和上一张图一样,就不加注释了。
在这里插入图片描述
上述机制最大的好处就是,整个过程中,永远有一个survivor space是空的,另一个非空的survivor space无碎片。

那么,Survivor为什么不分更多块呢?比方说分成三个、四个、五个?显然,如果Survivor区再细分下去,每一块的空间就会比较小,很容易导致Survivor区满,因此,我认为两块Survivor区是经过权衡之后的最佳方案。

原文:https://www.cnblogs.com/duanxz/p/6076662.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rabbitmq-消息追踪rabbitmq_tracing

【README】 消息中心的消息追踪需要使用 Trace 实现,Trace是 rabbitmq用于记录每一次发送的消息;方便开发者调试,排错。可通过插件形式提供可视化界面。 【1】 开启消息追踪 1)消息追踪通过 rabbitmq的插件 trace 来实现&#x…

python大神交流网站_学习Python必去的8个网站

作为一个现时代的程序员初学者,除了看书之外,互联网的学习手段也是断不能少的! 以下这些网站,虽说不上全方位的满足你的需求,但是大部分也都能! 0.国外的大神GitHub : https://github.com/pypa/…

一文理清Http2.0

前言 HTTP2.0主要有三大特性:二进制协议、头部压缩、服务端推送(Server Push)、多路复用。本文从分析http1.x存在的问题入手,逐一介绍http2.0的优势。 Http1.x存在的问题 在HTTP1.0下,HTTP1.1非Keep-Alive模式下&am…

收敛和发散思维如何被用作解决问题的手段

转自: https://www.jdon.com/mda/thinking.html 将发散和收敛的思想结合在一起使用时,可以帮助分析人员得出更好的和更有创造性的解决方案。发散性思维是将一个话题分解并产生许多从原始概念中分支出来的想法的过程,而收敛性思维则是集中于少…

关于python面向对象编程中、下列说法中_关于Python面向对象编程的知识点总结

前言 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。 接下来我们就来了解关于Python面向对象编程的知…

Java开发必会的反编译知识

转载自 Java开发必会的反编译知识 编程语言在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language)。编程语言(Programming Language)分为低级语言(Low-level Language)和高…

happen-before原则的理解

前言 在程序执行时,为了提高性能,编译器和处理器会对指令进行重排序。 为了明确定义多线程场景下重排序的问题(可见性、有序性、原子性),Java引入了JMM(Java Memory Model),也就是Java内存模型。JMM为JAV…

转:RabbitMQ 消息队列特性知多少

转自: https://www.jianshu.com/p/94d6d5d98c3d 序言 现在我们每天都要与信息打交道,主动或被动的在创造或接收消息。你会收到话费通知短信,使用微信 QQ跟远在万里的朋友交流,也可能使用钉钉跟同事讨论工作,使用抖音…

easyui根据select下拉框内容更新表单内容_Ant Design 4.0 的一些杂事儿 - Select 篇

前几篇:Ant Design 4.0 的一些杂事儿 - Table 篇Ant Design 4.0 的一些杂事儿 - Form 篇聊完了 Table 和 Form 两个重型组件,我们来继续聊聊看起来不那么重的 Select 组件。它在 Ant Design 4.0 中有哪些变化。如果你读过 《Ant Design 4.0 进行时》&…

避免代码冗余,使用接口和泛型重构Java代码

转载自 避免代码冗余,使用接口和泛型重构Java代码在使用动态语言和.NET工作了若干年后,我又回到老本行–Java开发。在Ruby中,清除代码冗余是非常方便的,而在Java中则需要结合接口和泛型实现类似的功能。 原始代码 以下是这个类中的…

一文理类加载相关知识:类加载器、双亲委派、SPI

思维导图 类加载的时机 类加载的流程 类从被加载到内存中开始,直到被从内存中卸载为止,它的整个生命周期包括:验证、准备、解析、初始化、使用和卸载7 个阶段。 其中验证、准备、解析 3 个部分统称为连接(Linking) …

可以搜python编程答案的软件_python实现百万答题自动百度搜索答案

用python搭建百万答题、自动百度搜索答案。 使用平台 windows7 python3.6 MIX2手机 代码原理 手机屏幕内容同步到pc端 对问题截图 对截图文字分析 用浏览器自动搜索文本 使用教程 1、使用Airdroid 将手机屏幕显示在电脑屏幕上。也可使用360手机助手实现。不涉及任何代码。实现效…

intellij idea设置主题、字体样式和背景色

转自&#xff1a; https://blog.csdn.net/fanrenxiang/article/details/80598895 点击这里查看 <intellij idea使用教程汇总篇> 引言&#xff1a;所谓工欲善其事必先利其器&#xff0c;idea就是这样的利器&#xff0c;刚装好的intellij idea主题样式是白的&#xff0c;…

MySQL优化(四):count()

count()不同写法的区别 COUNT(字段名)&#xff1a;返回SELECT语句检索的行中值不为NULL的行数 COUNT(1)&#xff1a;表示的是直接查询符合条件的数据库表的行数&#xff08;会包含值为NULL的行数&#xff09;。其中1指的是表中的第一个字段&#xff0c;如有表 table(id, colu…

图像sobel梯度详细计算过程_数字图像处理(第十章)

点、线、边缘检测背景知识。书中主要介绍了图像的一阶导数与二阶导数&#xff0c;这个之前的文章中有过介绍这里在复习一遍。对于函数 ,对于点 在x方向的一阶偏导为&#xff1a;,二阶偏导为&#xff1a;之后书中总结了一阶导与二阶导对于图像求取边缘的结论&#xff1a;孤立点检…

idea部署maven+javaweb项目到jboss

小编习惯使用eclipse对jboss跑的项目部署,第一次使用idea进行jboss部署项目,遇到很多问题,做此文章以帮助更多人. 图中涂鸦的是项目名,对应上自己的项目名即可 1.导入项目,这一步不多说 2.配置项目: a>点击file-->Project-Stucture-->Project 3.配置Modules 配置…

Java8-本地缓存

转载自 Java8-本地缓存这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存。因为Map有一个新的方法可以在key为Null的时候自动计算一个新的value值。非常完美的实现cache。来看下代码&#xff1a;12345678910111213141516publicstatic void main(String…

Integer和Int的比较,谈谈拆卸和装箱

示例代码 public static void main(String[] args) {Integer a new Integer(10111);int b 10111;boolean equal1 a b;//自动拆箱&#xff0c;xxxValue()boolean equal2 a.equals(b);//自动装箱, valueOf()System.out.println(equal1);System.out.println(equal2); }反编译…

python调用webservice接口实例_python调用webservice接口的实现

使用suds这个第三方模块 from suds.client import Client url http://ip:port/?wsdl cilentClient(url) print cilent 查看webservice接口的具体信息&#xff1a; 调用接口方法&#xff0c;通常 client.service.methodname 实际测试过程中遇到的坑&#xff1a; 1、tns 值为Lo…

idea2021部署maven+javaweb项目到jboss(diy)

【README】 我为什么要写这个文章&#xff0c;看了这位老哥的博文 https://blog.csdn.net/PacosonSWJTU/article/details/118074604 部署成功了&#xff0c;很感谢&#xff0c;所以也想照做一下&#xff1b; 【1】创建web项目module &#xff08;Project02 是一个空项目&…