对象创建

  • 类加载过后可以直接确定一个对象的大小
  • 对象栈上分配是通过逃逸分析判定、标量替换实现的,即把不存在逃逸的对象拆散,将成员变量恢复到基本类型,直接在栈上创建若干个成员变量
  • 选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理 功能决定。因此,在使用Serial、ParNew等带Compact过程的收集器时,系统采用的分配算法是指针碰撞,而使用 CMS这种基于Mark-Sweep算法的收集器时,通常采用空闲列表
  • 空间并发分配解决方案
    • TLAB,线程私有空间分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定
    • CAS+失败重试保证更新操作的原子性

对象内存布局

内存布局

  • Klass Word(类指针):存储对象的类型指针,该指针指向它的类元数据。从JDK 1.6 update14开始,64位的JVM正式支持了-XX:+UseCompressedOops(默认开启),可以压缩指针,起到节约内存占用的作用。oop(ordinary object pointer)即普通对象指针,下列指针将压缩至32位:

    • 每个Class的属性指针(静态成员变量)
    • 每个对象的属性指针(对象变量)
    • 普通对象数组的每个元素指针
  • 指针压缩:

    • 如果GC堆大小在4G以下,直接砍掉高32位,避免了编码解码过程(偏移量除以/乘以8)
    • 如果GC堆大小在4G以上32G以下,则启用-XX:+UseCompressedOops命令
    • 如果GC堆大小大于32G,压指失效,使用原来的64位
  • -XX:+UseCompressedClassPointers

    • Java8使用Metaspace存储元数据,开启后类元信息中的指针也用32bit的Compressed版本,即Klass Word
    • 依赖-XX:+UseCompressedOops
  • 数组长度64位JVM的情况下也被压缩至32位

  • 对齐字节:HotSpot VM的自动内存管理要求对象大小必须是8字节的整数倍,不足时需要对齐填充来补全

对象头

  • 32位虚拟机占用32个字节,不同状态下各个比特位区间大小有变化

  • biased_lock:偏向锁标记,为1时表示对象启用偏向锁

  • age:默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。由于age只有4位,所以最大值为15

  • identity_hashcode

    • 采用延迟加载技术,只有在需要时使用System.identityHashCode(Object x)计算后写到该对象头中
    • 偏向锁没有存储HashCode的地方,偏向锁期间调用System.identityHashCode(x)会造成锁升级
    • 轻量级锁和重量级锁所指向的lock record或monitor都有存储HashCode的空间
    • 用户自定义hashCode()方法所返回的值不存在Mark Word中,只针对identity hash code
  • thread:持有偏向锁的线程ID

  • epoch:偏向锁的时间戳

  • ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针

  • ptr_to_heavyweight_monitor:重量级锁状态下,指向对象监视器Monitor的指针

ClassLayout

// 引入依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.11</version>
</dependency> // 查看对象布局信息
ClassLayout layout = ClassLayout.parseInstance(new A());
System.out.println(layout.toPrintable());

可通过ClassLayout查看对象布局信息,即对象占用空间情况

对象访问定位

句柄访问对象 直接指针访问对象
  • 句柄访问:java堆中会划分一块内存作为句柄池,线程栈中引用中存储的就是对象句柄地址。好处在于对象句柄地址固定,对象移动(垃圾回收时移动对象非常普遍)时仅改变句柄中的实例数据指针
  • 直接指针访问:线程栈中引用中存储的直接就是对象地址,好处在于速度更快(Sun HotSpot使用此种)

JVM之对象创建、对象内存布局、对象访问定位的更多相关文章

  1. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

  2. Java对象的创建、内存布局和访问定位

    在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...

  3. JVM 专题十二:运行时数据区(七)对象的实例化内存布局与访问定位

    1. 对象的实例化 1.1 创建对象的方式 new 最常见的方式 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 Class的newInstance() ...

  4. JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位

    对象的实例化 创建对象的方式 1.new:最常见的方式(本质是构造器) 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 2.Class的newInsta ...

  5. 【深入理解JVM】:Java对象的创建、内存布局、访问定位

    对象的创建 一个简单的创建对象语句Clazz instance = new Clazz();包含的主要过程包括了类加载检查.对象分配内存.并发处理.内存空间初始化.对象设置.执行ini方法等. 主要流 ...

  6. 深入理解java虚拟机(二)HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  7. HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  8. java面试-对象的创建、内存布局、访问定位

    一.对象的创建 1.虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过.如果没有,那必须先执行相应的 ...

  9. 深入理解Java虚拟机(二)、Java对象的创建,内存布局和访问定位

    对象的创建: Object obj = new Object(); 常量池中是否有Ljava.lang.Object

  10. 【JVM之内存与垃圾回收篇】对象实例化内存布局与访问定位

    对象实例化内存布局与访问定位 从各自具体的内存分配上来讲 new 的对象放在堆中 对象所属的类型信息是放在方法区的 方法当中的局部变量放在栈空间 这 new 的对象怎么把三块粘合到一起 就是这章的内容 ...

随机推荐

  1. 网络流学习-Ford-Fulkerson

    首先我们先解决最大流问题 什么是最大流问题呢 根据我的理解,有一个源点s,汇点t,s可以通过一个网络(雾)流向汇点t 但是每一条边都有他的最大传输容量限制,那么我们的任务是,如何分配流量使得..从s流 ...

  2. STM32 单片机的USART的奇偶校验 误区(坑)

    当STM32的串口配置成带有奇偶校验位的情况下,需要软件校验是否发生奇偶校验错误,硬件只是置起奇偶校验错误标志位,并将错误的数据放到DR寄存器中,同时置起RXEN标志位,如果使能中断还是会正常进入中断 ...

  3. 图片转tfrecords

    import numpy as np import tensorflow as tf import time import os import cv2 from sklearn.utils impor ...

  4. angular-2-tutorial-2017

    # angular-2-tutorial-2017https://www.sitepoint.com/understanding-component-architecture-angular/http ...

  5. Flutter: 显示&关闭系统叠加层ui

    import 'package:flutter/services.dart'; /// 关闭 SystemChrome.setEnabledSystemUIOverlays([]); /// 显示 S ...

  6. JavaScript数据类型判断的四种方法

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14416375.html 本文分享了JavaScript类型判断的四种方法:typeo ...

  7. MYSQL 悲观锁和乐观锁简单介绍及实现

    1:悲观锁 1.1 特点: 每次查询都会进行锁行,怕"其他人"进行数据的修改. 1.2 实现步骤: 步骤1:开启事务test1,并对id=2的记录进行查询,并加锁,如:   步骤2 ...

  8. Static Proxy

    0.静态代理 静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护代理对象.通过构造器塞入目标对象,赋值给代理对象,进而执行代理对象实现的接口方法,并实现前拦截,后拦截等所需的业务 ...

  9. Python3.x 基础练习题100例(21-30)

    练习21: 题目: 猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前 一天剩下的一半零一个.到第10天早上 ...

  10. [译]我是如何将GTA在线模式的加载时间缩短70%的

    [译]我是如何将GTA在线模式的加载时间缩短70%的 译注: 最近在网上发现了一篇有意思的文章, 一个国外大神受不了GTA5在线模式的加载时间, 一怒之下反汇编了GTA5的源码, 并最终发现了问题的原 ...