JVM堆内存空间(heap)

在Java程序运行时,系统运行过程中产生的大部分实例对象以及数组对象都会被放到堆中存储。

默认情况下,如果不通过参数强制指定堆空间大小,那么JVM会根据当前所在的平台进行自适应调整,起始大小默认为当前物理机器内存的1/64,最大大小默认为当前物理机器内存的1/4。

创建Java堆时,本质上并不是直接在内存中划分了一块完整的空间给JVM,因为在《Java虚拟机规范》中提及到:堆空间在物理上可以是不连续的,只需要逻辑上视为连续即可。所以一个JVM的堆空间在实际的机器内存上,可能是由机器内存中多个不同位置的空间组成的,如下图:
在这里插入图片描述
VM的堆空间结构会根据运行时具体采用的GC收集器来决定。在所有的GC收集器中,大体会将堆空间分为分代、分区两大类:
在这里插入图片描述

JDK 堆不同版本的区别

Java堆同时也是变化比较频繁的区域,在不同Java版本中,堆空间也发生了不同的改变:

● JDK7及之前:堆空间包含新生代、年老代以及永久代。
● JDK8:堆空间包含新生代和年老代,永久代被改为元数据空间,位于堆之外。
● JDK9:堆空间从逻辑上保留了分代的概念,但物理上本身不分代。
● JDK11:堆空间从此以后逻辑和物理上都不分代。

本质上来说,影响堆空间结构的并不是Java版本的不同,Java堆结构是跟JVM运行时所使用的垃圾回收器息息相关的,由GC器决定了运行时的堆空间会被划分为何种结构。

在JDK1.8及之前的Java版本中,几乎所有的GC器都会把堆空间划分为至少两个区域:新生代和年老代,但在JDK1.9到之后的GC器中,大多数的GC器开始了不分代的路子(具体原因稍后分析)。

分代堆空间

分代的含义是指在JVM运行过程中,堆空间是否会被分为不同的区域分别用于存储不同生命周期的对象实例,JDK1.8之前的堆结构是完全分代的,也就是指逻辑+物理上都分代,在运行时物理内存会被划为几块不同的区域,也就是一个Eden区、两个Survivor 区(Form/To区)以及一个Old区,从物理内存上来说各个区域都是完整且连续的内存,每块区域都用于存储不同周期的对象实例,相互之间并不干扰。

不分代堆空间

到了JDK1.9时,G1正式出道,成为了JVM内嵌的默认GC器,Java堆空间从此出现了不分代的概念,但不分代也分为两种情况,一种是逻辑分代,物理不分代,另一种则是逻辑+物理都不分代。

逻辑分代,物理不分代(G1):对象分配的逻辑上还是存在分代的思想,但是物理内存上不会再分为几块完整的分代空间。
逻辑+物理都不分代(ZGC、ShenandoahGC):无论从对象分配的逻辑上还是物理内存上,都不存在分代的概念。

JDK7及之前的堆内存空间划分

在JDK1.7及之前的JVM中,所有的GC器都是物理+逻辑都分代的,包括内嵌的默认GC器Parallel Scavenge(新生代)+ Parallel Old(老年代)也分代,所以一般堆空间会被划分为三个区域:新生代、年老代以及永久代:
● 新生代:一个Eden区、两个Survivor区(Form/To区),比例:8:1:1
● 年老代:一个Old区
● 永久代:方法区
在这里插入图片描述

JDK8堆内存空间划分

到了JDK1.8的时候,JVM将永久代,也就是方法区整合成了元数据空间,并且将其移出了堆,将其放在堆空间外的本地内存中。
在这里插入图片描述

JDK1.8的时候没啥好讲的,和1.7差距不大,最大区别在于移除了方法区,在本地内存中加入了元数据空间来存储之前方法区中的大部分数据(原方法区中的数据并不是所有都被迁移到了元空间存储,有些数据被分散到了JVM各个区域)。除此之外,常量池在1.8的时候也被移到了堆外。

JDK9堆内存空间划分

到了JDK1.9时,堆空间慢慢的开始了划时代的改变,在此之前,堆空间的布局都是采用分代存储的方式,无论从逻辑上还是从物理内存上,都是分代的。但是到了jdk9堆分代根据收集器来使用物理和逻辑分代收集器或逻辑分代收集器

  1. 逻辑分代 (Logical Generations):
    ○ 在逻辑分代中,堆内存被逻辑上划分为不同的区域(如新生代和老年代),但这些区域的实际物理存储并不一定是连续的或固定的。
    ○ 这种分代方式使得垃圾收集器可以根据实际需求动态地调整各个区域的大小和分布。
  2. 物理分代 (Physical Generations):
    ○ 在物理分代中,堆内存被明确地划分为不同的物理区域(如新生代和老年代),这些区域的边界是固定的。
    ○ 这种分代方式使得垃圾收集器更容易管理各个区域,但也限制了动态调整的能力。

在 JDK 9 及之后的版本中,尽管堆内存仍然分为新生代和老年代,但垃圾收集器的实现细节和策略有所不同。以下是一些主要的变化:

1. G1 垃圾收集器

G1 垃圾收集器在 JDK 9 及之后的版本中得到了进一步的改进和完善,也是默认收集器。逻辑分代,G1 的主要特点包括:

● 分区式垃圾收集:G1 将堆内存划分为多个固定大小的 Region,每个 Region 的大小通常是 1MB 到 32MB。
● 并发标记:G1 可以在应用程序运行的同时进行标记操作,减少了应用程序的暂停时间。
● 可控的暂停时间:G1 收集器旨在预测性地控制垃圾收集的暂停时间,使其适合大规模应用。

在 G1 中,新生代和老年代的概念仍然存在,但它们是由多个 Region 动态组成的。例如,一部分 Region 可以被分配给新生代,另一部分 Region 可以被分配给老年代。
在这里插入图片描述

JDK1.9时,G1将Java堆划分为多个大小相等的独立的Region区域,不过在HotSpot的源码TARGET_REGION_NUMBER定义了Region区的数量限制为2048个(实际上允许超过这个值,但是超过这个数量后,堆空间会变的难以管理)。
一般Region区的大小等于堆空间的总大小除以2048,比如目前的堆空间总大小为8GB,就是8192MB/2048=4MB,那么最终每个Region区的大小为4MB
G1保留了年轻代和老年代的概念,但不再是物理隔阂了,它们都是可以不连续物理内存来组成的Region的集合。

G1中的年老代晋升条件和之前的无差,达到年龄阈值的对象会被转入年老代的Region区中,不同的是对于大对象的分配,在G1中不会让大对象进入年老代,在G1中由专门存放大对象的Region区叫做Humongous区,如果在分配对象时,判定出一个对象属于大对象,那么则会直接将其放入Humongous区存储。

Humongous区存在的意义:可以避免一些“短命”的巨型对象直接进入年老代,节约年老代的内存空间,可以有效避免年老代因空间不足时的GC开销。
当堆空间发生全局GC(FullGC)时,除开回收新生代和年老代之外,也会对Humongous区进行回收。

2. 其他垃圾收集器

其他垃圾收集器,如 Serial Collector、Parallel Collector 和 CMS Collector,在 JDK 9 及之后的版本中仍然保留了新生代和老年代的概念。

在 JDK 9 及之后的版本中,JVM 的堆内存仍然保留了分代的概念,分为新生代和老年代。尽管在一些细节上有所变化,但这种分代的概念有助于垃圾收集器更高效地管理内存。

● G1 垃圾收集器:通过分区式垃圾收集、并发标记和可控的暂停时间,使得 G1 成为现代 Java 应用程序中常用的垃圾收集器之一。
● 其他垃圾收集器:仍然保留了新生代和老年代的概念,并在不同场景下具有各自的优势

JDK11的垃圾收集器

默认垃圾回收器G1
jdk11引入的ZGC
在JDK11的时候,Java又推出了一款新的垃圾回收器ZGC,它也是一款基于Region区内存布局的GC器,这款GC器是真正意义上的不分代,无论是从逻辑上还是物理上都不分代。
在这里插入图片描述
在ZGC中,也会把堆空间划分为一个个的Region区域,但ZGC中的Region区不存在分代的概念,它仅仅只是简单的将所有Region区分为了大、中、小三个等级:
● 小型Region区(Small):固定大小为2MB,用于分配小于256KB的对象。
● 中型Region区(Medium):固定大小为32MB,用于分配>=256KB ~ <=4MB的对象。
● 大型Region区(Large):没有固定大小,容量可以动态变化,但是大小必须为2MB的整数倍,专门用于存放>4MB的巨型对象。但值得一提的是:每个Large区只能存放一个大对象,也就代表着你的这个大对象多大,那么这个Large区就为多大,所以一般情况下,Large区的容量要小于Medium区,并且需要注意:Large区的空间是不会被重新分配的

实际上,JDK11中的ZGC并不是因为要抛弃分代理念而不设计分代的堆空间的,因为实际上最开始分代理念被提出的本质原因是源于「大部分对象朝生夕死」这个概念的,而实际上大部分Java程序在运行时都符合这个现象,所以逻辑分代+物理不分代是堆空间最好的结构方案。

堆总结

Java堆空间是JVM运行时内存区域中占比最大的一块,此内存区域唯一的目的就是存储运行时创建出的对象实例。同时,随着运行时采用的GC器不同,Java堆也会被分为不同的结构,其中主要可分为分代和不分代的两类结构。相对来说,分代结构是最适合Java对象“朝生夕死”的特性的,如果堆结构是分代的,可以使得JVM能够更好的管理堆内存中的对象,包括内存的分配以及回收。

有兴趣的同学可以加群
在这里插入图片描述

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

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

相关文章

基于ssm+vue的汽车租赁管理系统

摘要 随着移动应用技术的发展&#xff0c;越来越多的用户借助于移动手机、电脑完成生活中的事务&#xff0c;许多的传统行业也更加重视与互联网的结合&#xff0c;以提高商家知名度和寻求更高的经济利益。针对传统汽车租赁系统&#xff0c;租赁信息、续租信息等问题&#xff0c…

【算法每日一练及解题思路】找出模式匹配字符串的异位词在原始字符串中出现的索引下标

【算法每日一练及解题思路】找出模式匹配字符串的异位词在原始字符串中出现的索引下标 一、题目&#xff1a;找出模式匹配字符串的异位词在原始字符串中出现的索引下标 二、举例&#xff1a; 两个字符串原始字符串initStr123sf3rtfb,模式匹配字符串regxf3s&#xff0c;找到模…

区域生长算法详解与Python实现

图像分割是计算机视觉中一个重要的任务&#xff0c;区域生长算法是其中的一种常见方法。本文将详细介绍区域生长算法的原理&#xff0c;并通过Python代码实现&#xff0c;带你一步步理解它的实际应用。 1. 区域生长算法简介 区域生长算法是一种基于像素相似性进行图像分割的方…

【方法论】读论文的三个层次,四个阶段,十个问题

学习资料 - 沈向洋十问 如何正确阅读一篇科研论文 阅读理解作者的意图&#xff0c;不同的阅读需求对应不同的阅读层次&#xff08;速读&#xff0c;精读&#xff0c;研读&#xff09; 速读&#xff1a;标题&#xff0c;引言&#xff0c;摘要&#xff0c;结论 文章要解决什么…

并发编程之定时任务定时线程池

并发编程之定时任务&定时线程池-CSDN博客

Upload-LABS通关攻略【1-20关】

Pass-01 第一关是前端JS绕过 上传一个php文件显示只能上传特定后缀名的文件 这里将1.php改为1.jpg直接进行抓包&#xff0c;在数据包中将jpg改为php放行 文件上传成功&#xff0c;邮件图片新建页面打开 可以访问到1.php文件&#xff0c;则一句话密码上传成功 使用蚁剑 进行连接…

六、vue进阶知识点

一、scoped解决样式冲突 默认情况:写在组件中的样式会 全局生效→ 因此很容易造成多个组件之间的样式冲突问题。 1.全局样式:默认组件中的样式会作用到全局 2.局部样式:可以给组件加上 scoped 属性,可以让样式只作用于当前组件scoped原理? 1.当前组件内标签都被添加 data-v-…

智慧猪场实训中心解决方案

一、引言 随着科技的飞速发展&#xff0c;传统养猪业正经历着前所未有的变革。为了提高养猪效率、降低生产成本并保障猪只健康&#xff0c;智慧养猪场的概念应运而生。唯众特此推出《智慧猪场实训中心解决方案》&#xff0c;旨在通过先进的技术与管理手段&#xff0c;为养猪业培…

RTA-OS Port Guide学习(一)-基于S32K324 OS

文章目录 前言OS Port的安装Port CharacteristicsParameters of ImplementationConfiguration ParametersStack used for C-startup(SpPreStartOS)Stack used when idle (SpStartOS)Stack overheads for ISR activation (SpIDisp)Stack overheads for ECC tasks (SpECC)Stack o…

uniapp uni-popup底部弹框留白 底部颜色修改 滚动穿刺

做底部弹框的时候&#xff0c;可能出现以下场景需要处理。 一、出现底部留白不是白色&#xff0c;需要修改颜色的时候&#xff1a; 1、如果弹框不需要圆角效果&#xff0c;则在uni-popup加上背景色就行&#xff0c;弹框是个直角样式&#xff1a; 2、如果需要圆角效果&#xff0…

vue3本地运行错误集

1、解决报错ValidationError: Progress Plugin Invalid Options问题 ValidationError: Progress Plugin Invalid Optionsoptions should NOT have additional propertiesoptions should NOT have additional propertiesoptions should NOT have additional propertiesoptions …

「Claude3.5」全面超越「gpt-4o」,我用它做了个贪吃蛇,玩了一整天!

大家好&#xff0c;我是凡人。 就在昨天晚上Anthropic在X上连续发了4条动态来高调宣布他们的Claude 3.5 Sonnet中杯的版本已经全面向公众开放使用&#xff0c;大批的技术博主连夜测试&#xff0c;纷纷给出的不低的评价。 而这还仅仅是开胃小菜&#xff0c;官方宣称今年晚些时候…

苹果mac数据恢复概率大吗 mac数据恢复专业软件哪个好用

一般情况下&#xff0c;当我们把电脑中的数据删掉后&#xff0c;都会保存在回收站里面&#xff0c;但如果回收站被清空了或者数据在回收站中没有找到的话&#xff0c;那么&#xff0c;之前被删掉的数据还能恢复吗&#xff1f;恢复的概率有多大呢&#xff1f; 答案是可以的&…

【微服务】限流、熔断和降级(持续更新中~)

1、限流 1.1 什么是限流 限流&#xff08;Rate Limiting&#xff09;是一种常用的技术手段&#xff0c;用于控制系统对资源的访问速率&#xff0c;确保系统的稳定性和可靠性。在分布式系统、Web服务、API接口等场景中&#xff0c;限流尤为重要。通过限制请求的频率或数量&…

每天五分钟计算机视觉:人脸识别网络FaceNet

本文重点 在前面的课程中,为了解决人脸识别的问题,我们学习了Siamese神经网络。本文我们学习另外一种人脸识别网络模型FaceNet。 论文 FaceNet: A Unified Embedding for Face Recognition and Clustering FaceNet概述 FaceNet是谷歌在CVPR 2015上提出的一种深度学习模型,…

【Redis】Redis 持久化 AOF、RDB—(七)

目录 一、AOF 日志二、RDB 内存快照 Redis 一旦服务器宕机&#xff0c;内存中的数据将全部丢失&#xff0c;从后端数据库恢复这些数据&#xff0c;对数据库压力很大&#xff0c;且性能肯定比不上从 Redis 中读取&#xff0c;会拖慢应用程序。所以&#xff0c;对 Redis 来说&…

Linux awk案例

目录 1. 查询时间超过2000毫秒的请求2. 查询指定列组合出现的次数3. 统计所有文件的大小4. 获取大于指定大小的文件名&#xff0c;并按照从大到小排序5. grep指定字段后&#xff0c;使用awk列转行6. 查询第四个字段等于指定值的内容 1. 查询时间超过2000毫秒的请求 ✅log: 202…

初等数学几百年重大错误:N各元n的对应n+1的全体是N的真子集N+——百年病态集论的症结

黄小宁 数学图可是“离散”的点组成的点集N&#xff5b;0&#xff0c;1&#xff0c;2&#xff0c;…&#xff0c;n&#xff0c;…0&#xff5d;&#xff08;各数是点的坐标&#xff09;。设本文所说集合往往是元不少于两个的集。定义&#xff1a;若数&#xff08;点&#xff09…

实现一个能设置MaxLine的LayoutManager

实现一个能设置MaxLine的LayoutManager 有时候&#xff0c;我们会遇到这种需求&#xff1a;一个线性的列表布局&#xff0c;当item量很少的时候&#xff0c;就是wrap_content直接展示完所有item&#xff0c;但是当item数量超过某个数时就要固定高度&#xff0c;让其变成可滑动…

jmeter如何把一个请求的响应中部分字段提取出来便于下个请求用

jmeter如何把一个请求的响应中部分字段提取出来便于下个请求用&#xff0c;可以通过json提取器提取&#xff0c;如果提取多个&#xff0c;就设置多个json提取。 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dd5afb1fca3f4e31b636e17e11e8dfc3.png