zoukankan      html  css  js  c++  java
  • JVM(七)压缩指针

    类型指针

    一般对象指针(oop, ordinary object pointer)是HotSpot虚拟机的一个术语,表示受托管的对象指针。它的大小通常和本地指针是一样的。Java应用程序和GC子系统会非常小心地跟踪这些受托管的指针,以便在销毁对象时回收内存空间,或是在对空间进行整理时移动(复制)对象。

    为什么要压缩指针

    类型指针是对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说查找对象的元数据信息并不一定要经过对象本身。 以前的是32位,也就说内存的寻址空间最大可以达到2的32次方的地址,2的32次方表示的地址空间是4G ,但是现在很多内存大小都超过了4G , 在64位的java虚拟机中,类型指针占了64位,位数的增加虽然可以寻址到更大的空间,但是实际上我们并没有使用那么大的空间了,并且位数增加了意味这占用更大的内存,也是就说64位的类型指针位数太多了。 也就是我只要能表示该地址就行了。于是就出现了如下

    1297993-20200319175256054-1341880593.jpg

    oops 最后的三位始终为零。这样可想而知,有些地址不能表示了,因为它的尾3位都是0,所以需要对齐。

    什么情况下会进行压缩?

    下面表述摘自 http://shzhangji.com/cnblogs/2015/06/25/compressed-oops-in-the-hotspot-jvm/ 如果UseCompressedOops是打开的,则以下对象的指针会被压缩:

    • 所有对象的klass属性
    • 所有对象指针实例的属性
    • 所有对象指针数组的元素(objArray) HotSpot VM中,用于表示Java类的数据结构是不会压缩的,这部分数据都存放在永久代(PermGen)中。

    在解释器中,一般对象指针也是不压缩的,包括JVM本地变量和栈内元素、调用参数、返回值等。解释器会在读取堆内对象时解码对象指针,并在存入时进行编码。

    同样,方法调用序列(method calling sequence),无论是解释执行还是编译执行,都不会使用对象指针压缩。

    在编译后的代码中,对象指针是否压缩取决于不同的优化结果。优化后的代码可能会将压缩后的对象指针直接从一处搬往另一处,而不进行编解码操作。如果芯片(如x86)支持解码,那在使用对象指针时就不需要自行解码了。

    所以,以下数据结构在编译后的代码中既可以是压缩后的对象指针,也可能是本地地址:

    • 寄存器或溢出槽(spill slot)中的数据
    • 对象指针映射表(GC映射表)
    • 调试信息
    • 嵌套在机器码中的对象指针(在非RISC芯片中支持,如x86)
    • nmethod常量区(包括那些影响到机器码的重定位操作)

    补充

    使用 jol 来查看对象头的信息

    增加依赖

            <dependency>
                <groupId>org.openjdk.jol</groupId>
                <artifactId>jol-core</artifactId>
                <version>0.10</version>
            </dependency>
    
            Object object = new Object();
            String info = ClassLayout.parseClass(Object.class).toPrintable(object);
            System.out.println("info : " + info);
    
    
            结果 : 
    
             java.lang.Object object internals:
     OFFSET  SIZE   TYPE DESCRIPTION                               VALUE
          0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
          4     4        (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
          8     4        (object header)                           e5 c1 f2 27 (11100101 11000001 11110010 00100111) (670220773)
         12     4        (loss due to the next object alignment)
    Instance size: 16 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
    
    

    参考资料

    • http://shzhangji.com/cnblogs/2015/06/25/compressed-oops-in-the-hotspot-jvm/(推荐阅读)
    • https://docs.oracle.com/cd/E19620-01/805-3024/lp64-1/index.html(32和64位下C语言数据结构位数的表示)
    • https://wiki.openjdk.java.net/display/HotSpot/CompressedOops(推荐阅读)
  • 相关阅读:
    Javascript的this用法
    angularjs学习笔记--1.入门
    git的简单应用
    转:Netty服务器线程模型概览
    Netty 4.0 中文文档
    转:腾讯CKV海量分布式存储系统
    转Redis性能测试
    maven assemby 打包问题
    转发:TCP
    转:HBase Server启动过程
  • 原文地址:https://www.cnblogs.com/Benjious/p/12526108.html
Copyright © 2011-2022 走看看