- 浏览: 3009180 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
如题。先前都没仔细留意,今天在看一个crash log的时候才发现这点,记录一下。
本来以为这个是在6 update 25才开始开启的…
注意:32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。64位HotSpot VM的版本字符串样子如下:
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:
HotSpot 17:
HotSpot 19 / HotSpot 20:
(注: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。
(更新:G1 GC的限制在7017008: G1: Turn on compressed oops by default.已经解除了,于HS21 checkin,也就是说JDK7开始就没有这个限制了。)
第1、3、4点都很直观,于是第2点就是个关键点了:阈值是多大?
还是看回代码,HotSpot 20:
(注:其中 (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上有,
于是,前面提到的第2个条件在64位HotSpot VM上默认是:
os::vm_page_size()是操作系统的虚拟内存的分页大小,在Linux上等于sysconf(_SC_PAGESIZE)的值;在x86_64上的Linux默认分页大小为4KB。
MaxHeapSize的值基本上等于-Xmx参数设置的值(会根据分页大小、对齐等因素做调整)。
MaxPermSize就是perm gen设置的最大大小。
注意:通过显式设置-XX:ObjectAlignmentInBytes参数到大于8的值,UseCompressedOops的应用范围可以增加。例如说-XX:ObjectAlignmentInBytes=16能让压缩指针在64GB或以下的GC heap上开启。
这值的计算也曾经RP过:
Oracle的HotSpot VM参数文档里其实也有说UseCompressedOops的使用说明:
本文只是从源码层确认了该参数自动开启的条件。
这下可以确认,在我现在用的环境里,当包括perm gen在内的GC堆大小在32GB - 4KB以下的时候,使用64位的JDK 6 update 23或更高版本就会自动开启UseCompressedOops功能。
另外也记了一个gist来看默认情况下JDK6是否开启压缩指针:https://gist.github.com/rednaxelafx/1333043
在VM启动的时候,可以给 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode 参数来确认压缩指针的工作模式。
例子请看:https://gist.github.com/rednaxelafx/998125
HotSpot VM现在只使用3种模式的压缩指针:
1、当整个GC堆所预留的虚拟地址范围的最高的地址在4GB以下的时候,使用"zero based Compressed Oops, 32-bits Oops"模式,也就是基地址为0、shift也为0;
2、当GC堆的最高地址超过了4GB,但在32GB以下的时候,使用"zero based Compressed Oops"模式,也就是基地址为0、shift为 LogMinObjAlignmentInBytes (默认为3)的模式;
3、当GC堆的最高地址超过了32GB,但整个GC堆的大小仍然在32GB以下的时候,使用非零基地址、shift为 LogMinObjAlignmentInBytes (默认为3)的模式。
如果上面三种情况都无法满足,那压缩指针就无法使用了。
上述三种模式的名字在Universe类里有声明:
hotspot/src/share/vm/memory/universe.hpp
可见,HotSpot VM并不尝试尽量减小shift的数值,而是使用固定数值(与对象对齐相关)或者不做shift。
这点上IBM J9 VM则采取了不同的策略,总是会尝试使用最小的shift值。
==========================================
在64位HotSpot上,不开压缩指针的时候对象头的结构是:
开启压缩指针时:
==========================================
顺带记几个链接:
HotSpot早期的compressed oops的代码提交
本来以为这个是在6 update 25才开始开启的…
注意:32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。64位HotSpot VM的版本字符串样子如下:
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)
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:
#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:
#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:
#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。
(更新:G1 GC的限制在7017008: G1: Turn on compressed oops by default.已经解除了,于HS21 checkin,也就是说JDK7开始就没有这个限制了。)
第1、3、4点都很直观,于是第2点就是个关键点了:阈值是多大?
还是看回代码,HotSpot 20:
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上有,
ObjectAlignmentInBytes = 8 MinObjAlignmentInBytes = 8 HeapWordSize = 8 MinObjAlignment = 1 MinObjAlignmentInBytesMask = 0x0111 LogMinObjAlignmentInBytes = 3 LogHeapWordSize = 3 // _LP64 LogMinObjAlignment = 0 OopEncodingHeapMax = 0x800000000 // 32GB
于是,前面提到的第2个条件在64位HotSpot VM上默认是:
MaxHeapSize + MaxPermSize + os::vm_page_size() <= 32GB
os::vm_page_size()是操作系统的虚拟内存的分页大小,在Linux上等于sysconf(_SC_PAGESIZE)的值;在x86_64上的Linux默认分页大小为4KB。
MaxHeapSize的值基本上等于-Xmx参数设置的值(会根据分页大小、对齐等因素做调整)。
MaxPermSize就是perm gen设置的最大大小。
注意:通过显式设置-XX:ObjectAlignmentInBytes参数到大于8的值,UseCompressedOops的应用范围可以增加。例如说-XX:ObjectAlignmentInBytes=16能让压缩指针在64GB或以下的GC heap上开启。
这值的计算也曾经RP过:
引用
Changeset: b7268662a986
Author: coleenp
Date: 2008-04-29 19:31 -0400
URL: http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/b7268662a986
6689523: max heap calculation for compressed oops is off by MaxPermSize
Summary: Need to subtract MaxPermSize from the total heap size when determining whether compressed oops is turned on.
Author: coleenp
Date: 2008-04-29 19:31 -0400
URL: http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/b7268662a986
6689523: max heap calculation for compressed oops is off by MaxPermSize
Summary: Need to subtract MaxPermSize from the total heap size when determining whether compressed oops is turned on.
Oracle的HotSpot VM参数文档里其实也有说UseCompressedOops的使用说明:
引用
-XX:+UseCompressedOops
Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.
Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.
本文只是从源码层确认了该参数自动开启的条件。
这下可以确认,在我现在用的环境里,当包括perm gen在内的GC堆大小在32GB - 4KB以下的时候,使用64位的JDK 6 update 23或更高版本就会自动开启UseCompressedOops功能。
另外也记了一个gist来看默认情况下JDK6是否开启压缩指针:https://gist.github.com/rednaxelafx/1333043
在VM启动的时候,可以给 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode 参数来确认压缩指针的工作模式。
例子请看:https://gist.github.com/rednaxelafx/998125
HotSpot VM现在只使用3种模式的压缩指针:
1、当整个GC堆所预留的虚拟地址范围的最高的地址在4GB以下的时候,使用"zero based Compressed Oops, 32-bits Oops"模式,也就是基地址为0、shift也为0;
2、当GC堆的最高地址超过了4GB,但在32GB以下的时候,使用"zero based Compressed Oops"模式,也就是基地址为0、shift为 LogMinObjAlignmentInBytes (默认为3)的模式;
3、当GC堆的最高地址超过了32GB,但整个GC堆的大小仍然在32GB以下的时候,使用非零基地址、shift为 LogMinObjAlignmentInBytes (默认为3)的模式。
如果上面三种情况都无法满足,那压缩指针就无法使用了。
上述三种模式的名字在Universe类里有声明:
hotspot/src/share/vm/memory/universe.hpp
// Narrow Oop encoding mode: // 0 - Use 32-bits oops without encoding when // NarrowOopHeapBaseMin + heap_size < 4Gb // 1 - Use zero based compressed oops with encoding when // NarrowOopHeapBaseMin + heap_size < 32Gb // 2 - Use compressed oops with heap base + encoding. enum NARROW_OOP_MODE { UnscaledNarrowOop = 0, ZeroBasedNarrowOop = 1, HeapBasedNarrowOop = 2 };
可见,HotSpot VM并不尝试尽量减小shift的数值,而是使用固定数值(与对象对齐相关)或者不做shift。
这点上IBM J9 VM则采取了不同的策略,总是会尝试使用最小的shift值。
==========================================
在64位HotSpot上,不开压缩指针的时候对象头的结构是:
+0: [ _mark (8 bytes) ] +8: [ _klass (8 bytes) ] +16: ...
开启压缩指针时:
+0: [ _mark (8 bytes) ] +8: [ _narrow_klass (4 bytes) ] +12: [ padding or first field (4 bytes) ] +16: ...
==========================================
顺带记几个链接:
HotSpot早期的compressed oops的代码提交
引用
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
引用
6689060: Escape Analysis does not work with Compressed Oops
Summary: 64-bits VM crashes with -XX:+AggresiveOpts (Escape Analysis + Compressed Oops)
Reviewed-by: never, sgoldman
Summary: 64-bits VM crashes with -XX:+AggresiveOpts (Escape Analysis + Compressed Oops)
Reviewed-by: never, sgoldman
引用
6711701: disable compressed oops by default
发表评论
-
The Prehistory of Java, HotSpot and Train
2014-06-02 08:18 0http://cs.gmu.edu/cne/itcore/vi ... -
MSJVM and Sun 1.0.x/1.1.x
2014-05-20 18:50 0当年的survey paper: http://www.sym ... -
Sun JDK1.4.2_28有TieredCompilation
2014-05-12 08:48 0原来以前Sun的JDK 1.4.2 update 28就已经有 ... -
IBM JVM notes (2014 ver)
2014-05-11 07:16 0Sovereign JIT http://publib.bou ... -
class data sharing by Apple
2014-03-28 05:17 0class data sharing is implement ... -
HotSpot Server VM与Server Class Machine
2014-02-18 13:21 0HotSpot VM历来有Client VM与Server V ... -
Java 8的lambda表达式在OpenJDK8中的实现
2014-02-04 12:08 0三月份JDK8就要发布首发了,现在JDK8 release c ... -
GC stack map与deopt stack map的异同
2014-01-08 09:56 0两者之间不并存在包含关系。它们有交集,但也各自有特别的地方。 ... -
HotSpot Server Compiler与data-flow analysis
2014-01-07 17:41 0http://en.wikipedia.org/wiki/Da ... -
基于LLVM实现VM的JIT的一些痛点
2014-01-07 17:25 0同事Philip Reames Sanjoy Das http ... -
tailcall notes
2013-12-27 07:42 0http://blogs.msdn.com/b/clrcode ... -
《自制编程语言》的一些笔记
2013-11-24 00:20 0http://kmaebashi.com/programmer ... -
字符串的一般封装方式的内存布局 (1): 元数据与字符串内容,整体还是分离?
2013-11-07 17:44 22219(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21336(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
Java的instanceof是如何实现的
2013-09-22 16:57 0Java语言规范,Java SE 7版 http://docs ... -
也谈类型: 数据, 类型, 标签
2013-08-18 01:59 0numeric tower http://en.wikiped ... -
oop、klass、handle的关系
2013-07-30 17:34 0oopDesc及其子类的实例 oop : oopDesc* ... -
Nashorn各种笔记
2013-07-15 17:03 0http://bits.netbeans.org/netbea ...
相关推荐
在Ubuntu上安装Oracle JDK
oracle jdk8 8u212 linux 64位, 包含文件: jdk-8u212-linux-x64.tar.gz -- jdk压缩文件 jdk环境变量配置说明
Oracle JDK11 Windows 压缩版
oracle jdk 1.5 1.6 1.7 linux 64位下载。百度云分享链接。
linux系统64位1.6版本的oracle jdk,可用于编译Android4.4源码。因为Oracle官网需要注册账号才能下载。有需要的可以下载这个。
linux oracle jdk 8安装包
JDK和ORACLE JDK冲突修改环境变量
OracleJDK1.8 For MacOS,版本号202,方便大家不需要Oracle安装器就可以直接配置JDK到环境变量,同时这是OracleJDK8最后一版本使用BCL协议的(后续使用OTN协议)
全名:jdk-16.0.2_windows-x64_bin.exe
java jdbc oracle (JDK1.6)驱动
这是oracle-jdk8最新版本的面相开发人员的开发工具集,是sun的jdk产品,支持mac平台,这是第一部分,两部分下来后进行合并后才能使用
openjdk与Oraclejdk的区别.doc openjdk与Oraclejdk的区别.doc openjdk与Oraclejdk的区别.doc openjdk与Oraclejdk的区别.doc openjdk与Oraclejdk的区别.doc openjdk与Oraclejdk的区别.doc
使用于32位window系统,稳定的jdk7,使用于32位window系统,稳定的jdk7,使用于32位window系统,稳定的jdk7,使用于32位window系统,稳定的jdk7,
jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk1.8 64位下载jdk...
Oracle JDK从2019年4月16号开始商用商用商用收费,最后一个免费版本是1.8.202
Oracle java jdk1.6.0_45 免费下载 jdk-6u45-windows-x64.exe
oracle官网 jdk-11.0.3_windows-x64
jdk-8u131适用64位系统.exe
oracle的JDBC驱动,JDK6,For use with JDK 6; It contains the JDBC driver classes except classes for NLS support in Oracle Object and Collection types.
windows64位jdk6、jdk7、jdk8安装包