JVM的栈、堆

什么是栈

  • 栈又叫堆栈,是先入后出的数据结构
  • 栈是线程私有的,不能互相访问的,栈随着线程的创建而创建,并且在编译时就已确定了栈的大小
  • 栈通过栈帧保存了局部变量、对象的内存引用地址、操作栈、动态链接等等

栈帧

  栈帧就是栈中的最小单位,第一个方法的调用就会生成栈帧,并将其压如栈中,就是压栈。
  第一个方法中又调用了第二个方法,则会生成第二个方法的栈帧,并压栈,当方法执行完或跑出异常时,会进行出栈的操作,并返回值给方法一的栈。

栈溢出的场景

  • 递归死循环
    递归死循环导致无尽的方法调用,栈帧最终压破了栈的最大值,故而导致了栈溢出

一个对象的大小

一个对象包含了三个主要的内容:对象头、实例数据(成员变量信息)、对齐补充

对象头

(1)普通对象分为两个部分:Mark Word 和 元数据指针(指向对象的class类型)
(2)数组对象分为三个部分:Mark Word、元数据指针和数组长度

Mark Word

(1)GC分代年龄;(2)哈希吗;(3)锁信息(个人理解,线程上锁之后,对象头的锁信息指向线程的栈信息)等

实例数据

(1)基本数据类型(参考基本数据类型大小);(2)引用数据类型(4个字节);

对齐补充

对齐补充是为了保证整个对象大小为8个字节的倍数,当整个对象头+实例对象的大小不是8字节倍数时,对齐补充来进行保证。

对象头的大小

Mark Word在不同位数的系统中,大小不同
PS:64位开启指针压缩为-XX:UseCompressedOops,并且jdk1.8后默认开启

系统 Mark Word(字节) 元数据指针 (字节) 数组长度(字节) 对象头总计(对象/数组)
32位 4 4 4 8/12
64位 8 8 4 16/20
64位开启指针压缩 8 4 4 12/16

查看对象大小的工具

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.15</version>
</dependency>

(1)对象的内部信息:ClassLayout.parseInstance(obj).toPrintable()
(2)对象的外部信息,包括引用的对象:GraphLayout.parseInstance(obj).toPrintable()
(3)对象占用的总空间:GraphLayout.parseInstance(obj).totalSize()

posted on 2021-04-29 09:50  lyjlyjlyj  阅读(151)  评论(0编辑  收藏  举报

导航