java虚拟机(第二版) 第二章总结 (二)

版权声明: https://blog.csdn.net/ttt_12345/article/details/82981655

本文总结下java虚拟机的第二章的第三小节

1、(原文2.3)HotSpot虚拟机对象探秘

文中以HotSpot虚拟机为例,讲述了java对象的创建以及访问。

当我们写的new关键字被虚拟机执行时:

 <1>、检查new所对应的参数是否能在常量池中定位到一个类的符号引用;

<2>、检查这个符号引用代表的类是否已被加载、 解析和初始化过; 

<3>、如果没有, 那必须先执行相应的类加载过程(书中第7章);

<4>、上述步骤执行结束后,则为新生对象分配内存,有两种方式

      <1、指针碰撞:指堆内存为规整的,可以简单的分为已被占用的和未被占用的两块,中间以一个指针作为分隔,为新对象分配内存只是将指针向未被占用的内存空间移动下而已;

      <2、空闲列表:指堆内存并非规整的,虚拟机维护着一个未使用内存块的列表,当新建对象时,从列表中查找一个可以容下新对象的内存即可;

选择哪种分配方式由使用哪种垃圾收集器决定,Serial、 ParNew等带Compact(标记-整理算法)过程的收集器时, 系统采用的分配算法是指针碰撞,

CMS,基于Mark-Sweep算法(标记-清除算法)的收集器时, 通常采用空闲列表。

注:关于各个垃圾收集器所采用的算法概述如下,后续会详细总结

    Serial:复制算法(新生代)

    Serial Old:标记-整理算法(老年代)

    ParNew:(Serial的多线程版本)复制算法(新生代)

    Parallel Scavenge:(“吞吐量优先”收集器)复制算法(新生代)

    Parallel Old:(Parallel Scavenge的老年代版本)标记-整理算法 (老年          代)

CMS和G1后续会详细总结。

继续对象的创建内容总结...

<5>、解决对象创建在多线程情况下的线程安全问题的两种方案:

    <1、CAS配上失败重试的方式保证更新操作的原子性;

    <2、把内存分配的动作按照线程划分在不同的空间之中进行, 即每个线程在Java堆中预先分配一小块内存, 称为本地线程分配缓冲( Thread Local Allocation Buffer,TLAB) 。 哪个线程要分配内存, 就在哪个线程的TLAB上分配, 只有TLAB用完并分配新的TLAB时, 才需要同步锁定;

    虚拟机通过-XX: +/-UseTLAB参数设定使用TLAB。

<6>、初始化默认值;

<7>、对对象进行必要的设置, 例如这个对象是哪个类的实例、 如何才能找到类的元数据信息、 对象的哈希码、 对象的GC分代年龄等信息;

2、(原文2.3.2)在HotSpot虚拟机中, 对象在内存中的布局分为3块区域: 对象头( Header) 、实例数据( Instance Data) 和对齐填充( Padding) 。此部分都是些硬知识,且不常见,故暂时未总结,感兴趣的读者可以阅读原书。

3、(原文2.3.3) 对象的访问定位

主流的访问方式有使用句柄和直接指针两种


 <1>使用句柄:此种情况Java堆中会分出一块内存作为句柄池, 引用中存储的就是对象的句柄地址, 而句柄中包含了对象实例数据与类型数据各自的具体地址信息,好处是句柄地址稳定,频繁的垃圾收集下只改实例数据指针,而引用本身不变。

<2>直接指针:看图我就不说话了

好处是速度更快, 节省了一次指针定位的时间开销,且因对象访问在Java中超级频繁, 所以会节省一大笔时间;

HotSpot是使用直接指针来访问对象的

本节完。

本文暂时总结了java虚拟机(第二版)中的2.3节的主要知识点,和一些up主自己的知识点,如果有记忆差错,还望见谅,后面我会找时间继续的,最后,我总结的知识点比较简练,如果需要了解详细内容的话,请阅读原书。也欢迎大家关注我的公众号号 “up随想”,关注后或许会收到up主的小福利哦!!

猜你喜欢

转载自blog.csdn.net/ttt_12345/article/details/82981655
今日推荐