??xml version="1.0" encoding="utf-8" standalone="yes"?>牛牛电影国产一区二区,在线成人动漫,精品99在线http://www.aygfsteel.com/conans/category/45963.html你越?zhun)扎我就兴?/description>zh-cnSat, 03 Dec 2011 23:03:50 GMTSat, 03 Dec 2011 23:03:50 GMT60Hot Spot JVM5中的GC调优http://www.aygfsteel.com/conans/articles/365427.htmlCONANCONANFri, 02 Dec 2011 13:59:00 GMThttp://www.aygfsteel.com/conans/articles/365427.html引言
有JAVA开发经验的朋友们一定碰到过下面的这U情?那就是自己所开发的应用q行?jin)一D|间后其性能或者响应速度?x)有明显的降?q是由多斚w的原因造成的即有程序本w的优化问题,也有q行环境问题.此运行环境即包括g环境也包括Y件环?大多ChW一个能惛_的解x(chng)法是提升g的配|而忽略了(jin)E序本n的运行环境JVM也提供了(jin)比较多的调优选项.本文重Ҏ(gu)q利用JVM的一些选项对GCq行调优.

U定:
1.读者应具备一定JAVA的知?

2.本文中的JVM选项均以SUN公司发布的HotSpot JVM 5为准Q不q大多数的选项在JVM1.3,JVM1.4中也是可用的Q?

3.以JAVA_HOME下demo/jfc/SwingSet2/SwingSet2.jarZq行说明.

4.阅读本文需要一些关于GC的知识,可以到附录A中了(jin)解这些知识?/p>

关键?
JVM(java虚拟?,调优,GC(垃圾回收)

JVM GC调优
Z(jin)能够JVM GC的调优能够用在具体的实践当?下面利用若q个例子来说明GC的调?
?QHeap size 讄
JVM堆的讄是指javaE序q行q程中JVM可以调配使用的内存空间的讄.JVM在启动的时候会(x)自动讄Heap size的|其初始空??Xms)是物理内存的1/64Q最大空?-Xmx)是物理内存的1/4。可以利用JVM提供?Xmn -Xms -Xmx{选项可进行设|。Heap size 的大是Young Generation 和Tenured Generaion 之和?br /> 当在JAVA_HOME下demo/jfc/SwingSet2/目录下执行下面的命o(h)?br /> java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar
pȝ输出为:(x)
Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 2" java.lang.OutOfMemoryError: Java heap space
除了(jin)q些异常信息外,q(sh)(x)发现E序的响应速度变慢?jin)。这说明Heap size 讄偏小QGC占用?jin)更多的旉Q而应用分配到的执行时间较?yu)?br /> 提示Q在JVM中如?8Q的旉是用于GC且可用的Heap size 不2Q的时候将抛出此异怿息?br /> 上面的命o(h)换成以下命o(h)执行则应用能够正怋用,且未抛出M异常?br /> java -jar -Xmn4m -Xms16m -Xmx32m SwingSet2.jar
提示QHeap Size 最大不要超q可用物理内存的80Q,一般的要将-Xms?Xmx选项讄为相同,?Xmn?/4?Xmx倹{?/font>

?QYoung GenerationQ?XmnQ的讄
在本例中看一下Young Generation的设|不同将有什么现象发生?br /> 假设Young generation 的大设|ؓ(f)4M Q即执行java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jarQ屏q输出如下(节选)(j)
[GC [DefNew: 3968K->64K(4032K), 0.0923407 secs] 3968K->2025K(32704K), 0.0931870 secs]
[GC [DefNew: 4021K->64K(4032K), 0.0356847 secs] 5983K->2347K(32704K), 0.0365441 secs]
[GC [DefNew: 3995K->39K(4032K), 0.0090603 secs] 6279K->2372K(32704K), 0.0093377 secs]
[GC [DefNew: 3992K->23K(4032K), 0.0057540 secs] 6325K->2356K(32704K), 0.0060290 secs]
[GC [DefNew: 3984K->27K(4032K), 0.0013058 secs] 6317K->2360K(32704K), 0.0015888 secs]
[GC [DefNew: 3981K->59K(4032K), 0.0023307 secs] 6315K->2422K(32704K), 0.0026091 secs]
程序体制ƈYoung Generation的大设|ؓ(f)8MQ即执行java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jarQ屏q输出如下(节选)(j)
[GC [DefNew: 7808K->192K(8000K), 0.1016784 secs] 7808K->2357K(32576K), 0.1022834 secs]
[GC [DefNew: 8000K->70K(8000K), 0.0149659 secs] 10165K->2413K(32576K), 0.0152557 secs]
[GC [DefNew: 7853K->59K(8000K), 0.0069122 secs] 10196K->2403K(32576K), 0.0071843 secs]
[GC [DefNew: 7867K->171K(8000K), 0.0075745 secs] 10211K->2681K(32576K), 0.0078376 secs]
[GC [DefNew: 7970K->192K(8000K), 0.0201353 secs] 10480K->2923K(32576K), 0.0206867 secs]
[GC [DefNew: 7979K->30K(8000K), 0.1787079 secs] 10735K->4824K(32576K), 0.1790065 secs]
那么Ҏ(gu)GC输出的信息(q里取第一行)(j)做一下Minor攉的比较。可以看Zơ的Minor攉分别在Young generation中找?904KQ?968K->64KQ和7616K(7808K->192K)而对于整个jvm则找?943KQ?968K->2025Q和5451KQ?808K->2357KQ。第一U情况下Minor攉?jin)大U?0Q(1943/3904Q的对象Q而另外的50Q的对象则被Ud?jin)tenured generation。在W二中情况下Minor攉?jin)大U?2Q的对象Q只有不?0Q的对象被移C(jin)Tenured Generation.q个例子说明此应用在的Young generation 讄?m时显的偏?br /> 提示Q一般的Young Generation的大是整个Heap size?/4。Young generation的minor攉率应一般在70Q以上。当然在实际的应用中需要根据具体情况进行调整?/font>

?QYoung Generation对应用响应的影响
q是使用-Xmn4m ?Xmn8mq行比较Q先执行下面的命?br />

java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar
屏幕输出如下Q节选)(j)
Application time: 0.5114944 seconds
[GC [DefNew: 3968K->64K(4032K), 0.0823952 secs] 3968K->2023K(32704K), 0.0827626 secs]
Total time for which application threads were stopped: 0.0839428 seconds
Application time: 0.9871271 seconds
[GC [DefNew: 4020K->64K(4032K), 0.0412448 secs] 5979K->2374K(32704K), 0.0415248 secs]
Total time for which application threads were stopped: 0.0464380 seconds
Young Generation 的Minor攉占用的时间可以计如下:(x)应用U程被中断的L?Q应用执行L?L+应用U程被中断的L常)(j)Q那么在本例中垃圾收集占用的?LUؓ(f)pȝ?Q~14Q。那么当垃圾攉占用的时间的比例大的时候,pȝ的响应将慢?br /> 提示Q对于互联网应用pȝ的响应稍微慢一些,用户是可以接受的Q但是对于GUIcd的应用响应速度慢将?x)给用户带来非常不好的体验?/font>

?Q如何决定Tenured Generation 的大?/strong>
分别?Xmn8m -Xmx32m?Xmn8m -Xmx64mq行Ҏ(gu)Q先执行
java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps javac,命o(h)行将提示Q只提取?jin)Major攉Q?br />

111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs]
122.463: [GC 122.463: [DefNew: 8128K->8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K->2366K(24576K), 0.1322560 secs] 26758K->2366K(32704K), 0.1325284 secs]
133.896: [GC 133.897: [DefNew: 8128K->8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K->2573K(24576K), 0.1340199 secs] 26368K->2573K(32704K), 0.1343218 secs]
144.112: [GC 144.112: [DefNew: 8128K->8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K->2304K(24576K), 0.1246831 secs] 24692K->2304K(32704K), 0.1249602 secs]
再执行java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps javac,命o(h)行将提示Q只提取?jin)Major攉Q?br /> 90.597: [GC 90.597: [DefNew: 8128K->8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K->5141K(57344K), 0.2129882 secs] 57969K->5141K(65472K), 0.2133274 secs]
120.899: [GC 120.899: [DefNew: 8128K->8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K->2430K(57344K), 0.2216590 secs] 58512K->2430K(65472K), 0.2219384 secs]
153.968: [GC 153.968: [DefNew: 8128K->8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K->2309K(57344K), 0.2193906 secs] 59292K->2309K(65472K), 0.2196372 secs]
可以看出在Heap size ?2m的时候系l等候时间约?.13U左叻I而设|ؓ(f)64m的时候等候时间则增大?.22U左右了(jin)。但是在32m的时候系l的Major攉间隔?0U左叻I而Heap size 增加?4m的时候ؓ(f)30U。那么应用在q行的时候是选择32mq是64m呢?如果应用是webcdQ即要求有大的吞吐量Q的应用则?4mQ即heapsize大一些)(j)的比较好。对于要求实时响应要求较高的场合Q例如GUI型的应用Q则使用32m比较好一些?nbsp;
注意Q?br /> 1。因为在JVM5q行时已l对Heap-sizeq行?jin)优化,所以在能确定java应用q行时不?x)超q默认的Heap size的情况下不要对这些D行修攏V?br /> 2。Heap size?-Xms -Xmn 讄不要出物理内存的大。否则会(x)提示“Error occurred during initialization of VM Could not reserve enough space for object heap”?/font>

?:如何~短minor攉的时?/strong>
下面比较一下采?XX:+UseParNewGC选项和不采用它的时候的minor攉有什么不同。先执行
java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar 
pȝ输出如下信息(片段?br /> [GC 7807K->2641K(32576K), 0.0676654 secs]
[GC 10436K->3108K(32576K), 0.0245328 secs]
[GC 10913K->3176K(32576K), 0.0072865 secs]
[GC 10905K->4097K(32576K), 0.0223928 secs]
之后再执?java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar
pȝ输出如下信息(片段?br /> [ParNew 7808K->2656K(32576K), 0.0447687 secs]
[ParNew 10441K->3143K(32576K), 0.0179422 secs]
[ParNew 10951K->3177K(32576K), 0.0031914 secs]
[ParNew 10985K->3867K(32576K), 0.0154991 secs]
很显然用了(jin)-XX:+UseParNewGC选项的minor攉的时间要比不使用的时候优?/p>

?:如何~短major攉的时?/strong>
下面比较一下采?XX:+UseConcMarkSweepGC选项和不采用它的时候的major攉有什么不同。先执行
java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar
pȝ输出如下信息(片段?br /> [Full GC 22972K->18690K(262080K), 0.2326676 secs]
[Full GC 18690K->18690K(262080K), 0.1701866 secs
之后再执?java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar
pȝ输出如下信息(片段?br /> [Full GC 56048K->18869K(260224K), 0.3104852 secs]
提示Q此选项在Heap Size 比较大而且Major攉旉较长的情况下使用更合适?/font>

?:关于-server选项 在JVM中将q行中的c认定ؓ(f)server-class的时候用此选项。SUN 的Hot Spot JVM5 如果判断到系l的配置满如下条g则自动将q行的类认定为server-classQƈ且会(x)自动讄jvm的选项Q当没有手工讄q选项的时候〕而且HOTSPOT JVM5提供?jin)自动调优的功能Q他?x)根据JVM的运行情况进行调整。如果没有特别的需要是不需要太多的人工q预的。SUN形象的称q个机制?#8220;Z工学”QErgonomics〕。具体可以参考http://java.sun.com/docs/hotspot/gc5.0/ergo5.html
*.h2个或更多个物理的处理?br /> *.h2G或者更多的物理内存
提示Q此选项要放在所有选项的前面。例如:(x)java -server 其他选项 javac?/font>

附录A:预备知识
Q?/strong>JVM中对象的划分?qing)管?/p>

JVMҎ(gu)q行于其中的对象的生存时间大致的分ؓ(f)3U。ƈ且将q?U不同的对象分别存放在JVM从系l分配到的不同的内存I间。这U对象存攄间的理方式叫做Generation理方式?br /> 1。Young GenerationQ用于存?#8220;早?#8221;对象Q即瞬时对象Q。例如:(x)在创建对象时或者调用方法时使用的(f)时对象或局部变量?br /> 2。Tenured GenerationQ用于存?#8220;ȝ”对象Q即较长旉被引用的对象Q。往(xin)往(xin)体现Z个大型程序中的全局对象或长旉被用的对象?br /> 3。Perm GenerationQ用于存?#8220;怹”对象。这些对象管理着q行于JVM中的cdҎ(gu)?/p>

Q?/strong>JVM选项的分c?/p>

JVM有这么几U选项供?
1.?X选项使用的项?又称为非标准选项Q不同厂商的此类型选项是有所不同的。例如:(x)IBM的JVM用的一些选项在Sun的JVM中就不一定能生效。这U选项的用方式如?
java -Xmn16m -Xms64m -Xmx64m javacd
2.?XX选项使用的项目,q种cd的选项可能要求有对pȝ信息讉K的权限。所以要慎用。这U选项的用方式如?
java -XX:MaxHeapFreeRatio=70 -XX:+PrintGCDetails javacd
3.java选项(卛_命o(h)行执行java后提C的选项).
java -server -verbose:gc -d64 javacd

Q?/strong>垃圾攉分类

在JVM中有两种垃圾方式Q一U叫做MinorQ次攉Q,另一U叫做MajorQ主攉Q。其中Minor在Young Generation的空间被对象全部占用后执行,主要是对Young Generation中的对象q行垃圾攉。而Major是针对于整个Heap size的垃圾收集。其中Minor方式的收集经常发生,q且Minor攉所占用的系l时间小。Major方式的垃圾收集则是一U?#8220;昂贵”的垃圾收集方式,因ؓ(f)在Major要对整个Heap sizeq行垃圾攉,q会(x)使得应用停顿的时间变得较ѝ?/p>

Q?/strong>GC信息的格?/p>

 

[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]
<collector> GC为minor攉q程中用的垃圾攉器v的内部名U?
<starting occupancy1> young generation 在进行垃圾收集前被对象用的存储I间.
<ending occupancy1> young generation 在进行垃圾收集后被对象用的存储I间
<pause time1> minor攉使应用暂停的旉长短(U? 
<starting occupancy3> 整个?Heap Size)在进行垃圾收集前被对象用的存储I间
<ending occupancy3> 整个?Heap Size)在进行垃圾收集后被对象用的存储I间
<pause time3> 整个垃圾攉使应用暂停的旉长短(U?,包括major攉使应用暂停的旉(如果发生?jin)major攉).
Q?/strong>GC信息的选项
-XX:+PrintGCDetails 昄GC的详l信?br /> -XX:+PrintGCApplicationConcurrentTime 打印应用执行的时?br /> -XX:+PrintGCApplicationStoppedTime 打印应用被暂停的旉
提示:1.":"后的"+"可C开启此选项,如果?-"号那么表C关闭此选项?br />      2.在不同的选项和不同的攉方式和类型下输出的格式会(x)有所不同?/font>

@import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

CONAN 2011-12-02 21:59 发表评论
]]>
jstat使用http://www.aygfsteel.com/conans/articles/365426.htmlCONANCONANFri, 02 Dec 2011 13:30:00 GMThttp://www.aygfsteel.com/conans/articles/365426.htmljstat

       1. jstat -gc pid

            可以昄gc的信息,查看gc的次敎ͼ?qing)时间?/p>

            其中最后五,分别是young gc的次敎ͼyoung gc的时_(d)full gc的次敎ͼfull gc的时_(d)gc的L间?/p>

      2.jstat -gccapacity pid
            可以昄QVM内存?sh)三代(young,old,permQ对象的使用和占用大,

            如:(x)PGCMN昄的是最perm的内存(sh)用量QPGCMX昄的是perm的内存最大用量Q?/p>

            PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量?/p>

            其他的可以根据这个类推, OC是old内纯的占用量?/p>

     3.jstat -gcutil pid

            l计gc信息l计?/p>

     4.jstat -gcnew pid

           q轻代对象的信息?/p>

     5.jstat -gcnewcapacity pid

           q轻代对象的信息?qing)其占用量?/p>

     6.jstat -gcold pid

          old代对象的信息?/p>

     7.stat -gcoldcapacity pid

          old代对象的信息?qing)其占用量?/p>

     8.jstat -gcpermcapacity pid

          perm对象的信息及(qing)其占用量?/p>

     9.jstat -class pid

          昄加蝲class的数量,?qing)所占空间等信息?br />      10.jstat -compiler pid

          昄VM实时~译的数量等信息?/p>

     11.stat -printcompilation pid

          当前VM执行的信息?/p>

        一些术语的中文解释Q?/p>

         S0CQ年M中第一个survivorQ幸存区Q的定w (字节)
         S1CQ年M中第二个survivorQ幸存区Q的定w (字节)
         S0UQ年M中第一个survivorQ幸存区Q目前已使用I间 (字节)
         S1UQ年M中第二个survivorQ幸存区Q目前已使用I间 (字节)
           ECQ年M中EdenQ伊甸园Q的定w (字节)
           EUQ年M中EdenQ伊甸园Q目前已使用I间 (字节)
           OCQOld代的定w (字节)
           OUQOld代目前已使用I间 (字节)
           PCQPerm(持久?的容?(字节)
           PUQPerm(持久?目前已用空?(字节)
         YGCQ从应用E序启动到采hq轻代中gcơ数
       YGCTQ从应用E序启动到采hq轻代中gc所用时?s)
         FGCQ从应用E序启动到采hold?全gc)gcơ数
       FGCTQ从应用E序启动到采hold?全gc)gc所用时?s)
         GCTQ从应用E序启动到采hgc用的L?s)

    NGCMNQ年M(young)中初始化(最?的大?(字节)

    NGCMXQ年M(young)的最大容?(字节)

        NGCQ年M(young)中当前的定w (字节)

   OGCMNQold代中初始?最?的大?(字节)

   OGCMXQold代的最大容?(字节)

       OGCQold代当前新生成的容?(字节)

   PGCMNQperm代中初始?最?的大?(字节)

   PGCMXQperm代的最大容?(字节)  

       PGCQperm代当前新生成的容?(字节)

          S0Q年M中第一个survivorQ幸存区Q已使用的占当前定w癑ֈ?/p>

         S1Q年M中第二个survivorQ幸存区Q已使用的占当前定w癑ֈ?/p>

           EQ年M中EdenQ伊甸园Q已使用的占当前定w癑ֈ?/p>

           OQold代已使用的占当前定w癑ֈ?/p>

           PQperm代已使用的占当前定w癑ֈ?/p>

  S0CMXQ年M中第一个survivorQ幸存区Q的最大容?(字节)

 S1CMX Q年M中第二个survivorQ幸存区Q的最大容?(字节)

    ECMXQ年M中EdenQ伊甸园Q的最大容?(字节)

       DSSQ当前需要survivorQ幸存区Q的定w (字节)QEden区已满)(j)

          TTQ?持有ơ数限制

       MTT Q?最大持有次数限?/p> @import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

CONAN 2011-12-02 21:30 发表评论
]]>
JVM调优http://www.aygfsteel.com/conans/articles/339582.htmlCONANCONANThu, 02 Dec 2010 02:53:00 GMThttp://www.aygfsteel.com/conans/articles/339582.html

一、相x(chng)?/span>


基本回收法

  1. 引用计数QReference CountingQ?br /> 比较古老的回收法。原理是此对象有一个引用,卛_加一个计敎ͼ删除一个引用则减少一个计数。垃圑֛收时Q只用收集计Cؓ(f)0的对象。此法最致命的是无法处理循环引用的问题?
  2. 标记-清除QMark-SweepQ?br /> 此算法执行分两阶Dc(din)第一阶段从引用根节点开始标记所有被引用的对象,W二阶段遍历整个堆,把未标记的对象清除。此法需要暂停整个应用,同时Q会(x)产生内存片?
  3. 复制QCopyingQ?br /> ? 法把内存空间划Z个相{的区域Q每ơ只使用其中一个区域。垃圑֛收时Q遍历当前用区域,把正在用中的对象复制到另外一个区域中。次法每次只处? 正在使用中的对象Q因此复制成本比较小Q同时复制过M后还能进行相应的内存整理Q不q出?#8220;片”问题。当?dng)此算法的~点也是很明昄Q就是需要两? 内存I间?
  4. 标记-整理QMark-CompactQ?br /> 此算法结合了(jin)“标记-清除”?#8220;? ?#8221;两个法的优炏V也是分两阶D,W一阶段从根节点开始标记所有被引用对象Q第二阶D遍历整个堆Q把清除未标记对象ƈ且把存活对象“压羃”到堆的其中一 块,按顺序排放。此法避免?#8220;标记-清除”的碎片问题,同时也避免了(jin)“复制”法的空间问题?
  5. 增量攉QIncremental CollectingQ?/strong>
    实施垃圾回收法Q即Q在应用q行的同时进行垃圑֛收。不知道什么原因JDK5.0中的攉器没有用这U算法的?
  6. 分代QGenerational CollectingQ?br /> Z对对象生命周期分析后得出的垃圑֛收算法。把对象分ؓ(f)q青代、年老代、持久代Q对不同生命周期的对象用不同的法Q上q方式中的一个)(j)q行回收。现在的垃圾回收器(从J2SE1.2开始)(j)都是使用此算法的?

分代垃圾回收详述


如上图所C,为Java堆中的各代分布?

  1. YoungQ年MQ?br /> q? M分三个区。一个Eden区,两个Survivor区。大部分对象在EdenZ生成。当Eden区满Ӟq存?gu)zȝ对象被复制到Survivor? Q两个中的一个)(j)Q当q个Survivor区满Ӟ此区的存?gu)zd象将被复制到另外一个Survivor区,当这个SurvivorM满了(jin)的时候,从第一 个Survivor区复制过来的q且此时q存?gu)zȝ对象Q将被复?#8220;q老区(Tenured)”。需要注意,Survivor的两个区是对U的Q没先后? p,所以同一个区中可能同时存在从Eden复制q来 对象Q和从前一个Survivor复制q来的对象,而复制到q老区的只有从W一个Survivor去过来的对象。而且QSurvivor区L一个是I? 的?
  2. TenuredQ年老代Q?br /> q老代存放从年M存活的对象。一般来说年老代存放的都是生命期较长的对象?
  3. PermQ持久代Q?br /> ? 于存N(rn)态文Ӟ如今JavacR方法等。持久代对垃圑֛收没有显著媄(jing)响,但是有些应用可能动态生成或者调用一些classQ例如Hibernate{, 在这U时候需要设|一个比较大的持久代I间来存放这些运行过E中新增的类。持久代大小通过-XX:MaxPermSize=<N>q行讄?/li>

GCcd
GC有两U类型:(x)Scavenge GC和Full GC ?
  1. Scavenge GC
    一般情况下Q当新对象生成,q且在Eden甌I间p|Ӟ好触发Scavenge GCQ堆Eden区域q行GCQ清除非存活对象Qƈ且把且存活的对象移动到Survivor区。然后整理Survivor的两个区?
  2. Full GC
    Ҏ(gu)个堆q行整理Q包括Young、Tenured和Perm。Full GC比Scavenge GC要慢Q因此应该尽可能减少Full GC。有如下原因可能DFull GCQ?
    • Tenured被写?
    • Perm域被写满
    • System.gc()被显C?
    • 上一ơGC之后Heap的各域分配策略动态变?


分代垃圾回收q程演示




二、垃圑֛收器


目前的收集器主要有三U:(x)串行攉器、ƈ行收集器、ƈ发收集器 ?/p>

  1. 串行攉?/strong>

    使用单线E处理所有垃圑֛收工作,因ؓ(f)无需多线E交互,所以效率比较高。但是,也无法用多处理器的优势Q所以此攉器适合单处理器机器。当?dng)此收集器也可以用在小数据量?strong>100M
    左右Q情况下的多处理器机器上。可以?strong>-XX:+UseSerialGC
    打开?br />
  2. q行攉?br />
    1. 对年Mq行q行垃圾回收Q因此可以减垃圑֛收时间。一般在多线E多处理器机器上使用。?strong>-XX:+UseParallelGC .打开。ƈ行收集器在J2SE5.0W六6更新上引入,在Java SE6.0中进行了(jin)增强--可以堆年老代q行q行攉?strong>如果q老代不用ƈ发收集的话,是用单U程q行垃圾回收 Q因此会(x)制约扩展能力。?strong>-XX:+UseParallelOldGC 打开?
    2. 使用-XX:ParallelGCThreads=<N> 讄q行垃圾回收的线E数?strong>此值可以设|与机器处理器数量相{?/strong> ?
    3. 此收集器可以q行如下配置Q?
      • 最大垃圑֛收暂? 指定垃圾回收时的最长暂停时_(d)通过-XX:MaxGCPauseMillis=<N> 指定?lt;N>为毫U?如果指定?jin)此值的话,堆大和垃圾回收相关参数?x)进行调整以辑ֈ指定?/strong> 。设定此值可能会(x)减少应用的吞吐量?
      • 吞吐? 吞吐量ؓ(f)垃圾回收旉与非垃圾回收旉的比?/strong> Q通过-XX:GCTimeRatio=<N> 来设定,公式?strong>1/Q?+NQ?/strong> 。例如,-XX:GCTimeRatio=19Ӟ表示5%的时间用于垃圑֛收。默认情况ؓ(f)99Q即1%的时间用于垃圑֛收?/li>
  3. q发攉?br /> 可以保证大部分工作都q发q行Q应用不停止Q,垃圾回收只暂停很的旉Q此攉器适合对响应时间要求比较高的中、大规模应用。?strong>-XX:+UseConcMarkSweepGC 打开?br />
    1. q? 发收集器主要减少q老代的暂停时_(d)他在应用不停止的情况下用独立的垃圾回收U程Q跟t可辑֯象。在每个q老代垃圾回收周期中,在收集初期ƈ发收集器? Ҏ(gu)个应用进行简短的暂停Q在攉中还?sh)(x)再暂停一ơ。第二次暂停?x)比W一ơ稍长,在此q程中多个线E同时进行垃圑֛收工作?
    2. q发攉器?strong>处理器换来短暂的停顿旉 。在一个N个处理器的系l上Qƈ发收集部分?strong>K/N 个可用处理器q行回收Q一般情况下1<=K<=N/4 ?
    3. 在只?strong>一个处理器的主Z使用q发攉?/strong> Q设|ؓ(f)incremental mode 模式也可获得较短的停时间?
    4. 动垃圾 Q由于在应用q行的同时进行垃圑֛Ӟ所以有些垃圑֏能在垃圾回收q行完成时生,q样造成?#8220;Floating Garbage”Q这些垃N要在下次垃圾回收周期时才能回收掉。所以,q发攉器一般需?strong>20% 的预留空间用于这些Q动垃圾?
    5. Concurrent Mode Failure Qƈ发收集器在应用运行时q行攉Q所以需要保证堆在垃圑֛收的q段旉有够的I间供程序用,否则Q垃圑֛收还未完成,堆空间先满了(jin)。这U情况下会(x)发生“q发模式p|”Q此时整个应用将?x)暂停,q行垃圾回收?
    6. 启动q发攉?/strong> Q因为ƈ发收集在应用q行时进行收集,所以必M证收集完成之前有_的内存空间供E序使用Q否则会(x)出现“Concurrent Mode Failure”。通过讄-XX:CMSInitiatingOccupancyFraction=<N> 指定q有多少剩余堆时开始执行ƈ发收?/li>
    • 串行处理器:(x)
       --适用情况Q数据量比较?yu)?00M左右Q;单处理器下ƈ且对响应旉无要求的应用?br />  --~点Q只能用于小型应?
    • q行处理器:(x)
       --适用情况Q?#8220;对吞吐量有高要求”Q多CPU、对应用响应旉无要求的中、大型应用。D例:(x)后台处理、科学计?br />  --~点Q应用响应时间可能较?
    • q发处理器:(x)
       --适用情况Q?#8220;对响应时间有高要?#8221;Q多CPU、对应用响应旉有较高要求的中、大型应用。D例:(x)Web服务?应用服务器、电(sh)信交换、集成开发环境?/li>

三、常见配|D?/span>
  1. 堆大设|?br /> JVM 中最大堆大小有三斚w限制Q相x(chng)作系l的数据模型Q?2-btq是64-bitQ限Ӟpȝ的可用虚拟内存限Ӟpȝ的可用物理内存限制?2位系l? 下,一般限制在1.5G~2GQ?4为操作系l对内存无限制。我在Windows Server 2003 pȝQ?.5G物理内存QJDK5.0下测试,最大可讄?478m?br /> 典型讄Q?/strong>
    • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
      - Xmx3550m Q设|JVM最大可用内存(sh)ؓ(f)3550M?br /> -Xms3550m Q设|JVM?j)内存(sh)?550m。此值可以设|与-Xmx相同Q以避免每次垃圾回收完成后JVM重新分配内存?br /> -Xmn2g Q设|年M大小?G?strong>整个堆大?q轻代大?+ q老代大小 + 持久代大?/span>
      。持久代一般固定大ؓ(f)64mQ所以增大年M后,会(x)减小q老代大小。此值对pȝ性能影响较大QSun官方推荐配置为整个堆?/8?br /> -Xss128k Q? 讄每个U程的堆栈大。JDK5.0以后每个U程堆栈大小?MQ以前每个线E堆栈大ؓ(f)256K。更具应用的U程所需内存大小q行调整。在相同物理? 存(sh)Q减这个D生成更多的线E。但是操作系l对一个进E内的线E数q是有限制的Q不能无限生成,l验值在3000~5000左右?br />
    • java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
      -XX:NewRatio=4 :讄q轻代(包括Eden和两个Survivor区)(j)与年老代的比|除去持久代)(j)。设|ؓ(f)4Q则q轻代与q老代所占比gؓ(f)1Q?Q年M占整个堆栈的1/5
      -XX:SurvivorRatio=4 Q设|年M中EdenZSurvivor区的大小比倹{设|ؓ(f)4Q则两个SurvivorZ一个Eden区的比gؓ(f)2:4Q一个Survivor区占整个q轻代的1/6
      -XX:MaxPermSize=16m :讄持久代大ؓ(f)16m?br /> -XX:MaxTenuringThreshold=0 Q设|垃圾最大年龄?strong>如果讄?的话Q则q轻代对象不l过Survivor区,直接q入q老代
      。对于年老代比较多的应用Q可以提高效率?strong>如果此D|ؓ(f)一个较大|则年M对象?x)在Survivor行多ơ复Ӟq样可以增加对象再年M的存?gu)zL?/span> Q增加在q轻代即被回收的概论?/code>
  2. 回收器选择
    JVMl了(jin)三种选择Q?strong>串行攉器、ƈ行收集器、ƈ发收集器 Q但是串行收集器只适用于小数据量的情况Q所以这里的选择主要针对q行攉器和q发攉器。默认情况下QJDK5.0以前都是使用串行攉器,如果想用其他收集器需要在启动时加入相应参数。JDK5.0以后QJVM?x)根据当?a >pȝ配置 q行判断?
    1. 吞吐量优?/strong> 的ƈ行收集器
      如上文所qͼq行攉器主要以到达一定的吞吐量ؓ(f)目标Q适用于科学技术和后台处理{?br /> 典型配置 Q?
      • java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
        -XX:+UseParallelGC Q选择垃圾攉器ؓ(f)q行攉器?strong>此配|仅对年M有效。即上述配置下,q轻代用ƈ发收集,而年老代仍旧使用串行攉?br />
        -XX:ParallelGCThreads=20 Q配|ƈ行收集器的线E数Q即Q同时多个U程一赯行垃圑֛收。此值最好配|与处理器数目相{?br />
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
        -XX:+UseParallelOldGC Q配|年老代垃圾攉方式为ƈ行收集。JDK6.0支持对年老代q行攉?br />
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100
        -XX:MaxGCPauseMillis=100 : 讄每次q轻代垃圑֛收的最长时_(d)如果无法满此时_(d)JVM?x)自动调整年M大小Q以满此倹{?br />
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
        -XX:+UseAdaptiveSizePolicy
        Q设|此选项后,q行攉器会(x)自动选择q轻代区大小和相应的Survivor区比例,以达到目标系l规定的最低相应时间或者收集频率等Q此值徏议用ƈ行收集器Ӟ一直打开?br />
    2. 响应旉优先 的ƈ发收集器
      如上文所qͼq发攉器主要是保证pȝ的响应时_(d)减少垃圾攉时的停顿旉。适用于应用服务器、电(sh)信领域等?br /> 典型配置 Q?
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
        -XX:+UseConcMarkSweepGC Q设|年老代为ƈ发收集。测试中配置q个以后Q?/code> -XX:NewRatio=4的配|失效了(jin)Q原因不明。所以,此时q轻代大最好用-Xmn讄?/code>
        -XX:+UseParNewGC : 讄q轻代ؓ(f)q行攉。可与CMS攉同时使用。JDK5.0以上QJVM?x)根据系l配|自行设|,所以无需再设|此倹{?/code>
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
        -XX:CMSFullGCsBeforeCompaction Q由于ƈ发收集器不对内存I间q行压羃、整理,所以运行一D|间以后会(x)产生“片”Q得运行效率降低。此D|运行多次GC以后对内存空间进行压~、整理?br /> -XX:+UseCMSCompactAtFullCollection Q打开对年老代的压~。可能会(x)影响性能Q但是可以消除碎?br />
  3. 辅助信息
    JVM提供?jin)大量命令行参数Q打C息,供调试用。主要有以下一些:(x)
    • -XX:+PrintGC
      输出形式Q[GC 118250K->113543K(130112K), 0.0094143 secs]

                      [Full GC 121376K->10414K(130112K), 0.0650971 secs]

    • -XX:+PrintGCDetails
      输出形式Q[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]

                      [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

    • -XX:+PrintGCTimeStamps -XX:+PrintGCQPrintGCTimeStamps可与上面两个混合使用
      输出形式Q?strong>11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
    • -XX:+PrintGCApplicationConcurrentTime: 打印每次垃圾回收前,E序未中断的执行旉。可与上面؜合?br /> 输出形式Q?strong>Application time: 0.5291524 seconds
    • -XX:+PrintGCApplicationStoppedTime Q打印垃圑֛收期间程序暂停的旉。可与上面؜合?br /> 输出形式Q?strong>Total time for which application threads were stopped: 0.0468229 seconds
    • -XX:PrintHeapAtGC :打印GC前后的详l堆栈信?br /> 输出形式Q?br /> 34.702: [GC {Heap before gc invocations=7:
       def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K,  99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
      from space 6144K,  55% used [0x221d0000, 0x22527e10, 0x227d0000)
        to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
       tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
      the space 69632K,   3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
       compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
         the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
          ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
          rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
       def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K,   0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
        from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
        to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)
       tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
      the space 69632K,   4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
       compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
         the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
          ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
          rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      }
      , 0.0757599 secs]
    • -Xloggc:filename :与上面几个配合用,把相x(chng)志信息记录到文g以便分析?/li>
  4. 常见配置汇?/strong>
    1. 堆设|?
      • -Xms :初始堆大?
      • -Xmx :最大堆大小
      • -XX:NewSize=n :讄q轻代大?
      • -XX:NewRatio=n: 讄q轻代和q老代的比倹{如:?Q表C年M与年老代比gؓ(f)1Q?Q年M占整个年Mq老代和的1/4
      • -XX:SurvivorRatio=n :q轻代中EdenZ两个Survivor区的比倹{注意Survivor区有两个。如Q?Q表CEdenQSurvivor=3Q?Q一个Survivor区占整个q轻代的1/5
      • -XX:MaxPermSize=n :讄持久代大?/li>
    2. 攉器设|?
      • -XX:+UseSerialGC :讄串行攉?
      • -XX:+UseParallelGC :讄q行攉?
      • -XX:+UseParalledlOldGC :讄q行q老代攉?
      • -XX:+UseConcMarkSweepGC :讄q发攉?/li>
    3. 垃圾回收l计信息
      • -XX:+PrintGC
      • -XX:+PrintGCDetails
      • -XX:+PrintGCTimeStamps
      • -Xloggc:filename
    4. q行攉器设|?
      • -XX:ParallelGCThreads=n :讄q行攉器收集时使用的CPU数。ƈ行收集线E数?
      • -XX:MaxGCPauseMillis=n :讄q行攉最大暂停时?
      • -XX:GCTimeRatio=n :讄垃圾回收旉占程序运行时间的癑ֈ比。公式ؓ(f)1/(1+n)
    5. q发攉器设|?
      • -XX:+CMSIncrementalMode :讄为增量模式。适用于单CPU情况?
      • -XX:ParallelGCThreads=n :讄q发攉器年M攉方式为ƈ行收集时Q用的CPU数。ƈ行收集线E数?/li>

四、调优ȝ
  1. q轻代大选择
    • 响应旉优先的应?/strong> Q?strong>可能设大,直到接近pȝ的最低响应时间限?/span> Q根据实际情况选择Q。在此种情况下,q轻代收集发生的频率也是最的。同Ӟ减少到达q老代的对象?
    • 吞吐量优先的应用 Q尽可能的设|大Q可能到达Gbit的程度。因为对响应旉没有要求Q垃圾收集可以ƈ行进行,一般适合8CPU以上的应用?/li>
  2. q老代大小选择
    • 响应旉优先的应?/strong> Q年老代使用q发攉器,所以其大小需要小?j)设|,一般要考虑q发?x)话?/strong> ?strong>?x)话持?hu)旉 {一些参数。如果堆讄了(jin)Q可以会(x)造成内存片、高回收频率以及(qing)应用暂停而用传l的标记清除方式Q如果堆大了(jin)Q则需要较长的攉旉。最优化的方案,一般需要参考以下数据获得:(x)
      • q发垃圾攉信息
      • 持久代ƈ发收集次?
      • 传统GC信息
      • 花在q轻代和q老代回收上的旉比例
      减少q轻代和q老代p的时_(d)一般会(x)提高应用的效?br />
    • 吞吐量优先的应用 Q一般吞吐量优先的应用都有一个很大的q轻代和一个较?yu)的q老代。原因是Q这样可以尽可能回收掉大部分短期对象Q减中期的对象Q而年老代存N期存?gu)zd象?/li>
  3. 较小堆引L(fng)片问题
    ? 为年老代的ƈ发收集器使用标记、清除算法,所以不?x)对堆进行压~。当攉器回收时Q他?x)把盔R的空间进行合qӞq样可以分配l较大的对象。但是,当堆I间 较小Ӟq行一D|间以后,׃(x)出现“片”Q如果ƈ发收集器找不到够的I间Q那么ƈ发收集器会(x)停止Q然后用传l的标记、清除方式进行回收。如果出 ?#8220;片”Q可能需要进行如下配|:(x)
    • -XX:+UseCMSCompactAtFullCollection Q用ƈ发收集器Ӟ开启对q老代的压~?
    • -XX:CMSFullGCsBeforeCompaction=0 Q上面配|开启的情况下,q里讄多少ơFull GC后,对年老代q行压羃


CONAN 2010-12-02 10:53 发表评论
]]>
慢慢琢磨JVMhttp://www.aygfsteel.com/conans/articles/338994.htmlCONANCONANThu, 25 Nov 2010 02:11:00 GMThttp://www.aygfsteel.com/conans/articles/338994.html

1 JVM?

JVM是我们Javaer的最基本功底?jin),刚开始学Java的时候,一般都是从“Hello World”开始的Q然后会(x)写个复杂点classQ然后再找一些开源框Ӟ比如SpringQHibernate{等Q再然后开发企业的应用,比如|站、企业内部应用、实时交易系l等{,直到某一天突然发现做的系l咋p么慢呢,而且时不时还来个内存溢出什么的Q今天是交易pȝ报了(jin)StackOverflowErrorQ明天是|站pȝ报了(jin)个OutOfMemoryErrorQ这U错误又很难重现Q只有分析Javacore和dump文gQ运气好点还能分析出个结果,q行遭的点,q接去庙里烧香吧!每天接客L(fng)?sh)话都是战战兢兢的,生怕再Z么ُ(gu)蛑֭?jin)。我想Java做的久一点的都有q样的经历,那这些问题的最l根l是在哪呢?—?JVM?/p>

JVM全称是Java Virtual MachineQJava虚拟机,也就是在计算Z再虚拟一个计机Q这和我们?VMWare不一P那个虚拟的东西你是可以看到的Q这个JVM你是看不到的Q它存在内存?sh)。我们知道计机的基本构成是Q运器、控制器、存储器、输入和输出讑֤Q那q个JVM也是有这成套的元素,q算器是当然是交l硬件CPUq处理了(jin)Q只是ؓ(f)?jin)适应“一ơ编译,随处q行”的情况,需要做一个翻译动作,于是q?jin)JVM自己的命令集Q这与汇~的命o(h)集有点类|每一U汇~命令集针对一个系列的CPUQ比?086pd的汇~也是可以用?088上的Q但是就不能跑在8051上,而JVM的命令集则是可以到处q行的,因ؓ(f)JVM做了(jin)译Q根据不同的CPUQ翻译成不同的机器语a?/p>

JVM中我们最需要深入理解的是它的存储部分Q存储?盘QNOQNOQ?JVM是一个内存(sh)的虚拟机Q那它的存储是内存?sh)(jin),我们写的所有类、常量、变量、方法都在内存(sh)Q这军_着我们E序q行的是否健壮、是否高效,接下来的部分是重点介绍之?/p>

2 JVM的组成部?

我们先把JVMq个虚拟机画出来Q如下图所C:(x)


从这个图中可以看刎ͼJVM是运行在操作pȝ之上的,它与g没有直接的交互。我们再来看下JVM有哪些组成部分,如下图所C:(x)



 该图参考了(jin)|上qؓ(f)传的JVM构成图,大家看这个图Q整个JVM分ؓ(f)四部分:(x)

Class Loader cd载器

cd载器的作用是加蝲cL件到内存Q比如编写一个HelloWord.javaE序Q然后通过javac~译成class文gQ那怎么才能加蝲到内存(sh)被执行呢QClass Loader承担的就是这个责任,那不可能随便建立一?class文gp被加载的QClass Loader加蝲的class文g是有格式要求Q在《JVM Specification》中式这样定义Class文g的结构:(x)

    ClassFile {

     u4 magic;

     u2 minor_version;

     u2 major_version;

     u2 constant_pool_count;

     cp_info constant_pool[constant_pool_count-1];

     u2 access_flags;

     u2 this_class;

     u2 super_class;

     u2 interfaces_count;

     u2 interfaces[interfaces_count];

     u2 fields_count;

     field_info fields[fields_count];

     u2 methods_count;

     method_info methods[methods_count];

     u2 attributes_count;

     attribute_info attributes[attributes_count];

    }

需要详l了(jin)解的话,可以仔细阅读《JVM Specification》的W四?#8220;The class File Format”Q这里不再详l说明?/p>

友情提示Q?span>Class Loader只管加蝲Q只要符合文件结构就加蝲Q至于说能不能运行,则不是它负责的,那是?span>Execution Engine负责的?/span>

Execution Engine 执行引擎

执行引擎也叫做解释器(Interpreter)Q负责解释命令,提交操作pȝ执行?/p>

Native Interface本地接口

本地接口的作用是融合不同的编E语a为Java所用,它的初衷是融合C/C++E序QJava诞生的时候是C/C++横行的时候,要想立Q必L一个聪明的、睿智的调用C/C++E序Q于是就在内存(sh)专门开辟了(jin)一块区域处理标Cؓ(f)native的代码,它的具体做法是Native Method Stack中登记nativeҎ(gu)Q在Execution Engine执行时加载native libraies。目前该Ҏ(gu)使用的是来少?jin),除非是与g有关的应用,比如通过JavaE序驱动打印机,或者Javapȝ理生讑֤Q在企业U应用中已经比较?yu)见Q因为现在的异构领域间的通信很发达,比如可以使用Socket通信Q也可以使用Web Service{等Q不多做介绍?/p>

Runtime data areaq行数据?/p>

q行数据区是整个JVM的重炏V我们所有写的程序都被加载到q里Q之后才开始运行,Java生态系l如此的J荣Q得益于该区域的优良自治Q下一章节详细介绍之?/p>

整个JVM框架由加载器加蝲文gQ然后执行器在内存(sh)处理数据Q需要与异构pȝ交互是可以通过本地接口q行Q瞧Q一个完整的pȝ诞生?jin)?/p>

2 JVM的内存管?

所有的数据和程序都是在q行数据区存放,它包括以下几部分Q?/p>

Stack ?/p>

栈也叫栈内存Q是JavaE序的运行区Q是在线E创建时创徏Q它的生命期是跟随线E的生命期,U程l束栈内存(sh)释放,对于栈来说不存在垃圾回收问题Q只要线E一l束Q该栈就O(jin)ver。问题出来了(jin)Q栈中存的是那些数据呢?又什么是格式呢?

栈中的数据都是以栈QStack FrameQ的格式存在Q栈帧是一个内存区块,是一个数据集Q是一个有x(chng)?Method)和运行期数据的数据集Q当一个方法A被调用时׃生了(jin)一个栈帧F1Qƈ被压入到栈中QAҎ(gu)又调用了(jin)BҎ(gu)Q于是生栈帧F2也被压入栈,执行完毕后,先弹出F2栈Q再弹出F1栈Q遵?#8220;先进后出”原则?/p>

那栈帧中到底存在着什么数据呢Q栈帧中主要保存3cL据:(x)本地变量QLocal VariablesQ,包括输入参数和输出参C?qing)方法内的变量;栈操作(Operand StackQ,记录出栈、入栈的操作Q栈帧数据(F(tun)rame DataQ,包括cL件、方法等{。光说比较枯燥,我们M图来理解一下Java栈,如下图所C:(x)



 囄在一个栈中有两个栈Q栈?是最先被调用的方法,先入栈,然后Ҏ(gu)2又调用了(jin)Ҏ(gu)1Q栈?处于栈顶的位|,栈2处于栈底Q执行完毕后Q依ơ弹出栈?和栈?Q线E结束,栈释放?/p>

Heap 堆内?/p>

一个JVM实例只存在一个堆cdQ堆内存的大是可以调节的。类加蝲器读取了(jin)cL件后Q需要把cR方法、常变量攑ֈ堆内存(sh)Q以方便执行器执行,堆内存分Z部分Q?/p>

Permanent Space 怹存储?/strong>

怹存储区是一个常d存区域,用于存放JDK自n所携带的Class,Interface的元数据Q也是说它存储的是q行环境必须的类信息Q被装蝲q此区域的数据是不会(x)被垃圑֛收器回收掉的Q关闭JVM才会(x)释放此区域所占用的内存?/p>

Young Generation Space 新生?/strong>

新生区是cȝ诞生、成ѝ消亡的区域Q一个类在这里生,应用Q最后被垃圾回收器收集,l束生命。新生区又分Z部分Q? 伊甸区(Eden spaceQ和q存者区QSurvivor paceQ,所有的c都是在伊甸new出来的。幸存区有两个:(x) 0区(Survivor 0 spaceQ和1区(Survivor 1 spaceQ。当伊甸园的I间用完ӞE序又需要创建对象,JVM的垃圑֛收器对伊甸园区q行垃圾回收Q将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到q存0区。若q存0Z满了(jin)Q再对该行垃圑֛Ӟ然后Ud?区。那如果1Z满了(jin)呢?再移动到养老区?/span>

Tenure generation space养老区

养老区用于保存?sh)新生区{选出来的JAVA对象Q一般池对象都在q个区域z跃?nbsp;  三个区的C意囑֦下:(x)



 Method Area Ҏ(gu)?/p>

Ҏ(gu)区是被所有线E共享,该区域保存所有字D和Ҏ(gu)字节码,以及(qing)一些特D方法如构造函敎ͼ接口代码也在此定义?/p>

PC Register E序计数?/p>

每个U程都有一个程序计数器Q就是一个指针,指向Ҏ(gu)Z的方法字节码Q由执行引擎d下一条指令?/p>

Native Method Stack 本地Ҏ(gu)?/p>

3 JVM相关问题

问:(x)堆和栈有什么区?/strong>

{:(x)堆是存放对象的,但是对象内的临时变量是存在栈内存?sh),如例子中的methodVar是在q行期存攑ֈ栈中的?/p>

栈是跟随U程的,有线E就有栈Q堆是跟随JVM的,有JVM有堆内存?/p>

问:(x)堆内存(sh)到底存在着什么东西?

{:(x)对象Q包括对象变量以?qing)对象方法?/p>

问:(x)cd量和实例变量有什么区别?

{:(x)?rn)态变量是cd量,非静(rn)态变量是实例变量Q直白的_(d)有static修饰的变量是?rn)态变量,没有static修饰的变量是实例变量。静(rn)态变量存在方法区中,实例变量存在堆内存(sh)?/p>

问:(x)我听说类变量是在JVM启动时就初始化好的,和你q说的不同呀Q?/strong>

{:(x)那你是道听途说Q信我的Q没错?/p>

问:(x)Java的方法(函数Q到底是传D是传址Q?/strong>

{:(x)都不是,是以传值的方式传递地址Q具体的说原生数据类型传递的|引用cd传递的地址。对于原始数据类型,JVM的处理方法是从Method Area或Heap中拷贝到StackQ然后运行frame中的Ҏ(gu)Q运行完毕后再把变量指拷贝回厅R?/p>

问:(x)Z么会(x)产生OutOfMemory产生Q?/strong>

{:(x)一句话QHeap内存?sh)没有够的可用内存(sh)(jin)。这句话要好好理解,不是说Heap没有内存?sh)(jin),是说新申请内存的对象大于HeapI闲内存Q比如现在Heapq空?MQ但是新甌的内存需?.1MQ于是就?x)报OutOfMemory?jin),可能以后的对象申L(fng)内存都只?.9MQ于是就只出CơOutOfMemoryQGC也正怺(jin)Q看h像偶发事Ӟ是q么回事?nbsp;      但如果此时GC没有回收׃(x)产生挂v情况Q系l不响应?jin)?/p>

问:(x)我生的对象不多呀Qؓ(f)什么还?sh)(x)生OutOfMemoryQ?/strong>

{:(x)你(h)承层ơ忒多了(jin)QHeap? 产生的对象是先? 父类Q然后才产生子类Q明白不Q?/p>

问:(x)OutOfMemory错误分几U?

{:(x)分两U,分别?#8220;OutOfMemoryError:java heap size”?#8221;OutOfMemoryError: PermGen space”Q两U都是内存溢出,heap size是说甌不到新的内存?sh)(jin),q个很常见,(g)查应用或调整堆内存大?/p>

“PermGen space”是因为永久存储区满了(jin)Q这个也很常见,一般在热发布的环境中出玎ͼ是因为每ơ发布应用系l都不重启,久而久之永久存储区中的d象太多导致新对象无法甌内存Q一般重新启动一下即可?/p>

问:(x)Z么会(x)产生StackOverflowErrorQ?/strong>

{:(x)因ؓ(f)一个线E把Stack内存全部耗尽?jin),一般是递归函数造成的?/p>

问:(x)一个机器上可以看多个JVM吗?JVM之间可以互访吗?

{:(x)可以多个JVMQ只要机器承受得?jin)。JVM之间是不可以互访Q你不能在A-JVM中访问B-JVM的Heap内存Q这是不可能的。在以前老版本的JVM中,?x)出现A-JVM Crack后媄(jing)响到B-JVMQ现在版本非常少见?/p>

问:(x)Z么Java要采用垃圑֛收机Ӟ而不采用C/C++的显式内存管理?

{:(x)Z(jin)单,内存理不是每个E序员都能折腑֥的?/p>

问:(x)Z么你没有详细介绍垃圾回收机制Q?/strong>

{:(x)垃圾回收机制每个JVM都不同,JVM Specification只是定义?jin)要自动释放内存Q也是说它只定义了(jin)垃圾回收的抽象方法,具体怎么实现各个厂商都不同,法各异Q这东西实在没必要深入?/p>

问:(x)JVM中到底哪些区域是׃n的?哪些是私有的Q?/strong>

{:(x)Heap和Method Area是共享的Q其他都是私有的Q?/p>

问:(x)什么是JITQ你怎么没说Q?/strong>

{:(x)JIT是指Just In TimeQ有的文档把JIT作ؓ(f)JVM的一个部件来介绍Q有的是作ؓ(f)执行引擎的一部分来介l,q都能理解。Java刚诞生的时候是一个解释性语aQ别嘘,即ɾ~译成了(jin)字节码(byte codeQ也是针对JVM的,它需要再ơ翻译成原生代码(native code)才能被机器执行,于是效率的担忧就提出来了(jin)。SunZ(jin)解决该问题提Z(jin)一套新的机Ӟ好,你想~译成原生代码,没问题,我在JVM上提供一个工P把字节码~译成原生码Q下ơ你来访问的时候直接访问原生码成?jin),于是JITp生了(jin)Q就q么回事?/p>

问:(x)JVMq有哪些部分是你没有提到的?

{:(x)JVM是一个异常复杂的东西Q写一本砖头书都不Q还有几个要说明的:(x)

帔R池(constant poolQ:(x)按照序存放E序中的帔RQƈ且进行烦(ch)引编L(fng)区域。比?span>int i =100Q这?00放在常量池中?/p>

安全理器(Security ManagerQ:(x)提供Javaq行期的安全控制Q防止恶意攻击,比如指定d文gQ写入文件权限,|络讉KQ创E等{,Class Loader在Security Manager认证通过后才能加载class文g的?/p>

Ҏ(gu)索引表(Methods tableQ,记录的是每个method的地址信息QStack和Heap中的地址指针其实是指向Methods table地址?/p>

问:(x)Z么不在程序中昑ּ的生命System.gc()Q?/strong>

{:(x)因ؓ(f)昑ּ声明是做堆内存全扫描Q也是Full GCQ是需要停止所有的zd的(Stop  The World CollectionQ,你的应用能承受这个吗Q?/p>

问:(x)JVM有哪些调整参敎ͼ

{:(x)非常多,自己LQ堆内存、栈内存的大都可以定义Q甚x(chng)堆内存的三个部分、新生代的各个比例都能调整?/p>


CONAN 2010-11-25 10:11 发表评论
]]>
Sun JDK OOMhttp://www.aygfsteel.com/conans/articles/329031.htmlCONANCONANMon, 16 Aug 2010 10:21:00 GMThttp://www.aygfsteel.com/conans/articles/329031.html

Java的自动内存管理机制给开发h员带来了(jin)很多的便利,在设计、开发时可以完全不用考虑? 分配多少内存Q要记得回收内存{,但同时也带来?jin)各U各L(fng)问题Q其中最典型的问题就是OOMQ大部分Java开发h员(sh)计都看到q? java.lang.OutOfMemoryErrorq样的错误信息,在这文章中Q就来介l下Sun JDK中有哪几UOOM、OOMCZ、造成OOM的原因的查找、解决以?qing)Sun JDK代码中处理OOM的方式?/p>

PDF版本请从此下载:(x)http://blog.bluedavy.com/open/Sun-JDK-OOM.pdf

1 OOM的种c?br /> 在Sun JDK中运行时QJavaE序有可能出现如下几UOOM错误Q?br /> ?java.lang.OutOfMemoryError: unable to create new native thread
当调用new ThreadӞ如已创徏不了(jin)U程?jin),则?x)抛出此错误,如果是JDK内部必须创徏成功的线E,那么?x)造成Javaq程退出,如果是用L(fng)E,则仅抛出 OOMQ创Z?jin)的原因通常是创Z(jin)太多U程Q耗尽?jin)内存,通常可通过减少创徏的线E数Q或通过-Xss调小U程所占用的栈大小来减对Java 对外内存的消耗?/p>

?java.lang.OutOfMemoryError: request bytes for . Out of swap space?
当JNI模块或JVM内部q行malloc操作Q例如GC时做markQ时Q需要消耗堆外的内存Q如此时Javaq程所占用的地址I间过限制Q例? windows: 2GQlinux: 3GQ,或物理内存、swap区均使用完毕Q那么则?x)出现此错误Q当出现此错误时QJavaq程会(x)退出?/reason>

?java.lang.OutOfMemoryError: Java heap space
q是最常见的OOM错误Q当通过new创徏对象或数l时Q如Java HeapI间不Q新生代不Q触发minor GCQ还是不够,触发Full GCQ还是不够)(j)Q则抛出此错误?/p>

?java.lang.OutOfMemoryError: GC overhead limit execeeded
当通过new创徏对象或数l时Q如Java HeapI间不Q且GC所使用的时间占?jin)程序L间的98%Q且Heap剩余I间于2%Q则抛出此错误,以避免Full GC一直执行,可通过UseGCOverheadLimit来决定是否开启这U策略,可通过GCTimeLimit和GCHeapFreeLimit来控 制百分比?/p>

?java.lang.OutOfMemoryError: PermGen space
当加载classӞ在进行了(jin)Full GC后如PermGenI间仍然不Q则抛出此错误?br /> 对于以上几种OOM错误Q其中容易造成严重后果的是Out of swap spaceq种Q因U会(x)造成Javaq程退出,而其他几U只要不是在mainU程抛出的,׃?x)造成Javaq程退出?/p>

2 OOMCZ、原因查扑֒解决
q些CZ的class以及(qing)源码请从http://blog.bluedavy.com/jvm/cases/oom/OOMCases.zip下蝲Q徏议在q行前不要看源码Q毕竟源码是单的例子Q如果直接看源码的话Q可能会(x)了(jin)查找原因的乐?/p>

当JavaE序q行Ӟ?x)有很多U造成OOM的现象,q里面有些会(x)比较Ҏ(gu)查找出原因,而有些会(x)非常困难Q下面是来看一些OOM的Example?br /> ?Example 1
?Xms20m -Xmx20m -Xmn10m -XX:+UseParallelGC参数q行com.bluedavy.oom.JavaHeapSpaceCase1
q行后在输出的日志中可看到大量的Full GC信息Q以?qing)?x)
java.lang.OutOfMemoryError: GC overhead limit exceeded
和java.lang.OutOfMemoryError: Java heap space
Ҏ(gu)上面所说的OOMU类Q可以知道这是在new对象或数l时Java Heap Space不造成的,对于q种OOMQ需要知道的是程序中哪些部分占用?jin)Java Heap?br /> 要知道程序中哪些部分占用?jin)Java HeapQ首先必L到Java Heap中的信息Q尤其是OOM时的内存?sh)息Q在Sun JDK中可通过在启动参C加上-XX:+ HeapDumpOnOutOfMemoryError来获得OOM时的Java Heap中的信息Q当出现OOMӞ?x)自动生成一个java_pid[pid].hprof的文件?br /> 于是在启动参C加上上面的参敎ͼ再次q行JavaHeapSpaceCase1Q可看到在当前运行的路径下生成了(jin)一? java_pid10852.hprofQ由于pid不同Q你看到的可能是不一L(fng)文g名)(j)的文Ӟ在拿到这个文件后Q就可通过 matQhttp://www.eclipse.org/mat/Q来q行分析?jin)?br /> 用mat打开上面的文Ӟ默认情况下mat认ؓ(f)heap dump文g应以.binl尾Q因此请改名或以open file方式打开Q,打开后点击dominator_treeQ可看到sun.misc.Launcher$AppClassLoader占据?jin)大部分? 内存Q(h)l点开看,则可看到是由于com.bluedavy.oom.Caches中有一个ArrayListQ其中存攄对象占据?jin)大部分的内存,因? 解决q个OOM的办法是Q让CachescM攄对象d是有限制的Q或者限制放入Caches的ArrayList中的对象个数?br /> q种情况造成的OOMQ在实际的场景中当用缓存时很容易生,对于所有的~存、集合大都应给定限制的最大大,以避免出现缓存或集合太大Q导致消耗了(jin)q多的内存,从而导致OOM?/p>

?Example 2
?Xms20m -Xmx20m -Xmn10m -XX:+HeapDumpOnOutOfMemoryError执行com.bluedavy.oom.JavaHeapSpaceCase2
q行后在输出的日志中可看到大量的Full GC和java.lang.OutOfMemoryError: Java heap space?br /> 同样Q首先用mat打开需要分析的hprof文gQ很惊讶的发C么都看不出来QJava Heap Spaceq很充Q这奇怪了(jin)Q还好除?jin)能在OOM时自动dump出Heap的信息外Q还可通过jmap命o(h)手工dumpQ于是,在运行期出现频繁 Full GC、OOM的时候,手工通过jmap –dump:file=heap.bin,format=b [pid]生成一个heap.bin文gQ把q个heap.bin文g也拿到mat中分析,杯具Q还是什么都看不出来Q还好,q有一招,是直接? jmap –histo看看到底什么对象占用了(jin)大多数的内存Q执行一ơ,看到[I占用?jin)最多的内存Q没用,因ؓ(f)没法知道q个[I到底是代码中哪个部分创徏的,不甘 ?j),多执行几ơ,很幸q,H然看到com.bluedavy.oom.Case2Object占据?jin)最大的内存Q于是查找代码中哪些地方创徏?jin)这个对象? 发现?jin)代码中有一个线E创Z(jin)大量的Case2ObjectQ修改即可?br /> 从这个例子中Q可以看刎ͼ在分析OOM问题Ӟ一斚w是依赖OOM时dump出来的文Ӟ但这个文件其实只?x)在Javaq程中第一ơ出现OOM时生成,? 后再OOM׃?x)生成?jin)Q这有可能出现真实的OOM的原因被假的OOM原因l掩盖掉Q另一斚w是依赖在出现OOM时的人工操作Q这Uh肉方式其实比较杯 P因ؓ(f)只能先等到频JFull GC、OOMQ首先通过jmap –histo来看看到底什么对象占用了(jin)大部分的内存Q需要多执行几次Q以保正确性)(j)Q上面的例子比较q运Q因为刚好是自定义的对象Q如果是原生的类型, 那就只能借助dump文g来分析了(jin)Q通过jmap –dump手工dump出Heap文gQ然后用MAT分析Q但有可能会(x)出现上面例子中的状况Q就是mat分析上也看不Z么,多只能看到 unreachable objects里某些对象占用了(jin)大部分的内存Q而通常情况看到的可能都是原生类型,一旦真的碰到jmap –histo看到的是原生cd占用较多Qjmap dump看到的是Java Heap Space也不满的话,那只能说杯具?jin),在这U情况下Q唯一能做的是捕捉所有的异常Q然后打华ͼ从而判断OOM是在哪行代码抛出的?/p>

?Example 3
?Xms20m -Xmx20m -Xmn10m -XX:+HeapDumpOnOutOfMemoryError执行com.bluedavy.oom.JavaHeapSpaceCase3
在控制台中可看到大量的java.lang.OutOfMemoryError: Java heap spaceQ把生成的hprof文g攑օMAT中进行分析,q好看到实是Java Heap Space满了(jin)Q这好办了(jin)Q点开Dominator Tree视图Q可看到有一堆的U程Q每个都占用?jin)一定的内存Q从而导致了(jin)OOMQ要解决q个例子中的OOMQ有四种办法Q一是减处理的U程敎ͼ二是处理 U程需要消耗的内存Q三是提升线E的处理速度Q四是增加机器,减少单台机器所需承担的请求量?br /> 上面q种状况在系l处理慢的时候比较容易出现?/p>

?Example 4
?Xms20m -Xmx20m -Xmn10m -XX:+HeapDumpOnOutOfMemoryError执行com.bluedavy.oom.JavaHeapSpaceCase4
在控制台可看到大量的java.lang.OutOfMemoryError: Java heap spaceQ把生成的hprof文g攑օMAT中进行分析,可看到TaskExecutor中的handlers占据?jin)大量的内存Q分析代码,发现是由? 在task处理完后没有清除掉对应的handler造成的,修改卛_解决此OOM问题?br /> q是个典型的内存泄露的例子,如果不小?j)持有?jin)本应释放引用的对象,那么׃(x)造成内存泄露Q这是在~写JavaE序旉要特别注意的地方?/p>

?Example 5
?Xms1536m -Xmx1536m -Xss100m执行com.bluedavy.oom.CannotCreateThreadCase
在控制台可看到java.lang.OutOfMemoryError: unable to create new native thread?br /> 对于q种情况Q一需要查看目?Xss的大,例如在这个例子中-Xss太大Q导致连20个线E都无法创徏Q因此可解决的方法是降低-Xss的大;如果 Xss使用的是默认|那么可通过jstack来查看下目前Javaq程中是不是创徏?jin)过多的U程Q或者是java heap太大Q导致os没剩多少内存Q从而创Z出线E?/p>

?Example 6
Out of swap的例子实在太难D?jin),没在此列出了(jin),对于Out of swap的OOMQ需要首先观察是否因为Java Heap讄太大Q导致物理内?swapZ够用Q如果不是的话,则需x(chng)到底是哪些地方占用了(jin)堆外的内存,可通过google-perftools? 跟踪是哪些代码在调用mallocQ以?qing)所耗的内存比例Q在跟踪到后可(h)l查扑֎因?br /> M来说QOut of swap通常是最难查的OOMQ由于其是直接退出javaq程的,因此需要结合core dump文g和hs_err_pid[pid].logq行分析Q最关键的还是像查java heap那样Q要查出到底是什么代码造成?jin)native heap的消耗?/p>

?Example 7
PermGenI间满造成OOM的情况通常采取的解x(chng)法是单的扩大PermSize?/p>

ȝ上面的例子来看,对于OOM的情况,最重要的是Ҏ(gu)OOM的种cL扑ֈ底是代码中的什么部分造成的消耗?/p>

对于Java Heap Space OOM和GC overhead limit exceededq两U类型,可通过heap dump文g以及(qing)jmap –histo来进行分析,多数情况下可通过heap dump分析出原因,但也有少数情况会(x)出现heap dump分析不出原因Q而jmap –histo看到某原生类型占据了(jin)大部分的内存Q这U情况就非常复杂?jin),只能是仔l查看代码,q捕捉OutOfMemoryErrorQ从而来逐渐定位? 代码中哪部分抛出的?/p>

对于Out of swapq种cdQ其主要是地址I间过?jin)限制或者对外内存(sh)够用?jin)造成的,首先需要查看Java Heap讄是否q大Q然后可l合google-perftools来查看到底是哪些代码调用?jin)mallocQ在堆外分配内存?/p>

3 Sun JDK代码中处理OOM的方?br /> 在Sun JDK代码中,在不同的OOMӞ?x)调用不同的处理方式来进行处理,下面来看看JDK中几个典型的处理OOM的代码?br /> ?创徏U程p|
compiler_thread = new CompilerThread(queue, counters);
if (compiler_thread == NULL || compiler_thread->osthread() == NULL){
vm_exit_during_initialization(“java.lang.OutOfMemoryError”,
“unable to create new native thread”);
}
对于JDK中必d建成功的U程Q如p|?x)通过调用vm_exit_during_initialization打印出OOM错误Qƈ退出Javaq程?br /> 对于非必d建成功的U程Q通常?x)调?br /> THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
“unable to create new native thread”);
抛出OOM错误信息?/p>

?调用os:mallocp|
void *p = os::malloc(bytes);
if (p == NULL)
vm_exit_out_of_memory(bytes, “Chunk::new”);
return p;
当os:malloc或os:commit_memoryp|Ӟ?x)直接输出错误信息,q出Javaq程?/p>

?Java Heap上分配失败后
report_java_out_of_memory(“Java heap space”);
调用q个p明了(jin)不会(x)退出vmQ而只是抛出OOM错误?br /> 例如PermGen分配p|时的代码更ؓ(f)直观Q?br /> HeapWord* result = Universe::heap()->permanent_mem_allocate(size);
if (result != NULL) {
NOT_PRODUCT(Universe::heap()->
check_for_non_bad_heap_word_value(result, size));
assert(!HAS_PENDING_EXCEPTION,
“Unexpected exception, will result in uninitialized storage”);
return result;
}
// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
report_java_out_of_memory(“PermGen space”);

M而言Q对于一个大型系l而言Q通常OOM是难以避免的现象Q最重要的还是一旦出现OOMQ要掌握排查的方法,另外是Q随着现在内存来便 宜,CMS GC来成熟,采用64 bit操作pȝQ开启大内存?sh)是一U可选方式,基本上可以避免内存成为大问题Q毕竟在Java中完全可能随便写几行代码׃知不觉消耗了(jin)很多内存?/p>

ps: 感兴的同学q可参考sun官方的这关于OOM的文章:(x)
http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/memleaks.html





CONAN 2010-08-16 18:21 发表评论
]]>
վ֩ģ壺 ˱| | | | ԭ| | ˫| | | ƽ̶| | | | | ͭɽ| ³ľ| | | ɽ| ʯ̨| | | | ˮ| ߮| ̶| | | | ƽ| | | | | | ʡ| | ¹Ȫ| Т| ԭ| ƽ|