理解JVM工作机制(三)对象的内存布局

存储布局

在HostSpot虚拟机中,对象在堆内存中的存储布局可用划分为三个部分

  • 对象头(Header)
  • 实例数据(Instance Data)
  • 对齐填充(Padding)

在这里插入图片描述

各部分存储的数据
对象头

第一部分,存储对象自身的运行时数据

  • HashCode
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  • 偏向锁ID
  • 偏向时间戳

这部分的数据的长度在32位和64位的虚拟机中(未开启压缩指针)分别为32bit和64bit,称为Mark Word

第二部分,类型指针

即对象指向它的类型元数据的指针,用来确定该对象属于哪个类的实例

如果对象是一个数组,那在对象头中还必须有一块用于记录数组长度的数据

实例数据

存储各种类型的字段内容,包括父类继承和子类定义的字段。

分配策略

-xx:FieldAllocationStyle

默认顺序:longs、doubles、ints、shorts/chars/bytes/booleans、oops

对齐填充

HotSpot虚拟机的自动内存管理要求对象的起始地址都必须是8字节的整数倍。对象头已经被设计成8字节的整数倍了(1倍或者2倍)。因此,如果实例数据没有对齐的话,就需要这对其填充来补全。

通过栈中的reference来访问对象,一种通过句柄访问,另外一种则是直接直接访问

在这里插入图片描述

Java堆溢出

Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么随着对象数量的增加,总容量触及最大堆的容量限制后就会产生内存溢出异常。

VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

关于虚拟机栈和本地方法栈,在《Java虚拟机规范》中描述了两种异常:
1)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
2)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。

《Java虚拟机规范》明确允许Java虚拟机实现自行选择是否支持栈的动态扩展,而HotSpot虚拟机的选择是不支持扩展,所以除非在创建线程申请内存时就因无法获得足够内存而出现OutOfMemoryError异常,否则在线程运行时是不会因为扩展而导致内存溢出的,只会因为栈容量无法容纳新的栈帧而导致StackOverflowError异常。

-Xss1024k 栈内存设置

在 Java 8 里面不存在永久代了,取而代之的是元空间。

补充一下:方法区只是一个概念,永久代或者元空间是它的实现
方法区里面的那些东西,大部分都被移到堆里面去了,还剩下一些元数据被保存在元空间里面

元空间简介

元空间是保存元数据的地方

元数据:描述数据的数据
例如一部电影,导演:—、主演:—、投资方:—,这些信息中的导演、主演、投资方就叫元数据,他们加一起描述了整部电影的详细数据
那么在元空间里面保存的就是类的元数据,如方法、字段、类、包的描述信息,这些信息可以用于创建文档、跟踪代码中的依赖性、执行编译时检查

元空间存在的意义

在方法区里面,由于方法区大小是启动时就设置好的,可以用默认的也可以手动指定: -XX:MaxPermSize ,但是他始终还是有限定大小的(触发永久代 OOM 后该大小会动态调整),也就是说会发生 OOM

此外永久代的 GC 特别难搞,严重影响 Full GC 的性能。于是抛弃永久代,使用元空间,从而解决这些问题

元空间如何提高性能

永久代里面的常量池都移到堆里面,只保存元数据,从而让 Full GC 不再关心方法区
元空间使用直接内存,理论上系统内存有多大,元空间就可以有多大,不存在 OOM
元空间有单独的元空间虚拟机执行内存分配与垃圾回收
元空间工作流程
虽然元空间在本地内存中,但是还是可以通过:-XX:MetaspaceSize 来控制它的初始大小,达到该值就会触发垃圾收集进行类型卸载

同时 GC 时会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过 MaxMetaspaceSize 时,适当提高该值。

类加载器存储的位置就是元空间,每一个类加载器的存储区域都称作一个元空间,所有的元空间合在一起就是我们一直说的元空间。当一个类加载器被垃圾回收器标记为不再存活,其对应的元空间会被回收。

元空间的内存分配

由元空间虚拟机负责,采用的形式为:组块分配。

元空间虚拟机维护着一个全局的空闲组块列表,当一个类加载器需要元空间内存的时候就从这里面找一块,用完后再释放。类加载器维护的这个组块又分为多个小块,每一块存储一个单元的元信息,分配方式为指针碰撞法。

存在的问题:由于元空间的内存分配值组块方式的,所以存在内存碎片问题(目前不支持压缩)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值