溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JDK默認開啟壓縮指針問題怎么解決

發布時間:2022-03-31 14:28:22 來源:億速云 閱讀:216 作者:iii 欄目:編程語言

本篇內容介紹了“JDK默認開啟壓縮指針問題怎么解決”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

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++代碼

#ifdef _LP64       // Check that UseCompressedOops can be set with the max heap size allocated       // by ergonomics.       if (MaxHeapSize <= max_heap_for_compressed_oops()) {         if (FLAG_IS_DEFAULT(UseCompressedOops)) {           // Turn off until bug is fixed.           // the following line to return it to default status.           // FLAG_SET_ERGO(bool, UseCompressedOops, true);         }         // ...       }     #endif // _LP64

HotSpot 17:

C++代碼

#ifndef ZERO     #ifdef _LP64       // Check that UseCompressedOops can be set with the max heap size allocated       // by ergonomics.       if (MaxHeapSize <= max_heap_for_compressed_oops()) {     #ifndef COMPILER1         if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {           // Disable Compressed Oops by default. Uncomment next line to enable it.           // FLAG_SET_ERGO(bool, UseCompressedOops, true);         }       }     #endif       // ...     #endif // _LP64     #endif // !ZERO

HotSpot 19 / HotSpot 20:

C++代碼

#ifndef ZERO     #ifdef _LP64       // Check that UseCompressedOops can be set with the max heap size allocated       // by ergonomics.       if (MaxHeapSize <= max_heap_for_compressed_oops()) {     #ifndef COMPILER1         if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {           FLAG_SET_ERGO(bool, UseCompressedOops, true);         }     #endif       }       // ...     #endif // _LP64     #endif // !ZERO

(注: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++代碼

void set_object_alignment() {       // Object alignment.       assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");       MinObjAlignmentInBytes     = ObjectAlignmentInBytes;       assert(MinObjAlignmentInBytes >= HeapWordsPerLong * HeapWordSize, "ObjectAlignmentInBytes value is too small");       MinObjAlignment            = MinObjAlignmentInBytes / HeapWordSize;       assert(MinObjAlignmentInBytes == MinObjAlignment * HeapWordSize, "ObjectAlignmentInBytes value is incorrect");       MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;           LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);       LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;           // Oop encoding heap max       OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;     }         inline uintx max_heap_for_compressed_oops() {       // Avoid sign flip.       if (OopEncodingHeapMax < MaxPermSize + os::vm_page_size()) {         return 0;       }       LP64_ONLY(return OopEncodingHeapMax - MaxPermSize - os::vm_page_size());       NOT_LP64(ShouldNotReachHere(); return 0);     }

(注:其中 (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++代碼

ObjectAlignmentInBytes = 8     MinObjAlignmentInBytes = 8     HeapWordSize = 8     MinObjAlignment = 1     MinObjAlignmentInBytesMask = 0x0111     LogMinObjAlignmentInBytes = 3     LogHeapWordSize = 3 // _LP64     LogMinObjAlignment = 0     OopEncodingHeapMax = 0x800000000 // 32GB

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

C++代碼

MaxHeapSize + MaxPermSize + os::vm_page_size() <= 32GB

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功能。

“JDK默認開啟壓縮指針問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jdk
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女