JVM—对象的创建流程与内存分配

创建流程

对象创建的流程图如下:

对象的内存分配方式

内存分配的方式有两种:

  • 指针碰撞(Bump the Pointer)
  • 空闲列表(Free List)
分配方式 说明 收集器
指针碰撞(Bump the Pointer) 内存地址是连续的(新生代) Serial和ParNew收集器
空闲列表(Free List) 内存地址不连续(老年代) CMS收集器和Mark-Sweep收集器

指针碰撞

指针碰撞示意图如下:

内存分配安全问题:

虚拟机给A线程分配内存的过程中,指针未修改,此时B线程同时使用了该内存,就会出现问题。

解决方式:

  • CAS乐观锁:JVM虚拟机采用CAS失败重试的方式保证更新操作的原子性;
  • TLAB (Thread Local Allocation Buffer)本地线程分配缓存,预分配。

分配主流程

首先从TLAB里面分配,如果分配不到,再使用CAS从堆里面划分。

对象如何进入老年代

对象进入老年代流程如下:

  • 新对象大多数默认都进入Eden;

  • 对象进入老年代的四种情况:

    • 年龄太大 MinorGC15次-XX:MaxTenuringThreshold】;

    • 动态年龄判断:MinorGC后会动态判断年龄,将符合要求对象移入老年代;

      MinorGC之后,发现Survivor区中的一批对象的总大小大于了这块Survivor区的50%,那么就会将此时大于等于这批对象年龄最大值的所有对象,直接进入老年代。

      例子: Survivor区中有一批对象,年龄分别为年龄1+年龄2+年龄n的多个对象,对象总和大小超过了Survivor区域的50%,此时就会把年龄n及以上的对象都放入老年代。希望那些可能是长期存活的对象,尽早进入老年代。
      比率可以由-XX:TargetsurvivorRatio指定
    • 大对象直接进入老年代1M【-XX:PretenureSizeThreshold 】;(前提是Serial和ParNew收集器)

      为了避免大对象分配内存时的复制操作降低效率。

      避免了Eden和Survivor区的复制。

    • MinorGC后存活对象太多无法放入Survivor。

空间担保机制

空间担保机制:当新生代无法分配内存的时候,我们想把新生代的老对象转移到老年代,然后把新对象放入腾空的新生代。此种机制我们称之为内存担保。

空间担保流程图如下:

对象内存布局

对象内存布局示意图如下:

对象里的三个区

堆内存中,一个对象在内存中存储的布局可以分为三块区域:

堆内存中,一个对象在内存中存储的布局可以分为三块区域:

  • 对象头(Header) : Java对象头占8byte。如果是数组则占12byte。因为JVM里数组size需要使用4byte存储。

    • 标记字段MarkWord:

      • 用于存储对象自身的运行时数据,它是synchronized实现轻量级锁和偏向锁的关键。

      • 默认存储:对象HashCode、GC分代年龄、锁状态等等信息。

      • 为了节省空间,也会随着锁标志位的变化,存储数据发生变化。

    • 类型指针KlassPoint:

      • 是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
      • 开启指针压缩存储空间4byte,不开启8byte。
      • JDK1.6+默认开启
    • 数组长度:如果对象是数组,则记录数组长度,占4个byte,如果对象不是数组则不存在。

    • 对齐填充:保证数组的大小永远是8byte的整数倍。

  • 实例数据(Instance Data):生成对象的时候,对象的非静态成员变量也会存入堆空间

  • 对齐填充(Padding) :JVM内对象都采用8byte对齐,不够8byte的会自动补齐。

如何访问一个对象

有两种方式:

  1. 句柄:稳定,对象被移动只要修改句柄中的地址

  2. 直接指针:访问速度快,节省了一次指针定位的开销

JVM—对象的创建流程与内存分配的更多相关文章

  1. Java中对象创建时的内存分配

    一.前言知识铺垫   1.逃逸对象:在一个方法内创建的对象没有被外界引用则称该对象为未逃逸的对象. 2.JDK1.6以后的HotSpot虚拟机支持运行时的对象逃逸分析. 3.JVM中的参数配置: 1) ...

  2. spring中容器和对象的创建流程

    容器和对象的创建流程 1.先创建容器 2.加载配置文件,封装成BeanDefinition 3.调用执行BeanFactoryPostProcessor 准备工作: 准备BeanPostProcess ...

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

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

  4. 【JVM.2】垃圾收集器与内存分配策略

    垃圾收集器需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 在前一节中介绍了java内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈 ...

  5. 【Java杂货铺】JVM#Java高墙之GC与内存分配策略

    Java与C++之间有一堵由内存动态分配和垃圾回收技术所围成的"高墙",墙外的人想进去,墙外的人想出来.--<深入理解Java虚拟机> 前言 上一章看了高墙的一半,接下 ...

  6. TObject简要说明-对象的创建流程

    TObject = class    //创建    constructor Create;    //释放    procedure Free;    //初始化实列    class functi ...

  7. JVM优化之垃圾收集器以及内存分配

    在jvm中,实现了多种垃圾收集器,包括:串行垃圾收集器.并行垃圾收集器.CMS(并发)垃圾收集器.G1垃圾收集器,接下来,我们一个个的了解学习. 串行垃圾收集器 串行垃圾收集器,是指使用单线程进行垃圾 ...

  8. JVM学习十 -(复习)内存分配与回收策略

    内存分配与回收策略 对象的内存分配,就是在堆上分配(也可能经过 JIT 编译后被拆散为标量类型并间接在栈上分配),对象主要分配在新生代的 Eden 区上,少数情况下可能直接分配在老年代,分配规则不固定 ...

  9. JVM读书笔记之垃圾收集与内存分配

    1 概述 说起垃圾收集( Garbage Collection , GC ) ,大部分人都把这项技术当做 Java 语言的伴生产物.事实上, GC 的历史远远比 Java 久远,1960 年诞生于 M ...

  10. Java对象(创建过程、内存布局、访问方法)

    (Java 普通对象.不包括数组.Class 对象等.) ​ 对象创建过程 类加载 遇到 new 指令时,获取对应的符号引用,并检查该符号引用代表的类是否已被初始化.如果没有就进行类加载. 分配内存 ...

随机推荐

  1. 硬件开发笔记(五): 硬件开发基本流程,制作一个USB转RS232的模块(四):创建CON连接器件封装并关联原理图元器件

    前言   有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的.为了更好的表述封装设计过程,本文描述了一个创建CON标准连接件封装,创建 ...

  2. 擅长使用iter

    def populate_ranks(votes, ranks): names = list(votes.keys()) names.sort(key=votes.get, reverse=True) ...

  3. 1.Go 的基本数据类型

    Go 的基本数据类型

  4. 【Azure Cache for Redis】Redis的导出页面无法配置Storage SAS时通过az cli来完成

    问题描述 在Azure Redis的导出页面,突然不能配置Storage Account的SAS作为授权方式. 那么是否可以通过AZ CLI或者是Powershell来实现SAS的配置呢? 问题解答 ...

  5. 【Azure 云服务】查看Azure云服务在中国区域的VM型号大小列表(型号编码,定价层,以及CPU, Memory等)

    问题描述 如何查看创建 Azure Cloud Service 服务时,可以选择的VM型号吗? 问题解答 根据官网参考,可以通过PowerShell脚本 Get-AzComputeResourceSk ...

  6. 连接微信群、Slack 和 GitHub:社区开放沟通的基础设施搭建

    NebulaGraph 社区如何构建工具让 Slack.WeChat 中宝贵的群聊讨论同步到公共领域. 要开放,不要封闭 在开源社区中,开放的一个重要意义是社区内的沟通.讨论应该是透明.包容并且方便所 ...

  7. spark 下java list 或者scala list 转DataFrame or DataSet 总结

    一.JAVA list 转 DataFrame or DataSet case class CaseJava( var num: String, var id: String, var start_t ...

  8. nginx设置访问账号密码

    第一:为kibana加上了用户登陆访问 第二:不暴露服务器上5601端口,只开放80端口即可.这对服务器的安全也是一个很大的保护. 接下来我们就开始配置nginx与kibana. 一.配置nginx ...

  9. 前端css阴影画图

    在线演示地址:css阴影画图 一,在css中有一个box-shadow属性,可以设置元素的阴影. .item{ width: 50px; height: 50px; background: #0096 ...

  10. 虚拟机和开发板之间通过NFS互联

    简介 NFS是Network File System的首字母缩写.它是一种分布式协议,使客户端可以访问远程服务器上的共享文件.它允许网络中的计算机之间通过TCP/IP网络共享资源. 配置过程 安装NF ...