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(推薦閱讀)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM