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 -…...

Java 基础(3)—synchornized 关键字简单理解
一、synchronized 修饰同步代码块 用 synchronized 修饰代码段作为同步锁,代码如下: public class LockDemo {public Object object new Object();public void show(){synchronized (object) {System.out.println(">>>>>>hell…...

【Linux】调试工具gdb的使用
环境:centos7.6,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹前言在前文,我们已经讲解了vim工具以及gcc/g的使用,我们可以进行编写代码以及编译代码了,但是还没有学习如何在Linu…...

大数据知识图谱项目——基于知识图谱的医疗知识问答系统(详细讲解及源码)
基于知识图谱的医疗知识问答系统 一、项目概述 本项目基于医疗方面知识的问答,通过搭建一个医疗领域知识图谱,并以该知识图谱完成自动问答与分析服务。本项目以neo4j作为存储,基于传统规则的方式完成了知识问答,并最终以关键词执…...

威马汽车:跃马扬鞭未竟,鞍马劳顿难行?
“活下去,像牲口一样地活下去。” 威马汽车创始人、董事长兼CEO沈晖1月在社交媒体上分享的电影台词,已然成为威马近况的真实写照。 来源:新浪微博威马汽车沈晖Freeman 最近,网上出现了大量关于“威马汽车将实施全员停薪留职”的…...

【网络】网络基础
🥁作者: 华丞臧. 📕专栏:【网络】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉 LeetCode刷题网站 文章…...

Linux系统之Uboot、Kernel、Busybox思考之三
目录 三 内核的运行 5-中断子系统 6 锁、延迟与原子上下文 7 内存管理子系统 8 驱动的两类框架 三 内核的运行 5-中断子系统 中断子系统的数据结构及设计思想。 中断子系统需要解决中断管理的问题。 如果系统中断较少的话,其管理就不用设计这样一个中断子系统这…...

FPGA 20个例程篇:20.USB2.0/RS232/LAN控制并行DAC输出任意频率正弦波、梯形波、三角波、方波(一)
在最后一个例程中笔者精挑细选了一个较为综合性的项目实战,其中覆盖了很多知识点,也是从一个转产产品中所提炼出来的,所以非常贴近实战项目。 整个工程实现了用户通过对上位机PC端人机界面的操作,即可达到控制豌豆开发并行DAC输出…...

性能测试学习和性能瓶颈分析路线
很多企业招聘都只写性能测试,会使用LR,jmeter工具。其实会使用jmeter和LR进行性能测试还只是性能测试的第一步,离真正的性能测试工程师还很远,笔者也还在路上 .。 性能测试,都是要求测试系统性能,系统自然…...

达梦数据库(DM8)集成使用 Geoserver(2.22.2) 以及其他对应版本详解
达梦数据库(DM8)集成使用 Geoserver(2.22.2) 以及其他对应版本详解系统环境版本Geoserver 驱动对应版本达梦 8 集成 Geoserver 过程试错过程问题总结项目需要国产化,选择使用达梦数据库,在技术测试阶段&…...

全开源无加密的RuleApp文章社区APP客户端源码
内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 开源无加密的文章社区客户端源码分享 RuleApp文章社区,VIP会员,写作投稿积分商城,付费模块集成,多平台兼容这是一款开源免费,界…...