《深入理解java虚拟机》第二章笔记

1. 运行时数据区域

名称是否共享作用存在的异常
程序计数器线程私有如果执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址
java虚拟机栈线程私有每个方法在执行的同时会创建一个栈帧(局部变量表,操作数栈等),方法的调用过程,对应一个栈帧在虚拟机栈中的出入栈StackOverflowError,OutofMemoryError
本地方法栈线程私有作用与虚拟机栈类似,但是它是为Native方法服务的StackOverflowError,OutofMemoryError
java堆线程共享所有的对象实例以及数组都要在堆上分配,随着技术的发展,现在变得不是那么绝对了,垃圾回收比较多OutofMemoryError
方法区线程共享用于存储已被虚拟机加载的类信息,常量,静态变量等。垃圾回收在此比较少OutofMemoryError
运行时常量池线程共享属于方法区,用于存放编译期生成的 各种字面量和符号引用OutofMemoryError

2. 对象探究

2.1 对象的创建
  1. 类加载检查:

    • 遇到new指令时,检查这个指令的参数是否能在常量池中定位到一个类的符号引用。
    • 检查这个符号引用代表的类是否已被加载,解析和初始化过.

      1. 分配内存:等同于把一块确定大小的内存从java堆中划分出来
    • 指针碰撞:假设java堆中的内存是绝对规整的,所有用过的内存放在一边,空闲的内存放在另一边,那么就可以用一个指针向空闲空间挪动一段与对象大小相等的距离。
    • 空闲列表:假设内存是不规整的,那虚拟机就会维护一个列表,记录哪些内存块是可用的,然后去找一块足够大的划分给对象实例,并更新列表记录。

    ps:还要考虑并发问题,有两种解决方案

    1. CAS来保证更新操作原子性
    2. 把内存分配按照线程划分到不同的空间之中,也就是给每一个线程预先分配TLAB(本地线程分配缓存),只有TLAB用完,才会同步锁定

    3. 初始化为零值

    4. 进行必要设置

    比如这个对象是哪个类的实例,对象的哈希码等,还有是否启用偏向锁等,主要是对对象头进行设置

2.2对象的内存布局

2.2.1 对象头
  1. 第一部分用于存储对象自身的运行时数据

    如哈希码,GC分代年龄,锁状态标识等

  2. 第二部分是类型指针

    用来确定这个对象是哪个类的实例,如果对象是数组的话,还得有一块用于记录数组长度的数据。

2.2.2 实例数据
  • 存储的是有效信息,也就是所定义的各种类型的字段内容。
  • 这部分的存储顺序会受 虚拟机分配策略参数,字段在Java源码中的定义顺序的影响
2.2.3 对齐填充

这部分没什么含义的,主要起着占位符的作用,比如对象的大小必须是8字节的整数倍,当对象实例数据部分没有对齐时,就要通过它来填充

2.3对象的访问定位

主流的访问方式有 使用句柄 和直接指针 这两种
1. 使用句柄
- java 堆划分出一块内存空间来作为句柄池,reference中存的就是对象的 句柄地址
这里写图片描述

最大的好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改句柄中的实例数据指针,而reference本身不需要修改

2. 直接指针
reference中存的就是对象地址
image
最大的好处是速度更快,节省了一次指针定位的时间开销。

本书讨论的虚拟机是sun hotspot,它用的是直接指针方式

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值