溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JDK默認(rèn)開啟壓縮指針問(wèn)題怎么解決

發(fā)布時(shí)間:2022-03-31 14:28:22 來(lái)源:億速云 閱讀:165 作者:iii 欄目:編程語(yǔ)言

本篇內(nèi)容介紹了“JDK默認(rèn)開啟壓縮指針問(wèn)題怎么解決”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Sun的HotSpot VM從JDK5開始會(huì)根據(jù)運(yùn)行環(huán)境來(lái)自動(dòng)設(shè)定VM的一些參數(shù)(ergonomics)。其中大家最熟悉的可能是它會(huì)自動(dòng)選擇client與server模式、堆的初始和***大小等。事實(shí)上ergonomics會(huì)設(shè)置非常多的內(nèi)部參數(shù),包括自動(dòng)選擇GC算法、并行GC的線程數(shù)、GC的工作區(qū)分塊大小、對(duì)象晉升閾值等等。

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

于是我們可以留意一下幾個(gè)版本的HotSpot對(duì)UseCompressedOops參數(shù)的處理的差異:

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的版本號(hào)與JDK的版本號(hào)之間的關(guān)系,請(qǐng)參考另一篇筆記:Sun/Oracle JDK、OpenJDK、HotSpot VM版本之間的對(duì)應(yīng)關(guān)系)

可以看到,UseCompressedOops參數(shù)從HotSpot 19開始終于開始受ergonomics控制,會(huì)在下述條件滿足的時(shí)候默認(rèn)開啟:

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

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

3、沒(méi)有通過(guò).hotspotrc或命令行參數(shù)手動(dòng)設(shè)定過(guò)UseCompressedOops參數(shù)的值;

4、沒(méi)有使用Garbage-First (G1) GC。

第1、3、4點(diǎn)都很直觀,于是第2點(diǎn)就是個(gè)關(guān)鍵點(diǎn)了:閾值是多大?

還是看回代碼,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上默認(rèn)為8;

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

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

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

跟蹤一下里面幾個(gè)參數(shù)的計(jì)算,在64位HotSpot上有,

C++代碼

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

于是,前面提到的第2個(gè)條件在64位HotSpot VM上默認(rèn)是:

C++代碼

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

os::vm_page_size()是操作系統(tǒng)的虛擬內(nèi)存的分頁(yè)大小,在Linux上等于sysconf(_SC_PAGESIZE)的值;在x86_64上的Linux默認(rèn)分頁(yè)大小為4KB。

MaxHeapSize的值基本上等于-Xmx參數(shù)設(shè)置的值(會(huì)根據(jù)分頁(yè)大小、對(duì)齊等因素做調(diào)整)。

MaxPermSize就是perm gen設(shè)置的***大小。

這下可以確認(rèn),在我現(xiàn)在用的環(huán)境里,當(dāng)包括perm gen在內(nèi)的GC堆大小在32GB - 4KB以下的時(shí)候,使用64位的JDK 6 update 23或更高版本就會(huì)自動(dòng)開啟UseCompressedOops功能。

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

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jdk
AI