java 编译相关 && java profile
查看jvm编译代码:
osx下 要点: 在bash_profile或个人的其他文件定义环境变量 LD_LIBRARY_PATH, 里面包含hdis-amd64.dylib
参考这里
[参考这里]http://www.nitschinger.at/Printing-JVM-generated-Assembler-on-Mac-OS-X
GC策略 Strategy
JVM里的GC(Garbage Collection)的算法有很多种,如标记清除收集器,压缩收集器,分代收集器等等,详见HotSpot VM GC 的种类
现在比较常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即将内存分为几个区域,将不同生命周期的对象放在不同区域里:young generation,tenured generation和permanet generation。绝大部分的objec被分配在young generation(生命周期短),并且大部分的object在这里die。当young generation满了之后,将引发minor collection(YGC)。在minor collection后存活的object会被移动到tenured generation(生命周期比较长)。最后,tenured generation满之后触发major collection。major collection(Full gc)会触发整个heap的回收,包括回收young generation。permanet generation区域比较稳定,主要存放classloader信息。
young generation有eden、2个survivor 区域组成。其中一个survivor区域一直是空的,是eden区域和另一个survivor区域在下一次copy collection后活着的objecy的目的地。object在survivo区域被复制直到转移到tenured区。
我们要尽量减少 Full gc 的次数(tenured generation 一般比较大,收集的时间较长,频繁的Full gc会导致应用的性能收到严重的影响)。
堆内存GC
JVM(采用分代回收的策略),用较高的频率对年轻的对象(young generation)进行YGC,而对老对象(tenured generation)较少(tenured generation 满了后才进行)进行Full GC。这样就不需要每次GC都将内存中所有对象都检查一遍。
非堆内存不GC
GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类,当然permgen space存放的内容不仅限于类)的话,就很可能出现PermGen Space错误。
内存申请、对象衰老过程
一、内存申请过程
JVM会试图为相关Java对象在Eden中初始化一块内存区域;
当Eden空间足够时,内存申请结束。否则到下一步;
JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;
当old区空间不够时,JVM会在old区进行major collection;
完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”Out of memory错误”;
二、对象衰老过程
新创建的对象的内存都分配自eden。Minor collection的过程就是将eden和在用survivor space中的活对象copy到空闲survivor space中。对象在young generation里经历了一定次数(可以通过参数配置)的minor collection后,就会被移到old generation中,称为tenuring。
concept:
GC Type | 什么时候发生 | 触发时发生了什么 | 注意 |
---|---|---|---|
YGC: young generation gc | 当young generation满了之后,将引发minor collection | 清空Eden+from survivor中所有no ref的对象占用的内存 |
将eden+from sur中所有存活的对象copy到to sur中 一些对象将晋升到old中: to sur放不下的 存活次数超过turning threshold中的
重新计算tenuring threshold(serial parallel GC会触发此项) 重新调整Eden 和from的大小(parallel GC会触发此项) |全过程暂停应用 \n 是否为多线程处理由具体的GC决定 | jstat –gcutil gc log |
|FGC: FullGC | old空间不足
perm空间不足
显示调用System.GC, RMI等的定时触发
YGC时的悲观策略
dump live的内存信息时(jmap –dump:live) | 清空heap中no ref的对象
permgen中已经被卸载的classloader中加载的class信息
如配置了CollectGenOFirst,则先触发YGC(针对serial GC)
如配置了ScavengeBeforeFullGC,则先触发YGC(针对serial GC) | 全过程暂停应用
是否为多线程处理由具体的GC决定
是否压缩需要看配置的具体GC | jstat –gcutil gc log |
permanent generation空间不足会引发Full GC,仍然不够会引发PermGen Space错误。
类别 | 介绍 | 试用场景 | 使用 | 内存回收触发 | 细节 |
---|---|---|---|---|---|
throughput collector与concurrent low pause collector的区别是throughput collector只在young area使用使用多线程,而concurrent low pause collector则在tenured generation也使用多线程。
根据官方文档,他们俩个需要在多CPU的情况下,才能发挥作用。在一个CPU的情况下,会不如默认的serial collector,因为线程管理需要耗费CPU资源。而在两个CPU的情况下,也提高不大。只是在更多CPU的情况下,才会有所提高。当然 concurrent low pause collector有一种模式可以在CPU较少的机器上,提供尽可能少的停顿的模式,见CMS GC Incremental mode。
当要使用throughput collector时,在java opt里加上-XX:+UseParallelGC,启动throughput collector收集。也可加上-XX:ParallelGCThreads=
附注SUN的官方说明:
The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.
The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.
The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.
CMS GC Incremental mode
当要使用 concurrent low pause collector时,在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector还有一种为CPU少的机器准备的模式,叫Incremental mode。这种模式使用一个CPU来在程序运行的过程中GC,只用很少的时间暂停程序,检查对象存活。
在Incremental mode里,每个收集过程中,会暂停两次,第二次略长。第一次用来,简单从root查询存活对象。第二次用来,详细检查存活对象。整个过程如下:
- stop all application threads; do the initial mark; resume all application threads(第一次暂停,初始话标记)
- do the concurrent mark (uses one procesor for the concurrent work)(运行是标记)
- do the concurrent pre-clean (uses one processor for the concurrent work)(准备清理)
- stop all application threads; do the remark; resume all application threads(第二次暂停,标记,检查)
- do the concurrent sweep (uses one processor for the concurrent work)(运行过程中清理)
do the concurrent reset (uses one processor for the concurrent work)(复原)
当要使用Incremental mode时,需要使用以下几个变量:
-XX:+CMSIncrementalMode default: disabled 启动i-CMS模式(must with -XX:+UseConcMarkSweepGC)
-XX:+CMSIncrementalPacing default: disabled 提供自动校正功能
-XX:CMSIncrementalDutyCycle=
-XX:CMSIncrementalDutyCycleMin=
-XX:CMSIncrementalSafetyFactor=
-XX:CMSIncrementalOffset=
-XX:CMSExpAvgFactor=
SUN推荐的使用参数是:
-XX:+UseConcMarkSweepGC \
-XX:+CMSIncrementalMode \
-XX:+CMSIncrementalPacing \
-XX:CMSIncrementalDutyCycleMin=0 \
-XX:CMSIncrementalDutyCycle=10 \
-XX:+PrintGC Details \
-XX:+PrintGCTimeStamps \
-XX:-TraceClassUnloading
注:如果使用throughput collector和concurrent low pause collector,这两种垃圾收集器,需要适当的挺高内存大小,以为多线程做准备。
如何选择collector:
app运行在单处理器机器上且没有pause time的要求,让vm选择或者UseSerialGC.
重点考虑peak application performance(高性能),没有pause time太严格要求,让vm选择或者UseParallelGC+UseParallelOldGC(optionally).
重点考虑response time,pause time要小,UseConcMarkSweepGC.
Garbage Collctor – Future
Garbage First(G1)
jdk1.6 update 14 or jdk7
few flags need to set
-XX:MaxGCPauseMillis=100
-XX:GCPauseIntervalMillis=6000
还没尝试过使用…
Summary
import java.util.ArrayList;
import java.util.List;
public class SummaryCase {
public static void main(String[] args) throws InterruptedException {
List
用以下两种参数执行,会执行几次YGC几次FGC?
-Xms30M -Xmx30M -Xmn10M -Xloggc:gc.log -XX:+PrintTenuringDistribution -XX:+UseParallelGC
2.062: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
6467K->6312K(29440K), 0.0038214 secs]
4.066: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
12536K->12440K(29440K), 0.0036804 secs]
6.070: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
18637K->18584K(29440K), 0.0040175 secs]
6.074: [Full GC 18584K->18570K(29440K), 0.0031329 secs]
8.078: [Full GC 24749K->3210K(29440K), 0.0045590 secs]
(具体分析见http://rdc.taobao.com/team/jm/archives/440)
-Xms30M -Xmx30M -Xmn10M -Xloggc:gc.log -XX:+PrintTenuringDistribution -XX:+UseSerialGC
2.047: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age 1: 142024 bytes, 142024 total
6472K->6282K(29696K), 0.0048686 secs]
4.053: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15) - age 2: 141880 bytes, 141880 total
12512K->12426K(29696K), 0.0047334 secs]
6.058: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15) - age 3: 141880 bytes, 141880 total
18627K->18570K(29696K), 0.0049135 secs]
8.063: [Full GC 24752K->3210K(29696K), 0.0077895 secs]
(具体分析见http://rdc.taobao.com/team/jm/archives/458)
http://www.cnblogs.com/redcreen/archive/2011/05/04/2037029.html
http://www.cnblogs.com/redcreen/archive/2011/05/04/2037056.html
http://www.infoq.com/cn/articles/zzm-java-hsdis-jvm/
http://thinkinmylife.iteye.com/blog/443900
http://download.oracle.com/javase/6/docs/api/