JVM学习笔记六:运行时数据区之堆
目录
概述
堆空间内部结构
JDK7版本
JDK8版本
堆空间的内存划分
堆空间大小设置参数
概述
Java堆是虚拟机所管理的内存中最大的一块,其在JVM启动时即被创建,并且空间大小也被确定(这里是不考虑Java8之后以本地内存来实现的元空间,在Java8之前可以很确切的这么说,个人认为如果将其与元空间比较意义并不大),同时也是所有线程共享的一块内存区域,此内存区域的唯一目的就是存放对象实例,”几乎“所有的对象实例都在这里分配(注意这里的“几乎”二字,除了堆上分配,还可以栈上分配,这依赖于逃逸分析技术的提高)。
堆内存被分为了:新生代(Young)、老年代(Old),新生代又划分为:伊甸区(Eden),幸存者0区(Survivor 0)和幸存者1区(Survivor 1)(有的资料也写作:from 区和 to 区)。
从Java堆的内存划分便可以体现出Java堆是内存回收的重点地区,这种划分形式也是为了更高效的实现垃圾回收。
堆空间内部结构
我们平常讨论的JVM如果没有特别指明类型的话,默认都是以HotSpot虚拟机而言,下文也是入此。
说到堆空间的内部结构,需要根据JDK的版本而定,在JDK7及之前,HotSpot虚拟机选择将方法区和堆空间合并实现,称作永久代,其好处就是省略了专门为方法区编写代码,可以复用堆空间的代码。但是以现在的眼光来看,还是存在诸多弊端。所以在JDK8改为用本地内存来实现方法区,称作元空间。
JDK7版本
方法区被叫做永久代,并且和堆空间合并一起实现。其实在JDK7时开发人员就已经意识到了缺陷并且在开始解决了,JDK7时将字符串常量池、静态变量从永久代中存放到堆空间中。
JDK8版本
移除永久代,用本地内存实现方法区改称元空间。其中原本存放在永久代中的类型信息、字段、方法、常量保存在本地内存的元空间,字符串常量池和静态变量依旧保存在堆中(堆是内存回收的重点区域,而字符串是开发中经常用到的,所以也需要频繁的清理,所以字符串常量池放在堆空间是合理的)。
堆空间的内存划分
堆空间被分为了新生代、老年代,新生代被划分为伊甸区、幸存者0区、幸存者1区。
堆内存默认结构占比:
新生代:老年代 = 1:2
伊甸区:幸存者0区:幸存者1区 = 8:1:1
堆空间大小设置参数
Java堆区用于存储Java对象实例,堆的大小在JVM启动时就已经设定好了,可以在启动时设置启动参数来指定堆空间的大小。
- “-Xms"用于表示堆区的起始内存,等价于
-XX:InitialHeapSize
- “-Xmx"则用于表示堆区的最大内存,等价于
-XX:MaxHeapSize
一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时,将会抛出OutOfMemoryError异常。
通常会将-Xms和-Xmx两个参数配置相同的值,其目的是为了能够在ava垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小,从而提高性能。
堆空间分代思想
上文已经提到了默认情况下堆空间的分代结构以及具体的内存大小划分。这种分代形式主要跟垃圾回收机制有关,垃圾回收机制大多数都遵循了分代收集的原则:
- 弱分代假说:绝大多数对象都是朝生熄灭的。
- 强分代假说:熬过越多次垃圾收集的对象就越难以消亡。
- 跨代引用假说:跨代引用相对于同代引用来说仅占极少数。
可以粗略的理解为:存放在堆空间的对象需要经常清理,但是对象与对象之间的存活周期也是不同的。那些存活周期比较长的对象存放在老年代中,朝生熄灭的对象存放在新生代中。可以通过设置对两个代的垃圾扫描频率来达到更高的回收效率,新生代的对象朝生熄灭那么就需要经常清理,老年代的存活周期长可以降低频率提高效率。
分代内存设置
设置新生代内存大小
“-XX:NewSize” 新生代的最小值
”-XX:MaxNewSize“ 新生代的最大值
“-XX:NewRatio” 设置新生代与老年代在堆空间的大小
"-XX:SurvivorRatio" 设置幸存者区和伊甸区的大小比值(注意:幸存者区有两个)
例1:-XX:NewSize=10M -XX:MaxNewSize=20M 设置新生代最小值为10M,最大值为20M。
例2:-XX:NewRatio=4 设置新生代和老年代的比值为4,即 新生代 :老年代 = 1 :4
例3:-XX:SurvivorRatio=8 表示 幸存者区和伊甸区的大小比例为 1 :8。
对象在堆中的分配过程
上面的流程图表示的是对象在堆中内存分配的过程,内存分配和内存回收密切相关。
- 创建的对象先放伊甸园区,此区有大小限制。
- 当伊甸园的空间填满时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(MinorGC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区。(值得注意的是,幸存者区空间填满时并不会触发垃圾回收,对幸存者区的回收是在MinorGC中顺便做的事情)
- 然后将伊甸园中的剩余对象移动到幸存者0区。
- 如果再次触发垃圾回收,此时上次幸存下来的被放到幸存者0区的对象如果没有被回收,就会放到幸存者1区。(幸存者两个区之间是通过标记复制算法进行垃圾回收的)
- 如果再次经历垃圾回收,此时会重新放回幸存者0区,接着再去幸存者1区。
- 对象什么时候能够去到老年代?JVM默认是经历了15次垃圾回收之后。当然也可以设置参数来控制:设置
-Xx:MaxTenuringThreshold=N
- 当老年代内存不足时,再次触发GC:Major GC,进行养老区的内存清理。
- 若老年代执行了Major GC之后,发现依然无法进行对象的保存,就会产生OOM异常。
下图主要描述的是幸存者区之间的关系。
上面的描述只是从宏观的角度描述了对象在堆中的内存分配,接下来仔细考虑以下几个问题:
具体的分配方式是什么?
对于第一个问题,首先需要清楚的是,对象所需的内存在类加载阶段完成后便可确定下来。为对象分配内存实际上就是将一块内存从java堆中划分出来存放这个对象。如果java堆中的内存是绝对规整的,即所有用过的内存放置在一边,所有没用过的内存放置在另一边。那么我们可以很方便的使用一个中间指针来分配内存,新的对象到来了中间指针就往空闲内存方向移动新的对象的内存大小的距离即可。这种分配方式称为“指针碰撞”(Bump The Pointer)。但是如果java堆中的内存并不是规整的,已使用过的和未使用过的内存交织在一起,就不能使用指针碰撞的方式分配内存了,虚拟机就需要维护一个列表,记录哪些内存块是可用的,分配时从列表中找到一块足够大的空间划分给对象即可,并更新列表上的记录,这种分配方式称为“空闲列表”(Free List)。选择哪种分配方式取决于java堆是否规整,而java堆是否规整又取决于所采用的垃圾收集器是否带有空间压缩整理的能力决定。
对象的分配是很频繁的操作,并发情况下是线程安全的吗?
对于第二个问题,对象创建时并发情况下可能出现正准备分配给A对象的内存在指针还没来得及分配时,B对象又使用了这一块内存区域的情况。解决这个问题有两种可选方案:第一种就是对分配内存空间的动作进行同步处理,虚拟机采用的是CAS配上失败重试的方式来保证更新操作的原子性。另一种方式是把内存分配的动作按照线程划分在不同的空间中进行,给每一个线程在java堆中预先分配一小块内存,称为本地线程分配缓冲,线程要在堆中分配内存,首先在各自的本地缓冲区中分配,本地缓冲区用完了,分配新的缓冲区时才需要同步锁定。
相关文章:

JVM学习笔记六:运行时数据区之堆
目录 概述 堆空间内部结构 JDK7版本 JDK8版本 堆空间的内存划分 堆空间大小设置参数 概述 Java堆是虚拟机所管理的内存中最大的一块,其在JVM启动时即被创建,并且空间大小也被确定(这里是不考虑Java8之后以本地内存来实现的元空间&…...

usb闪存驱动器数据恢复该怎么进行?3个方法总结
“怎么办?我的USB驱动器不知道因为什么原因,里面的数据、文件都消失了。有没有什么方法在没有进行备份的情况下恢复从U盘丢失的数据?” USB驱动器作为最常用的存储移动设备,里面保存着各种文件数据。但是有时会出现损坏而导致数据…...

DAX 微信 markdown 编辑器
DAX 微信 markdown 编辑器 一、致谢 感谢开源项目: md wechat-format 感谢 WordPress 插件 Mine云点播 作者 mine27 的指导。 二、如何使用 打开如下地址,直接编辑,可以实时看到符合微信公众号排版的效果。 推荐访问:https://j…...
湖南中创教育为学员提供方便快速的退费服务
2006年,湖南中创教育科技有限公司创始人团队开始创业进入职业教育行业;2014年公司正式成立,组建专业团队并转型升级“互联网”,进入在线教育行业。 自主研发“中创网校”学习平台,为学员提供了集直播、视频回放复习、…...

Java 给视频添加背景音乐 | Java工具
目录 前言 Maven依赖 环境依赖 代码 总结 前言 本文提供给视频添加背景音乐的java工具,一如既往的实用主义。 Maven依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1…...

【JUC2022】第二章 多线程锁
【JUC2022】第二章 多线程锁 文章目录【JUC2022】第二章 多线程锁一、乐观锁与悲观锁1.悲观锁2.乐观锁二、八锁案例1.标准情况,有a、b两个线程,请问先打印邮件还是短信【结果:邮件】2.sendEmail方法中加入暂停3秒钟,请问先打印邮件…...

快学会这个技能-.NET API拦截技法
大家好,我是沙漠尽头的狼。 本文先抛出以下问题,请在文中寻找答案,可在评论区回答: 什么是API拦截?一个方法被很多地方调用,怎么在不修改这个方法源码情况下,记录这个方法调用的前后时间&…...

stm32f407探索者开发板(十八)——串口通信实验讲解(USART_RX_STA流程图详解)
文章目录一、uart_init(串口初始化)二、USART1_IRQHandler(串口1中断服务程序)三、main.c(主函数)四、关于printf的支持一、uart_init(串口初始化) 就是根据上一篇的一样的步骤&…...
Hystrix资源隔离
目录资源隔离使用资源隔离的好处基于Hystrix实现微服务中资源隔离基于Hystrix线程池隔离实现资源隔离利用 HystrixCommand 获取单条数据利用 HystrixObservableCommand 批量获取数据基于 Hystrix 信号量机制实现资源隔离资源隔离 资源隔离是什么? 资源隔离是指把对…...

字符串(一)-- LeetCode[3] 无重复字符的最长子串
1 无重复字符的最长子串 1.1 题目描述 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释…...

Qt中修改界面类的类名时需要注意的几个修改点
有些时候因为一些原因,需要修改Qt中创建的界面类,需要特别注意几个修改点。 比如将test类修改为test2类 修改test.h名称为test2.h文件;修改test.cpp名称为test2.cpp文件;修改test.ui名称为test2.ui文件;修改pro文件中…...

【Spring6】| Spring启示录、Spring概述
目录 一:Spring启示录 1. OCP开闭原则 2. 依赖倒置原则DIP 3. 控制反转IoC 二:Spring概述 1. Spring简介 2. Spring8大模块 3. Spring特点 一:Spring启示录 引言:前面我们已经学习了三层架构:表示层、业务层、…...

react源码中的fiber架构
先看一下FiberNode在源码中的样子 FiberNode // packages/react-reconciler/src/ReactFiber.old.js function FiberNode(tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ) {// Instancethis.tag tag;this.key key;this.elementType null;t…...

C++类和对象-继承多态
继承 继承是面向对象三大特性之一 定义类时,下级别的成员除了拥有上一级的共性,还有自己的特性,就可以考虑使用继承的技术,减少代码的重复 继承的基本语法 语法:class 子类 : 继承方式 父类 子类也被成为派生类父类…...

appium自动化测试
获取应用包名和入口activity:aapt命令 aapt目录: 安卓sdk的build-tools目录下(如果要在cmd里直接运行,要配置环境变量,否则需要在aapt所在目录下打开cmd) 示例: adt-bundle-windows-x86_64-20140702\sdk\build-too…...

打印流、转换流、数据流 、随机访问流
Java知识点总结:想看的可以从这里进入 目录5、打印流6、转换流7、数据流8、随机访问流5、打印流 实现将基本数据类型的数据格式转化为字符串输出,它们提供了一系列重载的print()和println()方法,用于多种数据类型的输出,这种流不会…...
Java的4种访问权限?
1、public: 所修饰的类、变量、方法,在内外包均具有访问权限;2、protected: 这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,但只对同包的类是可访问的,对外…...

APP任务模块功能借助php-resque实现业务解耦
先上设计图 说明:任务模块分一次性任务和每日任务,可能还包括男女用户任务区分 处理步骤: 一、同步任务数据库 1.1、任务列表数据库 1.2、完成任务数据库 二、搭建即时消息队列 一、composer require resque/php-resque二、因为服务器red…...
怎么做,才能在职场中晋升?
1 主动原则:主动做事 工作要积极主动,刚进入职场的同学,以为“服从命令听指挥”“领导指哪打哪”就是积极主动,结果易养 1.1 不好习惯 ① 认为主管肯定会帮你搞定晋升 你可能非常信任主管,认为自己只要把主管安排的…...

Vulnhub靶场----2、DC-2
文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-2下载地址:https://download.vulnhub.com/dc/DC-2.zip kali:192.168.144.148 DC-2:192.168.144.150 添加hosts文件:192.168.144.150 DC-2 二、渗透流程 nmap -A -…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...