JVM内存分配及申请过程

当使用new关键字或者其他任何方式进行创建一个类的对象时,JVM虚拟机需要为该对象分配内存空间,而对象的大小在类加载完成后已经确定了,所以分配内存只需要在Java堆中划分出一块大小相等的内存,JVM虚拟机中有指针碰撞和空闲列表两种方式分配内存。

指针碰撞方式

如果Java堆中内存是规整排列的,所有被用过的内存放一边,空闲的可用内存放一边,中间放置一个指针作为它们的分界点,在需要为新生对象分配内存的时候,只要将指针向空闲内存那边挪动一段与对象大小相等的距离即可分配。

代表GC回收器

ParNew,Serial,G1

空闲列表方式

如果Java堆中内存不是规整排列的,用过的内存和可用内存是相互交错的,这种情况下将不能使用指针碰撞方式分配内存,Java虚拟机需要维护一个列表用于记录哪些内存是可用的,在为新生对象分配内存的时候,在列表中寻找一块足够大的内存分配,并更新列表上的记录。

代表GC回收器

cms

Java虚拟机选择策略

Java虚拟机采用哪种方式为新生对象分配内存,取决于所使用的垃圾收集器,当垃圾收集器具有整理过程时,虚拟机将采用指针碰撞的方式;当垃圾收集器的回收过程没有整理过程时,则采用空闲列表方式。

现在虚拟机栈进行分配

此部分属于两部分的分配机制,当JVM创建线程Thread对象:

  1. 直接分配:局部变量、形式参数表。

  2. 优化分配:逃逸分析(栈上分配、标量替换等功能)。

如果完成分配之后,则结束内存分配,否则出现分配失败,或者无法进行分配操作后,会进入堆内存方式的分配。

新生区-Eden区的分配

TLAB内存的分配策略

上面刚刚说过了,主要有两种内存分配机制:如果采用指针碰撞法,则会出现性能问题和指针分配冲突的问题.,JVM虚拟机采用优化的手段,就是TLAB(ThreadLocal Allocation Buffer)预先分配了内存块。

总体内存分配流程策略

如果TLAB内存分配失败或者空间不足,则JVM会试图为相关Java对象在Eden中初始化一块内存区域,当Eden空间足够时,内存申请结束

当如果出现了Eden区内存无法进行分配,则会发生相关MinorGC(JVM试图释放在Eden中所有不活跃的对象(Minor GC),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区)。

此时Survivor区被用来作为Eden及old的中间交换区域,如果Survivor不足以放置eden区的对象 ,会进行担保分配,或者已经达到直接晋升到老年代的条件后,此时如果old区有空闲,Survivor区的对象会被移到Old区。

当old区空间不够时,JVM会在old区进行major collection;

完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";

  1. jvm优先分配在eden区
  2. 当Eden空间足够时,内存申请结束。

JVM锁的膨胀执行流程机制

无锁节点/偏向锁阶段

创建线程的时候在程序执行到同步代码块的时候,首先会基于上面说到的内存分配策略进行分配内存,此时会当当前线程获取到了相关锁资源的时候,因为属于无锁状态下转换为偏向锁:

无锁标记头

偏向锁标记头

  1. 会将相关的当前线程的线程ID赋值到相关的标记字段中。
  2. 为了提高性能以及栈空间可以获取相关的竞争数据,会将对象头的标记字段(Markword)拷贝到栈空间内部(Lock Record)锁记录。

轻量级锁阶段

竞争到锁的线程

与此同时,当另外一个线程同时也去竞争该资源的时候,需要进行竞争,因为在获取资源的时候,底层采用CAS机制取获取相关的资源标志,一旦获取成功,便可以通过偏向锁标识进行判断是否属于当前的锁owner线程。

当发现不属于偏向锁的线程进来竞争的时候,此时会产生竞争关系,因为同一时刻,只能允许一个线程获取资源,当前获取资源的线程会因为有其他线程也争抢过该资源,故此将java对象头中的锁字段改为00,如下图所示:

未竞争到锁的线程

当发生线程争抢CAS机制失败的时候,会进行相关的自旋机制,进行尝试下一次进行争抢到锁。


重量级锁阶段

未竞争到锁的线程
  1. 当超过自旋的线程一直处于自旋,且超过了自旋阈值之后,变会升级成为了重量级锁。

    或

  2. 当更多的线程都处于争抢状态且属于自旋锁机制之后(出现了大量的轻量级锁之后),便会升级未重量级锁。

  3. 直到被唤醒重新镜像竞争锁资源信息。

升级为重量级锁的结果会将线程的标志位置为10

此时不会在进行自旋CAS争抢 ,而是直接阻塞执行(采用底层mutex/Fast Mutex锁进行暂停中断线程的执行)。

竞争到锁的线程
  • 当锁标记因为发生变化,成为了重量级锁,所以,线程会同步自己的所记录,发现不一致,同步为重量级锁状态后,释放锁之后,进行唤醒阻塞的状态的线程。

  • 锁的状态暂时处于重量级锁状态。接下来会专门写一篇文章讲解一下锁降级哦,锁降级会较为复杂,而且场景完全不一样,对JVM要求也不一样。

当对象出现消亡了回收状态:

🏆【JVM技术专区】「难点-核心-遗漏」TLAB内存分配+锁的碰撞(技术串烧)!的更多相关文章

  1. ☕【Java技术指南】「难点-核心-遗漏」Java线程状态流转及生命周期的技术指南(知识点串烧)!

    前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理,配合这相关官方文档的中英文互译的介绍. 线程状态流转及生命周期 当线程被创建并启动以后,它既 ...

  2. JVM基础学习(二):内存分配策略与垃圾收集技术

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来 垃圾收集概述 Java内存模型中的堆和方法区是垃圾收集技术所需要关注的终点,因为其他的区域会跟 ...

  3. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  4. 【Java技术专题】「性能优化系列」针对Java对象压缩及序列化技术的探索之路

    序列化和反序列化 序列化就是指把对象转换为字节码: 对象传递和保存时,保证对象的完整性和可传递性.把对象转换为有字节码,以便在网络上传输或保存在本地文件中: 反序列化就是指把字节码恢复为对象: 根据字 ...

  5. C++_类和动态内存分配6-复习各种技术及队列模拟

    知识点: 队列:是一种抽象的数据类型(Abstract Data Type),可以存储有序的项目序列. 新项目被添加在队尾,并可以删除队首的项目.队列有些像栈.栈是在同一端进行添加和删除.这使得栈是一 ...

  6. LIbreOJ #6011. 「网络流 24 题」运输问题 最小费用最大流

    #6011. 「网络流 24 题」运输问题 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  7. loj #547. 「LibreOJ β Round #7」匹配字符串

    #547. 「LibreOJ β Round #7」匹配字符串   题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...

  8. 一夜搞懂 | JVM GC&内存分配

    前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习GC&内存分配? 时代发展到现在,如今的内存动态分配与内存回收技术已经相当成 ...

  9. jvm系列 (二) ---垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...

随机推荐

  1. 【字符串+排序】宇宙总统 luogu-1781

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 分析 给字符串排个序. AC代码 #include & ...

  2. Querydsl与SpringBoot集成

    Querydsl为大多数数据库提供了一种基于Java的类型安全,类SQL的查询方式.相比JPA,Querydsl能提供更加强大的查询方式,比如关联查询.相比MyBatis,Querydsl省去了XML ...

  3. Thinkphp中取消url中的index.php 和 Home 默认模块

    将配置文件中改: <?phpreturn array(    //'配置项'=>'配置值'    'URL_MODEL'=>'2',   //去掉url中index.php    ' ...

  4. vi正则表达式

    搜索命令:/正则表达式 替换命令::s/正则表达式/替换字符串/选项 :%s/str1/str2/g   该命令中:表示进入命令行模式,%表示对该文件所有行有效,s表示查找并替换,正则表达式str1表 ...

  5. 大数据学习(08)—— Hive简介

    前面的Hadoop学习是非常体系化的,有主线有细节.到了Hive这里,知识点非常零散,感觉没有什么主线能把它串起来.从官方网站上就能看出这点差异. 什么是Hive Hive是一个基于Hadoop的企业 ...

  6. .NET Conf 2020大会将于2020年11月10日--- 11月12日举行 (UTC)时区

    .NET Conf 2020大会将于2020年11月10日--- 11月12日举行 (UTC)时区 开始时间 2020年11月10日 08:00 (PT) | 16:00 (UTC)| 24:00(北 ...

  7. SQL Server截取字符串(经纬度)

    DECLARE @var VARCHAR(50) SET @var ='116.404556|39.915156' 方式一: SELECT CASE WHEN ISNULL(@var,'') < ...

  8. javaScript学习DOM模型

    DOM 全称是 Document Object Model 文档对象模型大白话,就是把文档中的标签,属性,文本,转换成为对象来管理                                   ...

  9. DVWA靶场之XSS(Stored)通关

    Low: <?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage ...

  10. python初始化定义空变量-小记

    python初始化定义空变量 数值 digital_value = 0 字符串 str_value = "" 列表 list_value = [] 字典 ditc_value = ...