JVM 内存模型与内存分配方式

文章目录

  • JVM 内存模型概述
    • 基于分代收集理论设计的垃圾收集器所管理的堆结构
    • 方法区的演变
  • 内存分配
    • 划分内存的方法
    • 划分内存时如何解决并发问题
    • 对象栈上分配
    • 基于分代收集理论的垃圾收集器管理下的内存分配规则
      • 对象优先分配在 Eden 区
      • 大对象直接进入老年代
      • 长期存活的对象将逐步进入老年代
      • 对象动态年龄判断机制
      • 老年代空间分配担保机制

JVM 内存模型概述

JVM 内存模型,也叫 JVM 运行时数据区。下面是 JVM 内存模型的图解:
在这里插入图片描述

可以看出,JVM 内存模型主要分为以下的几块:

  • 堆:线程共享,用于存放对象实例,是由垃圾收集器管理的区域,不同的垃圾收集器对于堆会有不同的布局实现
  • 方法区:线程共享,用于存储已被加载的所有类的类型信息静态变量字段信息方法信息字面量符号引用等数据
  • 程序计数器:线程私有,是当前线程所执行的字节码的行号指示器,是唯一一块不会发生 OOM 的区域
  • Native 栈:线程私有,也叫本地方法栈,当 JVM 执行 Native 方法时,存储一些必要的数据
  • JVM 栈:线程私有,也叫虚拟机栈,每个方法被执行时,JVM 都会创建一个栈帧用于存放方法的局部变量表操作数栈方法返回地址动态链接等数据

基于分代收集理论设计的垃圾收集器所管理的堆结构

堆是由垃圾收集器管理的内存区域,不同的垃圾收集器对于堆会有不同的布局实现,这里主要介绍基于分代收集理论设计的垃圾收集器所管理的堆结构。
基于分代收集理论,堆内存结构如下所示:
在这里插入图片描述

可以看出,堆内存结构主要分为:

  • Yound Gen:新生代,约占整个堆大小的 1/3
    • Eden 区:Eden 区,大约占新生代的 8/10
    • Survivor 0 区:S0 区,大约占新生代的 1/10
    • Survivor 1 区:S1 区,大约占新生代的 1/10
  • Old Gen:老年代,约占整个堆大小的 2/3

方法区的演变

方法区,在 JDK8 之前,是用永久代来实现的,在 JDK8 之后,是用元空间来实现的

内存分配

划分内存的方法

JVM 划分内存的方法有两种:

  • 指针碰撞:Bump the Pointer,当堆中的内存比较整齐,即用过的内存和空闲内存有一条清晰的分界线(分界线处有个指针作为分界点指示器)时,可以使用这种方法
    • 指针碰撞方法在分配内存时,仅仅需要将分界点指示器向空闲内存方向挪动一段距离,距离取决于所需内存大小
  • 空闲列表:Free List,当队中的内存不整齐,即用过的内存和空闲内存相互交错、没有清晰的分界线时,就不能使用指针碰撞的方式来分配内存了。JVM 会维护一个列表,记录队中每块内存的使用情况,在分配的时候从可用的内存中分配一块足够大的内存出去,并把这块内存标记为已使用

划分内存时如何解决并发问题

在实际的 JVM 运行过程中,很可能会出现多个线程同时申请内存的情况,此时如果不对划分内存操作进行并发控制操作,大概率会出现并发安全问题(多个内存分配请求被分配到了同一块内存空闲)。
针对上述情况,JVM 采取的并发控制手段有:

  • CAS:在划分内存时,采用 CAS + 自旋操作来保证同一块内存不会同时被分配给多个分配请求
  • TLABThread Local Allocation Buffer,即本地线程分配缓冲。核心思想就是把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在堆中预先分配一小块内存,这个线程后续的内存分配请求都会先在这块区域上进行,这一小块内存就称为本地线程分配缓冲。可以通过设置参数来开启或关闭此功能。

对象栈上分配

为了减少生命周期较短的对象在堆内分配的次数,JVM 会通过逃逸分析结合标量替换两个功能,把一些引用不会逃逸出方法之外的,可以使用若干个标量来替代本身的对象,将其内存分配在栈上进行。即:

  • 应用不会逃逸出方法之外,即这个对象是当前方法栈帧中创建出来的一个局部变量,其生命周期随着方法的结束而结束
  • 可以使用若干个标量来替代本身,即这个对象可以被分解成若干个不可再分的标量(如基本数据类型引用类型等)来替代

满足上述两个条件的对象,将可能会不被创建,而是直接由分解成若干个分配在栈上的标量替代,如:

class User {private int age;private String name;
}public void methodA() {User user = new User();user.age = 10;user.name = "Test";//将 user 数据插入到数据库中//由于 user 对象的引用没有传递到外部,且 user 对象本身可以被一个 int 类型和一个 reference 类型的标量替换掉//那么在开启了逃逸分析+标量替换时,将会用栈上分配的两个标量来替换掉,而不会在堆中创建这个对象......
}

注意,栈上分配必须依赖逃逸分析标量替换两个功能才能生效。

基于分代收集理论的垃圾收集器管理下的内存分配规则

基于分代收集理论的垃圾收集器,将堆根据存放对象的年龄不同划分成了不同的区域。在不同的区域内,会有不同的分配规则。

对象优先分配在 Eden 区

在大多数情况下,对象将会优先分配在 Eden 区。当 Eden 区没有足够的空间进行分配时,将会尝试进行一次 Young GC

大对象直接进入老年代

当对象的大小超过一定的阈值时,对象将会直接被分配到老年代

长期存活的对象将逐步进入老年代

Eden + S0 + S1 共同组成 Young Generation 的设计,称为 Appel 式垃圾收集机制。其主要的特点就是长期存活的对象将逐步进入老年代

  • 每个对象的对象头 Mark Word 中都会记录一个当前对象年龄的计数器
  • 在每一次经历 Young GC 后,如果对象依然存活,那么计数器将 +1
  • 在经历若干次(默认为 15 次)Young GC 还依然存活的对象,也即对象年龄大于晋升老年代年龄阈值(默认为 15)的对象,将会被移动到老年代中

对象动态年龄判断机制

在某一次 Young GC 时,如果此时 Survivor 空间中小于等于某年龄的所有对象大小的总和大于等于 Survivor 空间大小的一半,那么大于或等于该年龄的所有存活对象将直接进入到老年代中(尽管此时对象年龄可能尚未达到晋升老年代年龄阈值

老年代空间分配担保机制

Appel 式垃圾收集机制,核心思想使用的是复制算法。但是这个复制算法的备用空间(空闲的 Survivor 区)远小于主用空间(Eden 区 + 使用中的 Survivor 区),那么如果在某次 Young GC 时,存活下来的对象比备用空间大怎么办?
Appel 式垃圾收集机制给出的解决方案就是将这些所有存活下来的对象都移动到老年代中。这就是老年代空间分配担保机制的来源以及核心思想。
更细节的:

  • 在发生 Young GC 之前,JVM 必须检查当前老年代最大可用的连续空间是否大于新生代当前所有对象的总空间
    • 如果成立,那么可以安全地执行本次 Young GC
    • 如果不成立,那么 JVM 会查看当前是否开启了老年代空间分配担保机制(JDK 8 之后默认开启)
      • 如果未开启,那么将会执行一次 Full GC
      • 如果开启了,那么将会继续检查老年代最大可用的连续空间是否大于历次 Young GC 晋升到老年代的对象的平均总大小
        • 如果小于,那么将会执行一次 Full GC
        • 如果大于,那么将会有风险地执行本次 Young GC

注意,当有风险地执行 Young GC 时,如果本次 Young GC 存活下来的对象总大小大于老年代最大可用的连续空间(即出现了担保失败的情况),那么将会执行一次 Full GC

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

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

相关文章

image pil 图像保存_如何利用python中的PIL库做图像处理?

自从这个世界上出现了Python编程,一切都好像有了新的思路与进展,比如人工智能,还有我们常用的PS,你可知道Python也可以做图像处理,用的就是PIL库,还没有用过的,还没有发现的,还没有实…

link st 量产工具_ST-Link资料03_ST-Link固件升级、驱动下载安装方法

说明:本文原创作者『strongerHuang』本文首发于微信公众号『嵌入式专栏』,同时也更新在我的个人网站:EmbeddedDevelop一、写在前面前两篇文章讲述的都是关于ST-Link的一些理论知识,建议初学者看看:ST-Link资料01_ST-Li…

SSM 框架整合 spring 发送邮件功能实现!

基于SSM的 spring 发送邮件的实现 由于考虑到项目中需要,如果程序出现异常或其它问题,可以发送邮件来及时提醒后台维护人员处>理。所以目前考虑使用JavaMail来实现邮件发送!如下,是我整理的一些内容,做个笔记记录下…

Java 故障处理与性能监控工具

文章目录概述基础工具jpsjstatjinfojmapjhatjstack高级工具VisualVMVisualVM 的主要功能ArthasGC Easy概述 在使用 Java 语言进行开发的过程中,我们很可能会遇到各种程序问题。 比如,可能会遇见程序突然就静止不动了,但是程序进程依然显示在…

SSM整合框架实现发送邮件功能

SSM整合框架实现发送邮件功能 1.导入发送邮件的依赖 <!-- 发送邮件jar包--><!--spring支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.0.RELE…

ap接口 php_2018年小米高级 PHP 工程师面试题(模拟考试卷)

点击蓝字关注我们&#xff01;每天获取最新的编程小知识&#xff01;源 / php中文网 源 / www.php.cn在面试之前多看看有关公司的面试资料&#xff0c;对之后的面试会很有帮助。今天就给大家带来2018年小米高级 PHP 工程师面试题(模拟考试卷)&#xff0c;有着一定的参考价…

composer 设置版本号_Composer依赖管理 – PHP的利器

别再到处搜PHP类扩展包了&#xff0c;对于现代语言而言&#xff0c;包管理器基本上是标配。Java 有 Maven&#xff0c;Python 有 pip&#xff0c;Ruby 有 gem&#xff0c;Nodejs 有 npm。PHP 的则是 PEAR&#xff0c;不过 PEAR 坑不少&#xff1a;依赖处理容易出问题配置非常复…

SpringBoot2.5.4发送邮件4种方式

一.准备 在创建SpringBoot项目 二、选择依赖 选择依赖时 发现其选择依赖时有邮件发送与Springboot整合的jar包&#xff0c;我们勾选即可 如果未勾选也不要紧&#xff0c;咱们手动导入 <dependency><groupId>org.projectlombok</groupId><artifactId…

手游传奇刷元宝_传奇手游 平民制霸刀刀爆元宝!

新轩辕神途手游游戏介绍新轩辕神途是一款玩法种类十分丰富多样的神途手游&#xff0c;游戏内拥有放置挂机升级玩法&#xff0c;玩家不用浪费时间工作上学都能自动升级打宝&#xff0c;更有十分庞大的世界地图等你来探索&#xff0c;十分靠谱&#xff0c;更受欢迎&#xff0c;爆…

MySQL 逻辑架构与常用的存储引擎

文章目录概述逻辑架构示意图Server 层功能模块连接器查询缓存分析器优化器执行器存储引擎层InnoDBInnoDB 主要特性InnoDB 引擎下的查询过程MyISAMMyISAM 的主要特性MyISAM 引擎下的查询过程InnoDB 和 MyISAM 的对比概述 MySQL 是我们平时开发中最常用的关系型数据库&#xff0…

java 阿里云接口实现发送短信验证码

1.先去阿里云开通短信服务&#xff1a; 2.添加模板及签名&#xff1a;需要审核&#xff0c;个人账户审核就几分钟就OK 先解释一下模板及签名&#xff1a; 标准参照&#xff1a;https://help.aliyun.com/document_detail/55324.html?spm5176.sms-sign.0.0.765c1cbeNhvWBZ 去…

MySQL 索引底层数据结构实现

文章目录概述讨论范围查询数据结构查询数据结构种类及其高性能查询原理MySQL 索引的底层数据结构MySQL 索引的需求分析选择 MySQL 索引的底层数据结构B- 树和 B 树的对比MySQL 索引的底层数据结构揭秘概述 MySQL 的索引是存储引擎用于快速找到记录的一种数据结构&#xff0c;是…

Java面试——SpringMVC系列总结

文章目录&#xff1a; 1.什么是Spring MVC&#xff1f; 2.Spring MVC的主要组件有哪些&#xff1f; 3.请描述一下Spring MVC的工作流程&#xff1f; 4.MVC是什么&#xff1f;MVC设计模式的好处有哪些 5.拦截器Interceptor与过滤器Filter有什么区别&#xff1f; 6.Spring …

中蒙俄经济走廊背景_上海外国语大学师生代表团参观访问G60科创走廊俄罗斯院士创新基地...

10月23日&#xff0c;上海外国语大学团委书记、创新创业与实践教育学院执行院长廖文其、俄罗斯东欧中亚学院党总支副书记郝佳、辅导员石朝天及学生代表等一行15人参观访问G60科创走廊俄罗斯院士创新基地(下简称&#xff1a;创新基地)。创新基地主任赵磊、俄罗斯中小企业联合会华…

MySQL 索引类别与索引使用指南

文章目录概述MySQL 索引类型MySQL 索引方法BTREE 方法HASH 方法主键构成的索引结构主键索引的优点主键索引的缺点依赖顺序插入更新代价高索引使用指南索引树回顾索引树排序规则最左前缀法则最左前缀法则的产生依据最左前缀法则延申字段书写顺序不影响最左前缀法则最左前缀法则总…

测试员不可不知的几款bug管理工具

根据每个公司性质的不同&#xff0c;规模的不同&#xff0c;所用到的bug管理工具也可能不同。你们用的bug管理工具是什么呢&#xff1f;下面介绍几款主流的bug管理工具&#xff1a; 1. JIRA&#xff08;付费&#xff09; JIRA的生产者把JIRA定义为Professional Issue Tracker&…

Bugzilla 使用指南

本篇文章主要关注于如何高效合理的使用Bugzilla。 Bugzilla是一个开源的缺陷跟踪系统&#xff0c;它可以管理软件开发过程中缺陷的提交、修复、关闭等整个生命周期。 1. 基本概念 在Bugzilla中&#xff0c;Bug报告状态分为以下几种状态&#xff0c; 待确认的 unconfirmed 新…

MySQL explain 命令

概述 MySQL 的 explain 命令&#xff0c;主要用于查看实际查询过程中的一些执行细节&#xff08;执行计划&#xff09;&#xff0c;也是查看优化器决定如何执行查询的主要方法 explain 使用示例 explain 的使用也很简单&#xff0c;在 select 语句之前增加 explain 关键字再…

centos6.5安装bugzilla超详细教程

经过自己的摸索&#xff0c;与尝试&#xff0c;成功在centos6.5上&#xff0c;安装bugzilla。并且可以发送邮件。 一、安装软件 首先&#xff0c;需要安装一些软件 yum install mysql-devel -y yum install mysql-server -y yum install httpd -y yum install gcc gcc-…

从numpy里加载_PyTorch强化:01.PyTorch 数据加载和处理

PyTorch提供了许多工具来简化和希望数据加载&#xff0c;使代码更具可读性。1.下载安装包scikit-image&#xff1a;用于图像的IO和变换pandas&#xff1a;用于更容易地进行csv解析from __future__ import print_function, divisionimport osimport torchimport pandas as pd #用…