首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JVM调优技艺集锦(转)

2012-12-22 
JVM调优技巧集锦(转)1.?Heap设定与垃圾回收???????Java?Heap分为3个区,Young,Old和Permanent。Young保存刚

JVM调优技巧集锦(转)
1.?Heap设定与垃圾回收

???????Java?Heap分为3个区,Young,Old和Permanent。Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象,本文不讨论该区。

???????JVM的Heap分配可以使用-X参数设定,

???????-Xms?初始Heap大小

???????-Xmx?java?heap最大值

???????-Xmn?young?generation的heap大小?

???????JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young?区升级为Older区。Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能。

???????为什么一些程序频繁发生GC?有如下原因:

???????1)程序内调用了System.gc()或Runtime.gc()。

???????2)一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC。

???????3)Java的Heap太小,一般默认的Heap值都很小。

???????4)频繁实例化对象,Release对象。此时尽量保存并重用对象,例如使用StringBuffer()和String()。

???????如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态。许多Server端的Java程序每次GC后最好能有65%的剩余空间。

???????经验之谈:

???????1)Server端JVM最好将-Xms和-Xmx设为相同值。为了优化GC,最好让-Xmn值约等于-Xmx的1/3[2]。

???????2)一个GUI程序最好是每10到20秒间运行一次GC,每次在半秒之内完成[2]。


???????注意:

???????1)增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也?就是GC期间,Java应用程序不做任何工作。

???????2)Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等。


2.Stack的设定

???????每个线程都有他自己的Stack。

???????-Xss?每个线程的Stack大小?

???????Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小,例如-Xss1024K。如果Stack太小,也会导致Stack溢漏。

3.硬件环境

???????硬件环境也影响GC的效率,例如机器的种类,内存,swap空间,和CPU的数量。

???????如果你的程序需要频繁创建很多transient对象,会导致JVM频繁GC。这种情况你可以增加机器的内存,来减少Swap空间的使用[2]。

4.4种GC

???????第一种为单线程GC,也是默认的GC。,该GC适用于单CPU机器。

???????第二种为Throughput?GC,是多线程的GC,适用于多CPU,使用大量线程的程序。第二种GC与第一种GC相似,不同在于GC在收集Young区是多线程的,但在Old区和第一种一样,仍然采用单线程。-XX:+UseParallelGC参数启动该GC。

???????第三种为Concurrent?Low?Pause?GC,类似于第一种,适用于多CPU,并要求缩短因GC造成程序停滞的时间。这种GC可以在Old区的回收同时,运行应用程序。-XX:+UseConcMarkSweepGC参数启动该GC。

???????第四种为Incremental?Low?Pause?GC,适用于要求缩短因GC造成程序停滞的时间。这种GC可以在Young区回收的同时,回收一部分Old区对象。-Xincgc参数启动该GC。


最后附上用java?-X?命令查看JVM的配置说明:

D:\j2sdk15\bin>java?-X

????-Xmixed???????????mixed?mode?execution?(default)

????-Xint?????????????interpreted?mode?execution?only

????-Xbootclasspath:<directories?and?zip/jar?files?separated?by?;>

??????????????????????set?search?path?for?bootstrap?classes?and?resources

????-Xbootclasspath/a:<directories?and?zip/jar?files?separated?by?;>

??????????????????????append?to?end?of?bootstrap?class?path

????-Xbootclasspath/p:<directories?and?zip/jar?files?separated?by?;>

??????????????????????prepend?in?front?of?bootstrap?class?path

????-Xnoclassgc???????disable?class?garbage?collection

????-Xincgc???????????enable?incremental?garbage?collection

????-Xloggc:<file>????log?GC?status?to?a?file?with?time?stamps

????-Xbatch???????????disable?background?compilation

????-Xms<size>????????set?initial?Java?heap?size

????-Xmx<size>????????set?maximum?Java?heap?size

????-Xss<size>????????set?java?thread?stack?size

????-Xprof????????????output?cpu?profiling?data

????-Xfuture??????????enable?strictest?checks,?anticipating?future?default

????-Xrs??????????????reduce?use?of?OS?signals?by?Java/VM?(see?documentation)

????-Xcheck:jni???????perform?additional?checks?for?JNI?functions

????-Xshare:off???????do?not?attempt?to?use?shared?class?data

????-Xshare:auto??????use?shared?class?data?if?possible?(default)

????-Xshare:on????????require?using?shared?class?data,?otherwise?fail.

?

The?-X?options?are?non-standard?and?subject?to?change?without?notice.

-----------------------------------

?

JVM配置参数中文说明:

-----------------------------------

1、-Xmixed???????????mixed?mode?execution?(default)

?混合模式执行?

2、-Xint?????????????interpreted?mode?execution?only

?解释模式执行?

3、-Xbootclasspath:<directories?and?zip/jar?files?separated?by?;>

??????set?search?path?for?bootstrap?classes?and?resources

?设置zip/jar资源或者类(.class文件)存放目录路径?

3、-Xbootclasspath/a:<directories?and?zip/jar?files?separated?by?;>

??????append?to?end?of?bootstrap?class?path

?追加zip/jar资源或者类(.class文件)存放目录路径?

4、-Xbootclasspath/p:<directories?and?zip/jar?files?separated?by?;>

??????prepend?in?front?of?bootstrap?class?path

?预先加载zip/jar资源或者类(.class文件)存放目录路径?

5、-Xnoclassgc???????disable?class?garbage?collection

?关闭类垃圾回收功能?

6、-Xincgc???????????enable?incremental?garbage?collection

?开启类的垃圾回收功能?

7、-Xloggc:<file>????log?GC?status?to?a?file?with?time?stamps

?记录垃圾回日志到一个文件。?

8、-Xbatch???????????disable?background?compilation

?关闭后台编译?

9、-Xms<size>????????set?initial?Java?heap?size

?设置JVM初始化堆内存大小?

10、-Xmx<size>????????set?maximum?Java?heap?size

?设置JVM最大的堆内存大小?

11、-Xss<size>????????set?java?thread?stack?size

?设置JVM栈内存大小?

12、-Xprof????????????output?cpu?profiling?data

?输入CPU概要表数据?

13、-Xfuture??????????enable?strictest?checks,?anticipating?future?default

?执行严格的代码检查,预测可能出现的情况?

14、-Xrs??????????????reduce?use?of?OS?signals?by?Java/VM?(see?documentation)

?通过JVM还原操作系统信号?

15、-Xcheck:jni???????perform?additional?checks?for?JNI?functions

?对JNI函数执行检查?

16、-Xshare:off???????do?not?attempt?to?use?shared?class?data

?尽可能不去使用共享类的数据?

17、-Xshare:auto??????use?shared?class?data?if?possible?(default)

?尽可能的使用共享类的数据

18、-Xshare:on???????require?using?shared?class?data,?otherwise?fail.

?尽可能的使用共享类的数据,否则运行失败
?

The?-X?options?are?non-standard?and?subject?to?change?without?notice.

?

?

??????调整JVM?GC(Garbage?Collection),可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程,

由于各个程序具备不同的特点,如:web和GUI程序就有很大区别(Web可以适当的停顿,但GUI停顿是客户无法接受的),而且由于跑在各个机器上的配置不同(主要cup个数,内存不同),

所以使用的GC种类也会不同。接下来,我简单介绍一下如何调整GC。

?????首先说一下如何监视GC,你可以使用我以前文章中提到的JDK中的jstat工具?,也可以在java程序启动的opt里加上如下几个参数(注:这两个参数只针对SUN的HotSpot?VM):

????-XX:-PrintGC?????Print?messages?at?garbage?collection.?Manageable.

????-XX:-PrintGC?Details?????Print?more?details?at?garbage?collection.?Manageable.?(Introduced?in?1.4.0.)

????-XX:-PrintGCTimeStamps?????Print?timestamps?at?garbage?collection.?Manageable?(Introduced?in?1.4.0.)


???当把-XX:-PrintGC?Details?加入到java?opt里以后可以看见如下输出:

????[GC?[DefNew:?34538K->2311K(36352K),?0.0232439?secs]?45898K->15874K(520320K),?0.0233874?secs]

????[Full?GC?[Tenured:?13563K->15402K(483968K),?0.2368177?secs]?21163K->15402K(520320K),?[Perm?:?28671K->28635K(28672K)],?0.2371537?secs]



????他们分别显示了GC的过程,清理出了多少空间。第一行GC使用的是?‘普通GC’(Minor?Collections),第二行使用的是?‘全GC’(Major?Collections)。他们的区别很大,在第一行最后

我们可以看见他的时间是0.0233874秒,而第二行的Full?GC的时间是0.2371537秒。第二行的时间是第一行的接近10倍,也就是我们这次调优的重点,减少Full?GC?的次数,因为Full?GC

会暂停程序比较长的时间,如果Full?GC?的次数比较多。程序就会经常性的假死。当然这只是他们的表面现象,接下来我仔细介绍一下GC,和?Full?GC(为后面的调优做准备)。



??????我们知道Java和C++的区别主要是,Java不需要像c++那样,由程序员主动的释放内存。而是由JVM里的GC(Garbage?Collection)来,在适当的时候替我们释放内存。GC?的内部工作,

即GC的算法有很多种,?如:标记清除收集器,压缩收集器,分代收集器等等。现在比较常用的是分代收集(也是SUN?VM使用的),即将内存分为几个区域,将不同生命周期的对象放在不同区域里

(新的对象会先?生成在Young?area,在几次GC以后,如过没有收集到,就会逐渐升级到Tenured?area)。在GC收集的时候,频繁收集生命周期短的区域(Young?area),因为这个区域内的

对象生命周期比较短,GC?效率也会比较高。而比较少的收集生命周期比较长的区域(Old?area?or?Tenured?area),以及基本不收集的永久区(Perm?area)。



?????注:Young?area又分为三个区域分别叫Eden,和俩个Survivor?spaces。Eden用来存放新的对象,Survivor?spaces用于?新对象?升级到?Tenured?area时的?拷贝。

?????我们管收集?生命周期短的区域(Young?area)?的收集叫?GC,而管收集?生命周期比较长的区域(Old?area?or?Tenured?area)的收集叫?Full?GC,因为他们的收集算法不同,

所以使用的时间也会不同。我们要尽量减少?Full?GC?的次数。



??????接下来介绍一下?HotSpot?VM?GC?的种类,GC在?HotSpot?VM?5.0里有四种。一种是默认的叫?serial?collector,另外几种分别叫throughput?collector,concurrent?

low?pause?collector,?incremental?(sometimes?called?train)?low?pause?collector(废弃掉了)。以下是SUN的官方说明:??



???1.?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.

???2.?The?concurrent?low?pause?collector:?this?collector?is?used?if?the?-Xincgc&#8482;?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.

???3.?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.



???????简单来说就是throughput?collector和concurrent?low?pause?collector:使用多线程的方式,利用多CUP来提高GC的效率,而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较少的机器上,提供尽可能少的停顿的模式,见下文。



????????当要使用throughput?collector时,在java?opt里加上-XX:+UseParallelGC,启动throughput?collector收集。也可加上-XX:ParallelGCThreads=<desired?number>来改变线程数。

还有两个参数?-XX:MaxGCPauseMillis=<nnn>和?-XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用来控制最大暂停时间,而-XX:?GCTimeRatio可以提高GC说占CPU的比,

以最大话的减小heap。



??????当要使用?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=<N>?default:?50?启动CMS的上线

???????-XX:CMSIncrementalDutyCycleMin=<N>?default:?10?启动CMS的下线

???????-XX:CMSIncrementalSafetyFactor=<N>?default:?10?用来计算循环次数

???????-XX:CMSIncrementalOffset=<N>?default:?0?最小循环次数(This?is?the?percentage?(0-



100)?by?which?the?incremental?mode?duty?cycle?is?shifted?to?the?right?within?the?period



between?minor?collections.)

???????-XX:CMSExpAvgFactor=<N>?default:?25?提供一个指导收集数



??????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,这两种垃圾收集器,需要适当的挺高内存大小,以为多线程做准备。
原文链接:http://www.fkjava.com/article/9/3956420869086266989.html

热点排行