倉藍

          日記本

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            23 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks
             JAVA之JDK在64位系統默認開啟壓縮指針分析(請多多指正!)
                Sun的HotSpot VM從JDK5開始會根據運行環境來自動設定VM的一些參數(ergonomics)。其中大家最熟悉的可能是它會自動選擇client與server模式、堆的初始和最大大小等。事實上ergonomics會設置非常多的內部參數,包括自動選擇GC算法、并行GC的線程數、GC的工作區分塊大小、對象晉升閾值等等。

            Ergonomics相關的邏輯大都在hotspot/src/share/vm/runtime/arguments.cpp中,值得留意的是使用了FLAG_SET_ERGO()的地方。

            于是我們可以留意一下幾個版本的HotSpot對UseCompressedOops參數的處理的差異:

            HotSpot 16:

            C++代碼

        1. #ifdef _LP64     
        2.   // Check that UseCompressedOops can be set with 
          the max heap size allocated   
           
        3.   // by ergonomics.     
        4.   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
        5.     if (FLAG_IS_DEFAULT(UseCompressedOops)) {     
        6.       // Turn off until bug is fixed.     
        7.       // the following line to return it to default status.     
        8.       // FLAG_SET_ERGO(bool, UseCompressedOops, true);     
        9.     }     
        10.     // ...     
        11.   }     
        12. #endif // _LP64
        13.   HotSpot 17:

            C++代碼

        14. #ifndef ZERO     
        15. #ifdef _LP64     
        16.   // Check that UseCompressedOops can be set with 
          the max heap size allocated   
           
        17.   // by ergonomics.     
        18.   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
        19. #ifndef COMPILER1     
        20.     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {     
        21.       // Disable Compressed Oops by default. Uncomment 
          next line to enable it.   
           
        22.       // FLAG_SET_ERGO(bool, UseCompressedOops, true);     
        23.     }     
        24.   }     
        25. #endif     
        26.   // ...     
        27. #endif // _LP64     
        28. #endif // !ZERO    
        29.   HotSpot 19 / HotSpot 20:

            C++代碼

        30. #ifndef ZERO     
        31. #ifdef _LP64     
        32.   // Check that UseCompressedOops can be set with 
          the max heap size allocated   
           
        33.   // by ergonomics.     
        34.   if (MaxHeapSize <= max_heap_for_compressed_oops()) {     
        35. #ifndef COMPILER1     
        36.     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {     
        37.       FLAG_SET_ERGO(bool, UseCompressedOops, true);     
        38.     }     
        39. #endif     
        40.   }     
        41.   // ...     
        42. #endif // _LP64     
        43. #endif // !ZERO
        44.   (注:HotSpot VM的版本號與JDK的版本號之間的關系,請參考另一篇筆記:Sun/Oracle JDK、OpenJDK、HotSpot VM版本之間的對應關系)

            可以看到,UseCompressedOops參數從HotSpot 19開始終于開始受ergonomics控制,會在下述條件滿足的時候默認開啟管道磁力泵

            1、是64位系統(#ifdef _LP64)并且不是client VM(#ifndef COMPILER1);

            2、Java堆的最大大小不大于一個閾值(MaxHeapSize <= max_heap_for_compressed_oops());

            3、沒有通過。hotspotrc或命令行參數手動設定過UseCompressedOops參數的值;

            4、沒有使用Garbage-First (G1) GC.


          第1、3、4點都很直觀,于是第2點就是個關鍵點了:閾值是多大?

            還是看回代碼,HotSpot 20:

            C++代碼

        45. void set_object_alignment() {     
        46.   // Object alignment.     
        47.   assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");     
        48.   MinObjAlignmentInBytes     = ObjectAlignmentInBytes;     
        49.   assert(MinObjAlignmentInBytes >= HeapWordsPerLong * HeapWordSize, 
          "ObjectAlignmentInBytes value is too small");     
        50.   MinObjAlignment         = MinObjAlignmentInBytes / HeapWordSize;     
        51.   assert(MinObjAlignmentInBytes == MinObjAlignment * HeapWordSize, 
          "ObjectAlignmentInBytes value is incorrect");     
        52.   MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;     
        53.     
        54.   LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);     
        55.   LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;     
        56.     
        57.   // Oop encoding heap max     
        58.   OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;     
        59. }     
        60.     
        61. inline uintx max_heap_for_compressed_oops() {     
        62.   // Avoid sign flip.     
        63.   if (OopEncodingHeapMax < MaxPermSize + os::vm_page_size()) {     
        64.     return 0;     
        65.   }     
        66.   LP64_ONLY(return OopEncodingHeapMax - MaxPermSize - os::vm_page_size());     
        67.   NOT_LP64(ShouldNotReachHere(); return 0);     
        68. }
        69.   (注:其中 (uint64_t(max_juint) + 1) 的值也被稱為NarrowOopHeapMax,也就是2的32次方,0x100000000;

            ObjectAlignmentInBytes在64位HotSpot上默認為8;

            HeapWord在globalDefinitions.hpp里定義,大小跟一個char*一樣;

            HeapWordSize在同一個文件里定義,等于sizeof(HeapWord),在64位系統上值為8;

            LogHeapWordSize也在同一文件里,在64位系統上定義為3)

            跟蹤一下里面幾個參數的計算,在64位HotSpot上有,

            C++代碼

          1. ObjectAlignmentInBytes = 8     
          2. MinObjAlignmentInBytes = 8     
          3. HeapWordSize = 8     
          4. MinObjAlignment = 1     
          5. MinObjAlignmentInBytesMask = 0x0111     
          6. LogMinObjAlignmentInBytes = 3     
          7. LogHeapWordSize = 3 // _LP64     
          8. LogMinObjAlignment = 0     
          9. OopEncodingHeapMax = 0x800000000 // 32GB    

            于是,前面提到的第2個條件在64位HotSpot VM上默認是:

            C++代碼

        70. MaxHeapSize + MaxPermSize + os::vm_page_size() <= 32GB
        71.   os::vm_page_size()是操作系統的虛擬內存的分頁大小,在Linux上等于sysconf(_SC_PAGESIZE)的值;在x86_64上的Linux默認分頁大小為4KB.

            MaxHeapSize的值基本上等于-Xmx參數設置的值(會根據分頁大小、對齊等因素做調整)。

            MaxPermSize就是perm gen設置的最大大小。

            這下可以確認,在我現在用的環境里,當包括perm gen在內的GC堆大小在32GB - 4KB以下的時候,使用64位的JDK 6 update 23或更高版本就會自動開啟UseCompressedOops功能


          posted on 2012-03-02 11:07 cangshi 閱讀(2250) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 德惠市| 德令哈市| 莱芜市| 曲沃县| 新田县| 府谷县| 镇远县| 永仁县| 杭锦旗| 白河县| 云南省| 大关县| 崇义县| 禹州市| 伊川县| 达尔| 天水市| 黄浦区| 赤峰市| 四川省| 章丘市| 灵寿县| 亳州市| 甘孜县| 逊克县| 东源县| 武乡县| 广丰县| 北京市| 焉耆| 从江县| 麦盖提县| 东丰县| 廊坊市| 和静县| 剑川县| 东阿县| 扎鲁特旗| 辛集市| 昭平县| 南开区|