- 浏览: 3006231 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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分享的概要
把先前在论坛回复的一些帖打捞进来。这篇的原帖是:HotSpot VM 内存堆的两个Survivor区
下面是回复内容,带补充。
=================================================================
1、根本的区别之一:System.gc()可能在自动GC原本不会进入GC的位置上进入GC。
正常情况下,Java代码要尝试在GC堆上分配空间的时候才会触发GC;换句话说,基本上是“new”(或者类似的会隐式在GC堆上分配空间)的时候才会触发GC。但System.gc()、JVMTI的强制GC等动作都在正常情况之外提示系统要做一次GC。
这个情况即便在HotSpot上也不一定,要看被测的方法有没有被JIT编译过。解释执行的时候基本上没啥优化,所以局部变量的存活范围跟源码里看起来是一致的。但因为HotSpot的JIT编译带有优化,一个局部变量在一个方法里被使用过的赋值才会有效,而未被使用过的赋值很可能被消除掉。这样,在方法最后把局部变量设为null就是徒劳的,赋值动作本身都会被消除。事实上不需要额外的赋值为null的动作,JIT编译器也会尽可能的缩小变量的有效范围,所以完全没必要在方法末尾将局部变量置null。
在.NET的CLR上,由于方法总是要被编译了才可以执行(AOT或者JIT),而且编译也带有优化,源码里变量的引用状况跟实际运行时的引用状况的差异可能更明显些,像这个例子就比较极端。
2011-07-11补充:Peter Burka发了篇博文也提到了对象的生命周期可能比源码上看起来的要短的情况,A subtle issue of reachability
话说回来,Runtime.totalMemory()和Runtime.freeMemory()都是很RP的方法,其实并不适合细粒度观察…不知道您是用什么方式来“通过内存使用数据查看,该对象的内存是还没释放的”呢?
HotSpot默认会对方法调用次数的计数器做“衰减”,每进一次GC就会检查是否已到半衰周期,到了就会把所有方法的调用次数的计数器减半。如果写microbenchmark的话,在被测的方法里插入System.gc()很可能会带来干扰,使被测方法的调用次数始终达不到编译的条件,导致其不被JIT编译。要禁用计数器衰减的话,启动VM的时候要给参数-XX:-UseCounterDecay。要确认某个方法有没有被JIT编译请使用-XX:+PrintCompilation。
靠microbenchmark来观察某个对象有没有被GC回收多半是不准确的。可以具体情况具体分析。
另外值得注意的是,System.gc()不一定是触发所谓的“full GC”或者叫“major GC”。
在Sun JDK6与OpenJDK 6的HotSpot里,"GCCause是_java_lang_system_gc"的时候,如果VM启动参数DisableExplicitGC为false,则会触发一次full GC,如果该参数为true则完全不触发任何GC。要将这个参数设置为true,启动的时候写上-XX:+DisableExplicitGC就行。
HotSpot对System.gc()有特别处理,最主要的地方体现在一次System.gc()是否与普通GC一样会触发GC的统计/阈值数据的更新——HotSpot里的许多GC算法都带有自适应的功能,会根据先前收集的效率来决定接下来的GC中使用的参数,但System.gc()默认不更新这些统计数据,避免用户强行调用GC对这些自适应功能的干扰(可以参考HotSpot的UseAdaptiveSizePolicyWithSystemGC参数,默认是false)。除此之外,在HotSpot里,System.gc()所触发的full GC跟普通的full GC没啥大差别。
当使用Concurrent Mark-Sweep (CMS)时,可以通过-XX:+ExplicitGCInvokesConcurrent 或 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 参数来指定System.gc()触发并发GC而不是full GC。在CMS中,并发GC不对old gen做压缩,而full GC是stop-the-world的并且会做压缩。
------------------
在Oracle JRockit里,System.gc()触发的是nursery GC(如果选择了分代GC的话;如果选择的不是分代式GC算法则谈不上nursery还是old)。与HotSpot相同,可以通过一个参数禁用System.gc():-XXnoSystemGC。也可以通过另一个参数来强制System.gc()做full GC:-XXfullSystemGC。
JRockit R28里,禁用System.gc()的推荐参数是-XX:AllowSystemGC=false,而设定System.gc()触发full GC的参数是-XX:FullSystemGC=true。
------------------
在IBM JDK的JVM里,System.gc()同样可以禁用——使用-Xdisableexplicitgc参数。另外也有一些可以调节System.gc()触发的GC内容的参数,如-Xcompactexplicitgc、-Xnocompactexplicitgc之类。
============================================================
2、对OpenJDK 6里的HotSpot VM,请看这个文件,grep出/Use.*GC,/就知道了:
这样grep出来的启动参数中,UseMaximumCompactionOnSystemGC和UseAdaptiveSizePolicyWithSystemGC不是选择GC算法类型的参数,另外几个都是。它们分别是
·UseSerialGC
·UseG1GC
·UseParallelGC
·UseParallelOldGC
·UseAsyncConcMarkSweepGC(产品模式不可调)
·UseConcMarkSweepGC
·UseParNewGC
它们之间的关系请参考:Jon Masamitsu: Our Collectors
Sun(=> Oracle)的产品版JDK 6里的HotSpot同上。
------------------
JRockit R28的话,GC算法的基本设定可以用下面几个参数:
不过更推荐并且也更简单的是设定优化的目标,例如这几个参数:
-XgcPrio:throughput
-XgcPrio:pausetime
-XgcPrio:deterministic
有老帖描述了当时的JRockit该如何选择GC实现。
JRockit很有趣的一点是,当用户指定的是GC“模式”而不是具体的GC“策略”时,JRockit有可能在运行时根据运行状态改变具体的GC“策略”(只有选择了singlepar时无法改变策略,因为这个策略不需要write barrier但其它策略都需要)。
------------------
IBM J9有诸如下面几种设定GC算法的VM参数:
-Xgcpolicy:optthruput
-Xgcpolicy:optavgpause
-Xgcpolicy:gencon
-Xgcpolicy:subpool
下面是回复内容,带补充。
=================================================================
kingkan 写道
请教下前辈们:
1.手动System.gc()与JVM自动gc有什么根本上的区别么?在程序里面一个对象用完的时候,马上使用System.gc(),通过内存使用数据查看,该对象的内存是还没释放的。但是对象使用完,马上设置为null,再System.gc(),该对象的内存就被释放了,不解。
2.用户能自己设置JVM选择何种GC算法来进行GC么?
1.手动System.gc()与JVM自动gc有什么根本上的区别么?在程序里面一个对象用完的时候,马上使用System.gc(),通过内存使用数据查看,该对象的内存是还没释放的。但是对象使用完,马上设置为null,再System.gc(),该对象的内存就被释放了,不解。
2.用户能自己设置JVM选择何种GC算法来进行GC么?
1、根本的区别之一:System.gc()可能在自动GC原本不会进入GC的位置上进入GC。
正常情况下,Java代码要尝试在GC堆上分配空间的时候才会触发GC;换句话说,基本上是“new”(或者类似的会隐式在GC堆上分配空间)的时候才会触发GC。但System.gc()、JVMTI的强制GC等动作都在正常情况之外提示系统要做一次GC。
kingkan 写道
在程序里面一个对象用完的时候,马上使用System.gc(),通过内存使用数据查看,该对象的内存是还没释放的。但是对象使用完,马上设置为null,再System.gc(),该对象的内存就被释放了,不解。
这个情况即便在HotSpot上也不一定,要看被测的方法有没有被JIT编译过。解释执行的时候基本上没啥优化,所以局部变量的存活范围跟源码里看起来是一致的。但因为HotSpot的JIT编译带有优化,一个局部变量在一个方法里被使用过的赋值才会有效,而未被使用过的赋值很可能被消除掉。这样,在方法最后把局部变量设为null就是徒劳的,赋值动作本身都会被消除。事实上不需要额外的赋值为null的动作,JIT编译器也会尽可能的缩小变量的有效范围,所以完全没必要在方法末尾将局部变量置null。
在.NET的CLR上,由于方法总是要被编译了才可以执行(AOT或者JIT),而且编译也带有优化,源码里变量的引用状况跟实际运行时的引用状况的差异可能更明显些,像这个例子就比较极端。
2011-07-11补充:Peter Burka发了篇博文也提到了对象的生命周期可能比源码上看起来的要短的情况,A subtle issue of reachability
话说回来,Runtime.totalMemory()和Runtime.freeMemory()都是很RP的方法,其实并不适合细粒度观察…不知道您是用什么方式来“通过内存使用数据查看,该对象的内存是还没释放的”呢?
HotSpot默认会对方法调用次数的计数器做“衰减”,每进一次GC就会检查是否已到半衰周期,到了就会把所有方法的调用次数的计数器减半。如果写microbenchmark的话,在被测的方法里插入System.gc()很可能会带来干扰,使被测方法的调用次数始终达不到编译的条件,导致其不被JIT编译。要禁用计数器衰减的话,启动VM的时候要给参数-XX:-UseCounterDecay。要确认某个方法有没有被JIT编译请使用-XX:+PrintCompilation。
靠microbenchmark来观察某个对象有没有被GC回收多半是不准确的。可以具体情况具体分析。
另外值得注意的是,System.gc()不一定是触发所谓的“full GC”或者叫“major GC”。
在Sun JDK6与OpenJDK 6的HotSpot里,"GCCause是_java_lang_system_gc"的时候,如果VM启动参数DisableExplicitGC为false,则会触发一次full GC,如果该参数为true则完全不触发任何GC。要将这个参数设置为true,启动的时候写上-XX:+DisableExplicitGC就行。
HotSpot对System.gc()有特别处理,最主要的地方体现在一次System.gc()是否与普通GC一样会触发GC的统计/阈值数据的更新——HotSpot里的许多GC算法都带有自适应的功能,会根据先前收集的效率来决定接下来的GC中使用的参数,但System.gc()默认不更新这些统计数据,避免用户强行调用GC对这些自适应功能的干扰(可以参考HotSpot的UseAdaptiveSizePolicyWithSystemGC参数,默认是false)。除此之外,在HotSpot里,System.gc()所触发的full GC跟普通的full GC没啥大差别。
当使用Concurrent Mark-Sweep (CMS)时,可以通过-XX:+ExplicitGCInvokesConcurrent 或 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 参数来指定System.gc()触发并发GC而不是full GC。在CMS中,并发GC不对old gen做压缩,而full GC是stop-the-world的并且会做压缩。
------------------
在Oracle JRockit里,System.gc()触发的是nursery GC(如果选择了分代GC的话;如果选择的不是分代式GC算法则谈不上nursery还是old)。与HotSpot相同,可以通过一个参数禁用System.gc():-XXnoSystemGC。也可以通过另一个参数来强制System.gc()做full GC:-XXfullSystemGC。
JRockit R28里,禁用System.gc()的推荐参数是-XX:AllowSystemGC=false,而设定System.gc()触发full GC的参数是-XX:FullSystemGC=true。
------------------
在IBM JDK的JVM里,System.gc()同样可以禁用——使用-Xdisableexplicitgc参数。另外也有一些可以调节System.gc()触发的GC内容的参数,如-Xcompactexplicitgc、-Xnocompactexplicitgc之类。
============================================================
2、对OpenJDK 6里的HotSpot VM,请看这个文件,grep出/Use.*GC,/就知道了:
curl 'http://hg.openjdk.java.net/jdk6/jdk6/hotspot/raw-file/tip/src/share/vm/runtime/globals.hpp' | grep -A 2 -E 'Use.*GC,'
product(bool, UseSerialGC, false, \ "Use the serial garbage collector") \ \ product(bool, UseG1GC, false, \ "Use the Garbage-First garbage collector") \ \ product(bool, UseParallelGC, false, \ "Use the Parallel Scavenge garbage collector") \ \ product(bool, UseParallelOldGC, false, \ "Use the Parallel Old garbage collector") \ \ -- product(bool, UseMaximumCompactionOnSystemGC, true, \ "In the Parallel Old garbage collector maximum compaction for " \ "a system GC") \ -- product(bool, UseConcMarkSweepGC, false, \ "Use Concurrent Mark-Sweep GC in the old generation") \ \ -- develop(bool, UseAsyncConcMarkSweepGC, true, \ "Use Asynchronous Concurrent Mark-Sweep GC in the old generation")\ \ -- product(bool, UseParNewGC, false, \ "Use parallel threads in the new generation.") \ \ -- product(bool, UseAdaptiveSizePolicyWithSystemGC, false, \ "Use statistics from System.GC for adaptive size policy") \ \
这样grep出来的启动参数中,UseMaximumCompactionOnSystemGC和UseAdaptiveSizePolicyWithSystemGC不是选择GC算法类型的参数,另外几个都是。它们分别是
·UseSerialGC
·UseG1GC
·UseParallelGC
·UseParallelOldGC
·UseAsyncConcMarkSweepGC(产品模式不可调)
·UseConcMarkSweepGC
·UseParNewGC
它们之间的关系请参考:Jon Masamitsu: Our Collectors
Jon Masamitsu 写道
Sun(=> Oracle)的产品版JDK 6里的HotSpot同上。
------------------
JRockit R28的话,GC算法的基本设定可以用下面几个参数:
参数名 | 意义 |
-Xgc:singlecon 或 -Xgc:singleconcon | Concurrent Mark & Sweep 不分代,并发收集 |
-Xgc:gencon 或 -Xgc:genconcon | Generational Concurrent Mark & Sweep 分代式,并发收集 |
-Xgc:parallel 或 -Xgc:singlepar 或 -Xgc:singleparpar | Parallel Mark & Sweep 不分代,并行收集 |
-Xgc:genpar 或 -Xgc:genparpar | Generational Parallel Mark & Sweep 分代式,并行收集 |
-Xgc:singleconpar | Concurrent Mark, Parallel Sweep |
-Xgc:genconpar | Generational Concurrent Mark, Parallel Sweep |
-Xgc:singleparcon | Parallel Mark, Concurrent Sweep |
-Xgc:genparcon | Generational Parallel Mark, Concurrent Sweep |
不过更推荐并且也更简单的是设定优化的目标,例如这几个参数:
-XgcPrio:throughput
-XgcPrio:pausetime
-XgcPrio:deterministic
有老帖描述了当时的JRockit该如何选择GC实现。
JRockit很有趣的一点是,当用户指定的是GC“模式”而不是具体的GC“策略”时,JRockit有可能在运行时根据运行状态改变具体的GC“策略”(只有选择了singlepar时无法改变策略,因为这个策略不需要write barrier但其它策略都需要)。
------------------
IBM J9有诸如下面几种设定GC算法的VM参数:
-Xgcpolicy:optthruput
-Xgcpolicy:optavgpause
-Xgcpolicy:gencon
-Xgcpolicy:subpool
发表评论
-
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 22194(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21308(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 ...
相关推荐
Troubleshooting Guide for Java SE 6 with HotSpot VM
The Java HotSpot VM.pdf
jvm参数介绍,oracle HotSpot官方参数文档。
It will be set after the class is loaded.VM Started: Set deferred breakpoint Tes
HotSpot正是目前世界上java虚拟机的...还有两个runtime编译器(compilers )实现,正是他们帮助我们把类的字节码文件转换成本地的机器指令。当然还有大约3个垃圾收集器以及一系列用来实现同步的高性能运行库文件等等。
官方完整版JVM源码Hotspot VM,文件名hotspot.tar.gz。官方完整版JVM源码Hotspot VM,文件名hotspot.tar.gz。
HotspotContent:Hotspot应用程序的托管内容
官网HotSpot内存管理白皮书,对于jvm调优具有指导性意义
実装》第4章4.4小节. 每个版本的算法描述都稍微不同,我的伪代码也跟这两本书写的方式稍微不同,但背后要表达的核心思想是一样的就OK了.Tracing GC
本书以极其精练的语句诠释了 HotSpot VM的方方面面,比如:字节码的编译原理、字节码的内部组成结构、通过源码的方式剖析 HotSpot VM 的启动过程和初始化过程、Java 虚拟机的运行时内存、垃圾收集算法、垃圾收集器...
DR版回答是:t1在存Java静态变量的地方, 概念上在JVM的方法区(method area)里t2在Java堆里, 作为Test的一个实例的字段存在t3在J
学习JDK 源码必备,提起HotSpot VM,相信所有Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。 但不一定所有人都知道的是,这个目前看起来“血统纯正”的虚拟机在最初...
DR版回答是:t1在存Java静态变量的地方, 概念上在JVM的方法区(method area)里t2在Java堆里, 作为Test的一个实例的字段存在t3在J
The authors, who are all leading Java performance and Java HotSpot VM experts, help you improve performance by using modern software engineering practices, avoiding common mistakes, and applying tips ...
我打算为HotSpot VM写一个优化的JIT编译器。 多亏了 JVMCI,我可以使用-XX:+EnableJVMCI -XX:+UseJVMCICompiler -Djvmci.Compiler=yarrow选项在运行时轻松地将编译器插入JVM。 由于JVMCI是一项实验性功能,因此仅将...
技术文档分享。
The authors, who are all leading Java performance and Java HotSpot VM experts, help you improve performance by using modern software engineering practices, avoiding common mistakes, and applying tips ...
HotSpotSourceCodeExploration 基于OpenJDK10的HotSpot VM源代码的研究与探索。
openjdk是Oracle开源的JDK实现 原始目录介绍 src ├── cpu [CPU相关] | ├── ppc | ├── sparc | ├── x86 | ├── zero ├── os [操作系统相关] | ├── aix | ├── bsd ...| ├── solar