麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Java虛擬機(jī)詳解----常用JVM配置參數(shù)

2019-11-14 11:22:49
字體:
供稿:網(wǎng)友

原文地址:http://www.companysz.com/smyhvae/p/4736162.html

【聲明】 

歡迎

聯(lián)系方式:[email protected]  

 

本文主要內(nèi)容:

Trace跟蹤參數(shù)堆的分配參數(shù)棧的分配參數(shù)

 

零、在IDE的后臺(tái)打印GC日志:

既然學(xué)習(xí)JVM,閱讀GC日志是處理java虛擬機(jī)內(nèi)存問題的基礎(chǔ)技能,它只是一些人為確定的規(guī)則,沒有太多技術(shù)含量。

既然如此,那么在IDE的控制臺(tái)打印GC日志是必不可少的了。現(xiàn)在就告訴你怎么打印。

(1)如果你用的是Eclipse,打印GC日志的操作如下:

在上圖的箭頭處加上-XX:+PRintGCDetails這句話。于是,運(yùn)行程序后,GC日志就可以打印出來了:

(2)如果你用的是IntelliJ IDEA,打印GC日志的操作如下:

在上圖的箭頭處加上-XX:+PrintGCDetails這句話。于是,運(yùn)行程序后,GC日志就可以打印出來了:

當(dāng)然了,光有-XX:+PrintGCDetails這一句參數(shù)肯定是不夠的,下面我們?cè)敿?xì)介紹一下更多的參數(shù)配置。

 

一、Trace跟蹤參數(shù):

1、打印GC的簡要信息:

-verbose:gc-XX:+printGC

解釋:可以打印GC的簡要信息。比如:

[GC 4790K->374K(15872K), 0.0001606 secs]

[GC 4790K->374K(15872K), 0.0001474 secs]

[GC 4790K->374K(15872K), 0.0001563 secs]

[GC 4790K->374K(15872K), 0.0001682 secs]

上方日志的意思是說,GC之前,用了4M左右的內(nèi)存,GC之后,用了374K內(nèi)存,一共回收了將近4M。內(nèi)存大小一共是16M左右。

 

2、打印GC的詳細(xì)信息:

-XX:+PrintGCDetails

解釋:打印GC詳細(xì)信息。

-XX:+PrintGCTimeStamps

解釋:打印CG發(fā)生的時(shí)間戳。

 

理解GC日志的含義:

例如下面這段日志:

[GC[DefNew: 4416K->0K(4928K), 0.0001897 secs] 4790K->374K(15872K), 0.0002232 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

上方日志的意思是說:這是一個(gè)新生代的GC。方括號(hào)內(nèi)部的“4416K->0K(4928K)”含義是:“GC前該內(nèi)存區(qū)域已使用容量->GC后該內(nèi)存區(qū)域已使用容量(該內(nèi)存區(qū)域總?cè)萘浚薄6诜嚼ㄌ?hào)之外的“4790K->374K(15872K)”表示“GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆總?cè)萘浚薄?/p>

再往后看,“0.0001897 secs”表示該內(nèi)存區(qū)域GC所占用的時(shí)間,單位是秒。

 

再比如下面這段GC日志:

上圖中,我們先看一下用紅框標(biāo)注的“[0x27e80000, 0x28d80000, 0x28d80000)”的含義,它表示新生代在內(nèi)存當(dāng)中的位置:第一個(gè)參數(shù)是申請(qǐng)到的起始位置,第二個(gè)參數(shù)是申請(qǐng)到的終點(diǎn)位置,第三個(gè)參數(shù)表示最多能申請(qǐng)到的位置。上圖中的例子表示新生代申請(qǐng)到了15M的控件,而這個(gè)15M是等于:(eden space的12288K)+(from space的1536K)+(to space的1536K)。

疑問:分配到的新生代有15M,但是可用的只有13824K,為什么會(huì)有這個(gè)差異呢?等我們?cè)诤竺娴奈恼轮袑W(xué)習(xí)到了GC算法之后就明白了。

 

3、指定GC log的位置:

-Xloggc:log/gc.log

解釋:指定GC log的位置,以文件輸出。幫助開發(fā)人員分析問題。

  

-XX:+PrintHeapAtGC

解釋:每一次GC前和GC后,都打印堆信息。

例如:

上圖中,紅框部分正好是一次GC,紅框部分的前面是GC之前的日志,紅框部分的后面是GC之后的日志。

 

-XX:+TraceClassLoading

解釋:監(jiān)控類的加載。

例如:

[Loaded java.lang.Object from shared objects file]

[Loaded java.io.Serializable from shared objects file]

[Loaded java.lang.Comparable from shared objects file]

[Loaded java.lang.CharSequence from shared objects file]

[Loaded java.lang.String from shared objects file]

[Loaded java.lang.reflect.GenericDeclaration from shared objects file]

[Loaded java.lang.reflect.Type from shared objects file]

 

-XX:+PrintClassHistogram

 

解釋:按下Ctrl+Break后,打印類的信息。

例如:

 

二、堆的分配參數(shù):

1、-Xmx –Xms:指定最大堆和最小堆

舉例、當(dāng)參數(shù)設(shè)置為如下時(shí):

-Xmx20m -Xms5m

然后我們?cè)诔绦蛑羞\(yùn)行如下代碼:

System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");     //系統(tǒng)的最大空間System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的空閑空間System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");   //當(dāng)前可用的總空間

 運(yùn)行效果:

保持參數(shù)不變,在程序中運(yùn)行如下代碼:(分配1M空間給數(shù)組)

復(fù)制代碼
byte[] b = new byte[1 * 1024 * 1024];System.out.println("分配了1M空間給數(shù)組");System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的最大空間System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的空閑空間System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");   復(fù)制代碼

運(yùn)行效果:

注:Java會(huì)盡可能將total mem的值維持在最小堆。

保持參數(shù)不變,在程序中運(yùn)行如下代碼:(分配10M空間給數(shù)組)

復(fù)制代碼
byte[] b = new byte[10 * 1024 * 1024];System.out.println("分配了10M空間給數(shù)組");System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的最大空間System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的空閑空間System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");   //當(dāng)前可用的總空間復(fù)制代碼

運(yùn)行效果:

如上圖紅框所示:此時(shí),total mem 為7M時(shí)已經(jīng)不能滿足需求了,于是total mem漲成了16.5M。

 

保持參數(shù)不變,在程序中運(yùn)行如下代碼:(進(jìn)行一次GC的回收)

復(fù)制代碼
System.gc();System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");    //系統(tǒng)的最大空間System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");   //系統(tǒng)的空閑空間System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");   //當(dāng)前可用的總空間 復(fù)制代碼

運(yùn)行效果:

問題1: -Xmx(最大堆空間)和 –Xms(最小堆空間)應(yīng)該保持一個(gè)什么關(guān)系,可以讓系統(tǒng)的性能盡可能的好呢?

問題2:如果你要做一個(gè)Java的桌面產(chǎn)品,需要綁定JRE,但是JRE又很大,你如何做一下JRE的瘦身呢?

 

2、-Xmn、-XX:NewRatio、-XX:SurvivorRatio:

-Xmn

    設(shè)置新生代大小

-XX:NewRatio

    新生代(eden+2*s)和老年代(不包含永久區(qū))的比值

        例如:4,表示新生代:老年代=1:4,即新生代占整個(gè)堆的1/5

-XX:SurvivorRatio(幸存代)

    設(shè)置兩個(gè)Survivor區(qū)和eden的比值

        例如:8,表示兩個(gè)Survivor:eden=2:8,即一個(gè)Survivor占年輕代的1/10

 

現(xiàn)在運(yùn)行如下這段代碼:

復(fù)制代碼
public class JavaTest {    public static void main(String[] args) {        byte[] b = null;        for (int i = 0; i < 10; i++)            b = new byte[1 * 1024 * 1024];    }}復(fù)制代碼

我們通過設(shè)置不同的jvm參數(shù),來看一下GC日志的區(qū)別。

 

(1)當(dāng)參數(shù)設(shè)置為如下時(shí):(設(shè)置新生代為1M,很小)

-Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails 

運(yùn)行效果:

總結(jié):

  沒有觸發(fā)GC

    由于新生代的內(nèi)存比較小,所以全部分配在老年代。

 

(2)當(dāng)參數(shù)設(shè)置為如下時(shí):(設(shè)置新生代為15M,足夠大)

-Xmx20m -Xms20m -Xmn15m -XX:+PrintGCDetails

運(yùn)行效果:

上圖顯示:

沒有觸發(fā)GC

全部分配在eden(藍(lán)框所示)

老年代沒有使用(紅框所示)

 

(3)當(dāng)參數(shù)設(shè)置為如下時(shí):(設(shè)置新生代為7M,不大不小)

-Xmx20m -Xms20m –Xmn7m -XX:+PrintGCDetails

運(yùn)行效果:

總結(jié):

  進(jìn)行了2次新生代GC

  s0 s1 太小,需要老年代擔(dān)保

 

(4)當(dāng)參數(shù)設(shè)置為如下時(shí):(設(shè)置新生代為7M,不大不小;同時(shí),增加幸存代大小)

-Xmx20m -Xms20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails

運(yùn)行效果:

總結(jié):

    進(jìn)行了至少3次新生代GC

    s0 s1 增大

 

(5)當(dāng)參數(shù)設(shè)置為如下時(shí):

-Xmx20m -Xms20m -XX:NewRatio=1-XX:SurvivorRatio=2 -XX:+PrintGCDetails 

運(yùn)行效果:

 

 

(6)當(dāng)參數(shù)設(shè)置為如下時(shí): 和上面的(5)相比,適當(dāng)減小幸存代大小,這樣的話,能夠減少GC的次數(shù)

-Xmx20m -Xms20m -XX:NewRatio=1-XX:SurvivorRatio=3 -XX:+PrintGCDetails

 

 

3、-XX:+HeapDumpOnOutOfMemoryError、-XX:+HeapDumpPath

-XX:+HeapDumpOnOutOfMemoryError

    OOM時(shí)導(dǎo)出堆到文件

      根據(jù)這個(gè)文件,我們可以看到系統(tǒng)dump時(shí)發(fā)生了什么。

-XX:+HeapDumpPath

    導(dǎo)出OOM的路徑

例如我們?cè)O(shè)置如下的參數(shù):

-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump

上方意思是說,現(xiàn)在給堆內(nèi)存最多分配20M的空間。如果發(fā)生了OOM異常,那就把dump信息導(dǎo)出到d:/a.dump文件中。

然后,我們執(zhí)行如下代碼:

Vector v = new Vector();for (int i = 0; i < 25; i++)  v.add(new byte[1 * 1024 * 1024]);

上方代碼中,需要利用25M的空間,很顯然會(huì)發(fā)生OOM異常。現(xiàn)在我們運(yùn)行程序,控制臺(tái)打印如下:

現(xiàn)在我們?nèi)盤看一下dump文件:

8782a0ae-62fb-43a8-a5a6-1c5691e7fa59

上圖顯示,一般來說,這個(gè)文件的大小和最大堆的大小保持一致。

我們可以用VisualVM打開這個(gè)dump文件。

注:關(guān)于VisualVM的使用,可以參考下面這篇博客:

使用 VisualVM 進(jìn)行性能分析及調(diào)優(yōu):http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

或者使用Java自帶的Java VisualVM工具也行:

f9158d50-95d0-4732-942c-e872181fa530

f69bd0d2-a355-4a93-81c1-c3e71bce7509

上圖中就是dump出來的文件,文件中可以看到,一共有19個(gè)byte已經(jīng)被分配了。 

 

4、-XX:OnOutOfMemoryError:

-XX:OnOutOfMemoryError

    在OOM時(shí),執(zhí)行一個(gè)腳本。

      可以在OOM時(shí),發(fā)送郵件,甚至是重啟程序。

例如我們?cè)O(shè)置如下的參數(shù):

-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p //p代表的是當(dāng)前進(jìn)程的pid 

上方參數(shù)的意思是說,執(zhí)行printstack.bat腳本,而這個(gè)腳本做的事情是:D:/tools/jdk1.7_40/bin/jstack -F %1 > D:/a.txt,即當(dāng)程序OOM時(shí),在D:/a.txt中將會(huì)生成線程的dump。

5、堆的分配參數(shù)總結(jié):

根據(jù)實(shí)際事情調(diào)整新生代和幸存代的大小官方推薦新生代占堆的3/8幸存代占新生代的1/10在OOM時(shí),記得Dump出堆,確保可以排查現(xiàn)場(chǎng)問題

 

6、永久區(qū)分配參數(shù):

-XX:PermSize  -XX:MaxPermSize

    設(shè)置永久區(qū)的初始空間和最大空間。也就是說,jvm啟動(dòng)時(shí),永久區(qū)一開始就占用了PermSize大小的空間,如果空間還不夠,可以繼續(xù)擴(kuò)展,但是不能超過MaxPermSize,否則會(huì)OOM。

    他們表示,一個(gè)系統(tǒng)可以容納多少個(gè)類型

代碼舉例:

我們知道,使用CGLIB等庫的時(shí)候,可能會(huì)產(chǎn)生大量的類,這些類,有可能撐爆永久區(qū)導(dǎo)致OOM。于是,我們運(yùn)行下面這段代碼:

for(int i=0;i<100000;i++){  CglibBean bean = new CglibBean("geym.jvm.ch3.perm.bean"+i,new HashMap());}

上面這段代碼會(huì)在永久區(qū)不斷地產(chǎn)生新的類。于是,運(yùn)行效果如下:

fd7bcefb-d6d5-4fe0-8d77-9cddae2733fc

總結(jié):

  如果堆空間沒有用完也拋出了OOM,有可能是永久區(qū)導(dǎo)致的。

    堆空間實(shí)際占用非常少,但是永久區(qū)溢出 一樣拋出OOM。

 

三、棧的分配參數(shù):

1、Xss:

設(shè)置棧空間的大小。通常只有幾百K

  決定了函數(shù)調(diào)用的深度

  每個(gè)線程都有獨(dú)立的棧空間

  局部變量、參數(shù) 分配在棧上

注:棧空間是每個(gè)線程私有的區(qū)域。棧里面的主要內(nèi)容是棧幀,而棧幀存放的是局部變量表,局部變量表的內(nèi)容是:局部變量、參數(shù)。

我們來看下面這段代碼:(沒有出口的遞歸調(diào)用)

復(fù)制代碼
public class TestStackDeep {    private static int count = 0;    public static void recursion(long a, long b, long c) {        long e = 1, f = 2, g = 3, h = 4, i = 5, k = 6, q = 7, x = 8, y = 9, z = 10;        count++;        recursion(a, b, c);    }    public static void main(String args[]) {        try {            recursion(0L, 0L, 0L);        } catch (Throwable e) {            System.out.println("deep of calling = " + count);            e.printStackTrace();        }    }}復(fù)制代碼

上方這段代碼是沒有出口的遞歸調(diào)用,肯定會(huì)出現(xiàn)OOM的。

如果設(shè)置棧大小為128k:

-Xss128K 

運(yùn)行效果如下:(方法被調(diào)用了294次)

5c2b2060-e54a-4e7c-9a30-81567204d55b

如果設(shè)置棧大小為256k:(方法被調(diào)用748次)

7d6be7d6-b646-42bf-9357-1a3bccbb7a49

意味著函數(shù)調(diào)用的次數(shù)太深,例如遞歸調(diào)用。

 

總結(jié):

我們?cè)诒疚闹薪榻B了jvm的一些最基本的參數(shù),還有很多參數(shù)(如GC參數(shù)等)將在后續(xù)的系列文章中進(jìn)行介紹。我們將在接下來的文章中介紹GC算法。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 久久毛片免费观看 | 欧美精品欧美极品欧美激情 | 美国av片在线观看 | 日韩av在线网址 | 欧美激情综合在线 | 国产精品自拍片 | h色网站免费观看 | 曰韩一二三区 | 欧美精品亚洲人成在线观看 | 成人黄色小视频在线观看 | 色淫网站免费视频 | 国产成年人小视频 | 成人毛片av在线 | 看a级毛片 | 成年人黄色片视频 | 成人一级黄色大片 | 日韩精品a在线观看 | 特级黄毛片 | 97精品国产高清在线看入口 | 国产精品免费久久久久久 | 成人三级在线播放 | 欧美极品欧美精品欧美视频 | 日本成人一区二区 | 成人啪啪色婷婷久 | 日本免费一区二区三区四区 | 一级空姐毛片 | 日韩黄在线观看 | 毛片在哪看 | 超碰97最新 | 黄色网战入口 | 国产超碰人人做人人爱 | 精品久久久久久综合日本 | 国产一有一级毛片视频 | 久久综合给合久久狠狠狠97色69 | 一本一本久久a久久精品综合小说 | 538在线精品 | 国产一区二区三区视频在线观看 | 国产一国产一级毛片视频 | 中午日产幕无线码1区 | 国产一级做a爱片在线看免 2019天天干夜夜操 | 亚洲xxx在线观看 |