温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

JDK默认开启压缩指针问题怎么解决

发布时间:2022-03-31 14:28:22 来源:亿速云 阅读:175 作者: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