`

JAVA之JDK在64位系统默认开启压缩指针分析

    博客分类:
  • Java
 
阅读更多
from: http://www.blogjava.net/cangshi004/archive/2012/03/02/371120.html

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

#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-8u231-linux-x64.tar.gz.zip

    Java Development Kit(JDK)是开发和运行Java应用程序的基础,而`jdk-8u231-linux-x64.tar.gz.zip`是一个针对Linux 64位系统的Java 8更新231版本的压缩包。Java 8自发布以来,由于其稳定性和广泛的功能支持,至今...

    JDK9GC-cheatsheet.pdf

    JDK9 GC调优是Java开发中至关重要的一个环节,涉及到JVM(Java虚拟机)的性能优化。在这个版本中,HotSpot JVM提供了多种垃圾回收(GC)算法,每种算法都有其特定的适用场景和参数调整策略。下面将详细讨论JDK9中的...

    JDK10GC-cheatsheet.pdf

    JDK10的垃圾收集(GC)调优是Java开发者关注的重要领域,因为GC性能直接影响应用的稳定性和响应速度。本篇文章将详细解读JDK10中的GC参数及其作用。 首先,我们关注到Application Class Data Sharing(CDS)功能。...

    java高级工程师面试总结

    ### Java高级工程师面试总结 #### Java基础 - **Hashtable和HashMap的区别**: - `Hashtable`是线程安全的,而`HashMap`不是。这意味着在多线程环境中使用`Hashtable`时无需额外的同步措施,但这也使得其性能较低...

    打造极速MyEclipse+由MyEclipse内存不足谈谈JVM内存

    - 如果系统资源允许,可以开启JVM的压缩指针选项`-XX:+UseCompressedOops`,在64位系统中减少内存开销。 4. **监控与调优** 持续监控JVM的内存使用,观察是否有频繁的Full GC或长时间的暂停。根据监控结果,逐步...

    JVM 参数汇总.pdf

    25. **-XX:+UseCompressedOops** 和 **-XX:+UseCompressedClassPointers**: 在64位系统中,这些参数用于压缩对象引用和类对象指针,以减少内存占用和垃圾收集开销。 这些参数的调整需要根据应用程序的具体需求和...

    kafka_2.9.2-0.8.2.1.tgz

    Kafka默认开启JVM压缩指针,但只是在64位的HotSpot VM受支持,如果安装了32位的HotSpot VM,需要修改/bin/kafka-run-class.sh文件 KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseCompressedOops -XX:+UseParNewGC...

    JVM调优攻略.pdf

    - **类型指针**:指向对象的类元数据指针,默认情况下8字节,在JDK1.8之后,默认开启指针压缩,此时大小变为4字节。 - **实例数据**:存储对象的实际数据。 - **对齐填充**:为了性能考虑,确保对象占用的内存是8...

    2021-2022计算机二级等级考试试题及答案No.16478.docx

    22. **JDK工具**:Java Development Kit(JDK)包含了Java编译器(javac)、Java运行工具(java)、Java文档生成工具(javadoc)以及打包工具(jar)等,这些都是Java开发的标准工具。 23. **公式自动填充**:在...

Global site tag (gtag.js) - Google Analytics