JDK从6update23开始在64位系统上会默认开启压缩指针

如题。先前都没仔细留意,今天在看一个crash log的时候才发现这点,记录一下。

成都创新互联从2013年创立,先为古县等服务建站,古县等地企业,进行企业商务咨询服务。为古县企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。

本来以为这个是在6 update 25才开始开启的…

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  

HotSpot 17:

C++代码

 
 
 
  1. #ifndef ZERO   
  2. #ifdef _LP64   
  3.   // Check that UseCompressedOops can be set with the max heap size allocated   
  4.   // by ergonomics.   
  5.   if (MaxHeapSize <= max_heap_for_compressed_oops()) {   
  6. #ifndef COMPILER1   
  7.     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {   
  8.       // Disable Compressed Oops by default. Uncomment next line to enable it.   
  9.       // FLAG_SET_ERGO(bool, UseCompressedOops, true);   
  10.     }   
  11.   }   
  12. #endif   
  13.   // ...   
  14. #endif // _LP64   
  15. #endif // !ZERO  

HotSpot 19 / HotSpot 20:

C++代码

 
 
 
  1. #ifndef ZERO   
  2. #ifdef _LP64   
  3.   // Check that UseCompressedOops can be set with the max heap size allocated   
  4.   // by ergonomics.   
  5.   if (MaxHeapSize <= max_heap_for_compressed_oops()) {   
  6. #ifndef COMPILER1   
  7.     if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {   
  8.       FLAG_SET_ERGO(bool, UseCompressedOops, true);   
  9.     }   
  10. #endif   
  11.   }   
  12.   // ...   
  13. #endif // _LP64   
  14. #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++代码

 
 
 
  1. void set_object_alignment() {   
  2.   // Object alignment.   
  3.   assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");   
  4.   MinObjAlignmentInBytes     = ObjectAlignmentInBytes;   
  5.   assert(MinObjAlignmentInBytes >= HeapWordsPerLong * HeapWordSize, "ObjectAlignmentInBytes value is too small");   
  6.   MinObjAlignment            = MinObjAlignmentInBytes / HeapWordSize;   
  7.   assert(MinObjAlignmentInBytes == MinObjAlignment * HeapWordSize, "ObjectAlignmentInBytes value is incorrect");   
  8.   MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;   
  9.   
  10.   LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);   
  11.   LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;   
  12.   
  13.   // Oop encoding heap max   
  14.   OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;   
  15. }   
  16.   
  17. inline uintx max_heap_for_compressed_oops() {   
  18.   // Avoid sign flip.   
  19.   if (OopEncodingHeapMax < MaxPermSize + os::vm_page_size()) {   
  20.     return 0;   
  21.   }   
  22.   LP64_ONLY(return OopEncodingHeapMax - MaxPermSize - os::vm_page_size());   
  23.   NOT_LP64(ShouldNotReachHere(); return 0);   
  24. }  

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

 
 
 
  1. 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从6update23开始在64位系统上会默认开启压缩指针
浏览地址:http://www.36103.cn/qtweb/news49/9499.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联