JVM學習(1)——經過實例總結Java虛擬機的運行機制

俗話說,本身寫的代碼,6個月後也是別人的代碼……複習!複習!複習!涉及到的知識點總結以下:java

  • JVM的歷史
  • JVM的運行流程簡介
  • JVM的組成(基於 Java 7)
  • JVM調優參數:-Xmx和-Xms
  • 逃逸分析(DoEscapeAnalysis )的概念——JVM棧上分配實驗
  • JVM中client模式(-client)和server模式(-server)的區別
  • 查看GC日誌的方法
  • 使用idea對JVM進行參數輸入
  • Java棧,Java堆和方法區的交互原理
  • 爲了能讓遞歸方法調用的次數更多一些,應該怎麼作?c++


 

  當今——截止本文總結以前, 使用最爲普遍的 JVM 爲 HotSpot(HotSpot 爲Longview Technologies開發,被SUN收購),而  JVM 本質上是使用 軟件來模擬 Java 的字節碼的指令集 ,類比  VMWare,Visual Box……他們都是使用軟件去模擬物理CPU的指令集
  所謂讀史令人明智,先簡單回顧和了解下 JVM 與 Java 的發展史
  1. 1996年 SUN JDK 1.0 Classic VM——純解釋運行,使用外掛進行JIT
  2. 1997年 JDK1.1 發佈——AWT、內部類、JDBC、RMI、反射
  3. 1998年 JDK1.2 Solaris Exact VM
    1. JIT 解釋器 混合
    2. Accurate Memory Management 精確內存管理,數據類型敏感
    3. 提高 GC 性能
    4. JDK1.2開始稱爲Java 2,致使了J2SE J2EE J2ME 的出現
    5. 加入Swing Collections
  4. 2000年 JDK 1.3 Hotspot (HotSpot 爲Longview Technologies開發 被SUN收購)做爲默認虛擬機發布——加入JavaSound API
  5. 2002年 JDK 1.4 Classic VM退出歷史舞臺(1996年推出的 Classic VM 到2002年出 JDK 1.4 方纔退出)——Assert、正則表達式、NIO、IPV六、日誌API、加密類庫……
  6. 2004年 JDK1.5 即 JDK5 、J2SE 5 、Java 5 發佈了(很重要的一版),是Java語言的發展史上的又一里程碑事件。爲了表示這個版本的重要性,JDK 1.5 改名爲 5.0 
    1. 泛型
    2. 註解
    3. 裝箱
    4. 枚舉
    5. 可變長參數
    6. Foreach
  7. 2005年 Java SE 六、JDK 1.六、JDK 6 發佈,JavaOne 大會召開,SUN 公司公開 Java SE 6 此時 Java 的各類版本已經改名以取消其中的數字「2」——J2EE改名爲Java EE, J2SE改名爲Java SE,J2ME改名爲Java ME。
    1. 腳本語言支持
    2. JDBC 4.0
    3. Java編譯器 API
  8. 2006年11月13日,SUN 公司宣佈 Java 全線採納 GNU General Public License Version 2,從而公開了 Java 的源代碼,並創建OpenJDK——HotSpot 成爲Sun JDK 和 OpenJDK 中所帶的虛擬機。
  9. 2008 年 Oracle 收購 BEA——獲得JRockit VM
  10. 2010 年 Oracle 收購 Sun——獲得HotspotOracle 宣佈在 JDK 8 時整合 JRockit 和 Hotspot,優點互補,在Hotspot基礎上,移植JRockit優秀特性。
  11. 2011年 JDK 7 發佈,延誤項目推到JDK 8
    1. G1
    2. 動態語言加強
    3. 64位系統中的壓縮指針
    4. NIO 2.0
  12. 2014年 JDK 8 發佈
    1. Lambda 表達式
    2. 語法加強
    3. Java類型註解
  13. 2016年 JDK 9 發佈——模塊化

 


 

 

  Java的兩大基石:Java 語言規範和 JVM 規範正則表達式

  Java 語言規範:規定了語法、變量、類型、文法, Java 語言規範定義了什麼是Java語言
  JVM 規範:規範了 Class 文件類型、運行時數據、幀棧、虛擬機的啓動、虛擬機的指令集, JVM規範 主要定義二進制 class文件和 JVM指令集等且須要明確的問題是  Java語言和JVM相對獨立,不論何種語言,但凡符合了JVM規範,那麼均可以在JVM上運行,好比:
  • –Groovy
  • –Clojure
  • Scala

  


 

  JVM的啓動過程是怎樣的?算法

  也就是說JVM是如何一步步的找到main方法的……簡單總結下,Java虛擬機啓動的過程:編程

  1. 首先使用 Java 命令啓動JVM
  2. 其次進行JVM配置的裝載——根據當前路徑和系統的版本去尋找jvm.cfg文件,裝載配置
  3. 以後會根據加載的配置去尋找JVM.dll文件——JVM的主要實現文件。
  4. 再後,經過該文件去初始化JVM並得到相關的接口,好比JNIEnv接口,經過該接口實現findClass操做。
  5. 最後,經過相關接口(JNIEnv……),找到程序裏的main方法,便可進入程序……

  如圖:windows

 


 

  介紹一下 JVM 的基本結構,並說出各個模塊的功能?服務器

  能夠結合這個網絡上經典的 JVM 結構圖來理解 JVM,當總結完畢,再畫一個更加詳細的結構圖(jdk 7 規範的 JVM):網絡

  首先,要知道JVM有一個類加載系統(否則咱們的類無法執行),也就是傳說中的ClassLoader……Class文件(Java編譯以後的)經過類加載器被加載到JVM中,而JVM的內存空間是分區的,主要有如圖所示幾個區:數據結構

  • 方法區
  • Java 堆
  • Java 棧
  • 本地方法棧(也就是native方法調用)

  而類比物理cpu,JVM也須要一個指針來指向下一條指令的地址,就是圖中的PC寄存器,緊接着是執行引擎,用來執行字節碼,固然還有一個很重要的模塊——GC(垃圾回收器)。下面單獨總結下各個主要模塊:jvm

  • PC寄存器
  Java程序裏 每一個線程都擁有一個PC寄存器,線程私有的。每當線程啓動時PC寄存器就建立了,它是一個指針, 老是用來指向下一條指令的地址,讓程序知道下一步須要作啥,且執行本地方法時,PC的值爲undefined(未定義)
  • 方法區
   保存JVM裝載的類的信息,好比類型的常量池、類中的字段,類中的方法信息、方法的字節碼(bytecode)等, 注意這不是絕對的!!!好比:JDK 6 時,String等字符串常量的信息是置於方法區中的,可是到了JDK 7 時,已經移動到了Java堆。因此,方法區也好,Java堆也罷,到底詳細的保存了什麼,其實沒有具體定論,要結合不一樣的JVM版原本分析,由於技術是發展的! 不過通常認爲,方法區就是保存了JVM裝載的類的信息。一般方法區和永久區(Perm)關聯在一塊兒,永久區是JVM裏很常見的一個概念,它保存了相對來講比較穩定的數據……以後再總結。
  • Java堆
  Java堆是和程序開發密切相關的一塊內存區間,能夠說, 應用系統的對象都保存在Java堆中,全部線程共享Java堆,也就是說Java堆是全局共享的,從GC角度看,對使用了分代算法的GC來講,必須堆也是對應分代的,由於 Java堆是GC的主要工做區間……好比:以下圖,分代的堆:
  首先有個伊甸園(eden代)——是對象出生的地方,還有s0,s1使用複製算法……之後詳細總結。最後還有一個老年代tenured(長期佔有的,終身的)——年齡比較大的對象。
  • Java棧
  Java棧和Java堆是徹底不同的,上面說Java堆是全局共享(all線程訪問)的,而 Java棧是線程私有的,Java棧由一系列的幀組成( 所以Java棧也叫作幀棧),棧衆所周知是先進後出(FILO)的數據結構,Java棧也不例外, Java棧中的每一個幀都保存一個方法調用的局部變量、操做數棧、指向常量池的指針等,且每一次方法調用都會建立一個幀,並壓棧
  下面首先分析下 Java棧裏很重要的一個概念——局部變量表,該表不只僅只是方法裏的局部變量,而是更加寬泛的包含了方法的參數以及局部變量,當方法調用時,會在Java棧裏建立一個幀,幀裏的局部變量表保存了方法的參數和局部變量。以下一個靜態方法
1 public class Demo {
2     public static int doStaticMethod(int i, long l, float f, Object o, byte b) {
3         return 0;
4     }
5 }
View Code

  編譯以後的具有變量表字節碼以下:

1     LOCALVARIABLE i I L0 L1 0
2     LOCALVARIABLE l J L0 L1 1
3     LOCALVARIABLE f F L0 L1 3
4     LOCALVARIABLE o Ljava/lang/Object; L0 L1 4
5     LOCALVARIABLE b B L0 L1 5
6     MAXSTACK = 1
7     MAXLOCALS = 6

  能夠認爲Java棧幀裏的局部變量表有不少的槽位組成,每一個槽最大能夠容納32位的數據類型,故方法參數裏的int i 參數佔據了一個槽位,而long l 參數就佔據了兩個槽(1和2),Object對象類型的參數實際上是一個引用,o至關於一個指針,也就是32位大小。byte類型升爲int,也是32位大小。以下:

  相對再看看實例方法:

    public int doInstanceMethod(char c, short s, boolean b) {
        return 0;
    }
View Code

  編譯以後的具有變量表字節碼以下:

1    L1
2     LOCALVARIABLE this LDemo; L0 L1 0
3     LOCALVARIABLE c C L0 L1 1
4     LOCALVARIABLE s S L0 L1 2
5     LOCALVARIABLE b Z L0 L1 3
6     MAXSTACK = 1
7     MAXLOCALS = 4

  實例方法的局部變量表和靜態方法基本同樣,惟一區別就是實例方法在Java棧幀的局部變量表裏第一個槽位(0位置)存的是一個this引用(當前對象的引用),後面就和靜態方法的同樣了。

  再看,Java棧裏的方法調用組成幀棧的過程:

1     public static int doStaticMethod(int i, long l, float f, Object o, byte b) {
2         return doStaticMethod(i, l, f, o, b);
3     }
View Code

  如上一個遞歸調用(棧的內存溢出),當類中方法(靜態 or 實例)調用的時候,就會在Java棧裏建立一個幀,每一次調用都會產生一個幀,並持續的壓入棧頂……一直到Java棧滿了,就發生了溢出!或者方法調用結束了,那麼對應的Java棧幀就被移除。

  注意,一個Java棧幀裏除了保存局部變量表外,還會保存操做數棧返回地址等信息。順勢我在分析下Java棧幀裏的操做數棧,理解Java棧幀裏的操做數棧前先知道一個結論——由於Java沒有寄存器,故全部參數傳遞使用Java棧幀裏的操做數棧。

   看一個例子:

  注意,對於局部變量表的槽位,按照從0開始的順序,依次是方法參數,以後是方法內的局部變量,局部變量0就是a,1就是b,2就是c…… 編譯以後的字節碼爲:

  // access flags 0x9
  public static add(II)I
   L0
    LINENUMBER 18 L0 // 對應源代碼第18行,以此類推
    ICONST_0 // 把常量0 push 到Java棧幀的操做數棧裏
    ISTORE 2 // 將0從操做數棧pop到局部變量表槽2裏(c),完成賦值
   L1
    LINENUMBER 19 L1
    ILOAD 0 // 將局部變量槽位0(a)push 到Java棧幀的操做數棧裏
    ILOAD 1 // 把局部變量槽1(b)push到操做數棧  
    IADD // pop出a和b兩個變量,求和,把結果push到操做數棧
    ISTORE 2 // 把結果從操做數棧pop到局部變量2(a+b的和給c賦值)
   L2
    LINENUMBER 21 L2
    ILOAD 2 // 局部變量2(c)push 到操做數棧
    IRETURN // 返回結果
   L3
    LOCALVARIABLE a I L0 L3 0
    LOCALVARIABLE b I L0 L3 1
    LOCALVARIABLE c I L1 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3

  發現,整個計算過程的參數傳遞和操做數棧密切相關!如圖:


 

  繼續總結,區分Java堆上分配內存和棧上分配內存

  回憶c++語言,以下代碼:

    public void test() {
        Demo *demo = new Demo();
        // ......
        delete demo;
    }
View Code

new出的對象是在堆中分配內存,每次使用完畢,必須記得手動回收該內存區域,使用了delete運算符,若是一旦這樣的分配多了,那麼極可能忘記刪除,就可能會發生內存泄漏問題,一旦發生就很難發現和解決。若是是這樣:

    public void test() {
        Demo demo;// 使用c++的引用,直接聲明一個對象引用,對對象進行操做,操做完畢,不須要咱們手動釋放內存
    }
View Code

此時就叫在棧中分配,棧上分配,函數調用完成自動清理內存,不會發生內存泄漏。而堆上分配,每次須要清理空間。

  相似的原理,在Java中:

 1 public class OnStackTest {
 2     /**
 3      * alloc方法內分配了兩個字節的內存空間
 4      */
 5     public static void alloc(){
 6         byte[] b = new byte[2];
 7         b[0] = 1;
 8     }
 9 
10     public static void main(String[] args) {
11         long b = System.currentTimeMillis();
12 
13         // 分配 100000000 個 alloc 分配的內存空間
14         for(int i = 0; i < 100000000; i++){
15             alloc();
16         }
17 
18         long e = System.currentTimeMillis();
19         System.out.println(e - b);
20     }
21 }
View Code

alloc方法內的b(new)分配的內存按照以前理論,我開始認爲是分到了Java堆,那麼若是系統的內存空間不夠,是否是會發生內存泄漏?!下面作一個實驗來驗證。

  再實驗以前先總結幾個JVM調優的參數和一些須要使用的概念:

  • -XX:功能開關
  • -Xms:minimum memory size for pile and heap
  • -Xmx:maximum memory size for pile and heap
  • 打印GC日誌——我還須要使用JVM的一個查看GC日誌的參數:-XX:+PrintGC(當GC發生時打印信息)
  • JVM的server模式和client模式
  • 逃逸分析

  舉例:對JVM堆內存進行基本的配置可使用哪一個命令參數?

  -Xms 10m,表示JVM Heap(堆內存)最小尺寸10MB,最開始只有 -Xms 的參數,表示 `初始` memory size(m表示memory,s表示size),屬於初始分配10m,-Xms表示的 `初始` 內存也有一個 `最小` 內存的概念(其實經常使用的作法中初始內存採用的也就是最小內存)。

  -Xmx 10m,表示JVM Heap(堆內存)最大容許的尺寸10MB,按需分配。若是 -Xmx 不指定或者指定偏小,也許出現java.lang.OutOfMemory錯誤,此錯誤來自JVM不是Throwable的,沒法用try...catch捕捉。

 


 

  JVM的server模式和client模式的區別是什麼?

  -client,-server 兩個參數能夠設置JVM使用何種運行模式,client模式啓動較快,但運行性能和內存管理效率不如server模式,一般用於客戶端程序。相反server模式啓動比client慢,但可得到更高的運行性能,經常使用語服務器程序。

  windows上,缺省的虛擬機類型爲client模式使用java -verson命令查看),若是要使用server模式,就須要在啓動虛擬機時加-server參數,以得到更高性能,對服務器端應用,推薦採用server模式,尤爲是多個CPU的系統。

  在Linux,Solaris上缺省採用server模式。

  官方這樣介紹:JVM Server模式與client模式啓動,最主要的差異在於:-Server模式啓動時,速度較慢,可是一旦運行起來後,性能將會有很大的提高。JVM工做在Server模式能夠大大提升性能,但應用的啓動會比client模式慢大概10%。當該參數不指定時,虛擬機啓動檢測主機是否爲服務器,若是是,則以Server模式啓動,不然以client模式啓動,Java 5.0檢測的根據是至少2個CPU和最低2GB內存。

  綜上,當JVM用於啓動GUI界面的交互應用時適合於使用client模式,當JVM用於運行服務器後臺程序時建議用Server模式。

  JVM在client模式默認-Xms是1M,-Xmx是64M;

  JVM在Server模式默認-Xms是128M,-Xmx是1024M。能夠經過運行:java -version來查看jvm默認工做在什麼模式。

 


 

  什麼是JVM 的逃逸分析(Escape Analysis)?

  所謂逃逸分析,是JVM的一種內存分配的優化方式,一些參考書上這樣寫到:在編程語言的編譯優化原理中,分析指針動態範圍的方法稱之爲逃逸分析。通俗一點講,就是當一個對象的指針被多個方法或線程引用時,咱們稱這個指針發生了逃逸。而用來分析這種逃逸現象的方法,就稱之爲逃逸分析。

  咱們知道java對象是在堆裏分配的,在Java棧幀中,只保存了對象的指針。當對象再也不使用後,須要依靠GC來遍歷引用樹並回收內存,若是對象數量較多,將給GC帶來較大壓力,也間接影響了應用的性能。減小臨時對象在堆內分配的數量,無疑是最有效的優化方法,接下來,舉一個場景來闡述。

  假設在方法體內,聲明瞭一個局部變量,且該變量在方法執行生命週期內未發生逃逸(在方法體內,未將引用暴露給外面)。按照JVM內存分配機制,首先會在堆裏建立變量類的實例,而後將返回的對象指針壓入調用棧,繼續執行。這是優化前,JVM的處理方式。

  逃逸分析優化 – 棧上分配,優化原理:JVM分析找到未逃逸的變量(在方法體內,未將引用暴露給外面),將變量類的實例化內存直接在棧裏分配(無需進入堆),分配完成後,繼續在調用棧內執行,最後線程結束,棧空間被回收,局部變量也被回收。這是優化後的處理方式,對比能夠看出,主要區別在棧空間直接做爲臨時對象的存儲介質。從而減小了臨時對象在堆內的分配數量。

  以下例子是發生了逃逸的局部對象變量:

 1 class A {
 2     public static B b;  
 3 
 4     // 給全局變量賦值,發生逃逸
 5     public void globalVariablePointerEscape() { 
 6         b = new B();
 7     }  
 8 
 9      // 方法返回值,發生逃逸
10     public B methodPointerEscape() {
11         return new B();
12     }  
13 
14     // 實例引用傳遞,發生逃逸
15     public void instancePassPointerEscape() {
16         methodPointerEscape().printClassName(this); 
17     }
18 }  
19 
20 class B {
21     public void printClassName(A a) {
22         System.out.println(a.class.getName());
23     }
View Code

  記住一個結論:啓用逃逸分析的運行性能6倍於未啓用逃逸分析的程序。逃逸分析是JVM層面的工做,JVM作了逃逸分析,這樣沒有逃逸的對象就能夠被優化,從而減小堆的大小並減小GC。若是JVM沒有加逃逸分析,就算本身優化了代碼,也不會有效果。

  JVM中啓用逃逸分析須要安裝jdk1.6.0_14+版本,運行java時傳遞jvm參數  -XX:+DoEscapeAnalysis,取消逃逸分析把+改成-。

  


 

  下面回到以前的實驗代碼,以下:

 1 public class OnStackTest {
 2     /**
 3      * alloc方法內分配了兩個字節的內存空間
 4      */
 5     public static void alloc(){
 6         byte[] b = new byte[2];
 7         b[0] = 1;
 8     }
 9 
10     public static void main(String[] args) {
11         long b = System.currentTimeMillis();
12 
13         // 分配 100000000 個 alloc 分配的內存空間
14         for(int i = 0; i < 100000000; i++){
15             alloc();
16         }
17 
18         long e = System.currentTimeMillis();
19         System.out.println(e - b);
20     }
21 }
View Code

  我啓用逃逸分析(能夠看出b引用的對象沒有逃逸),並設置在服務端模式下運行程序(性能較高),修改JVM堆內存最小(初始化)爲10m,最大可用也爲10m,且打印GC做爲實驗結果。以下在idea設置JVM參數:

  進入菜單以後,在以下地方填寫JVM參數,在JVM啓動時,傳遞給jvm

  運行結果:

[GC (Allocation Failure) 2816K->727K(9984K), 0.0049897 secs]
23

Process finished with exit code 0


 

  得知,運行了23ms,沒有GC發生。做爲對比,我不用任何參數配置,也不進行逃逸分析,且本機在win下,默認是客戶端模式運行程序以下結果:

  發現運行了1285ms!間接的證實了以前的理論是有效果的。


 

  再進行實驗,只是取消逃逸分析,其餘不變,以下:

  運行結果:(數據不少……)

  1 [GC (Allocation Failure)  2816K->726K(9984K), 0.0331335 secs]
  2 [GC (Allocation Failure)  3542K->742K(9984K), 0.0005698 secs]
  3 [GC (Allocation Failure)  3558K->734K(9984K), 0.0016077 secs]
  4 [GC (Allocation Failure)  3550K->798K(9984K), 0.0004902 secs]
  5 [GC (Allocation Failure)  3614K->798K(9984K), 0.0003673 secs]
  6 [GC (Allocation Failure)  3614K->798K(8960K), 0.0003434 secs]
  7 [GC (Allocation Failure)  2590K->826K(9472K), 0.0003698 secs]
  8 [GC (Allocation Failure)  2618K->834K(9472K), 0.0001611 secs]
  9 [GC (Allocation Failure)  2626K->842K(9472K), 0.0002289 secs]
 10 [GC (Allocation Failure)  2634K->830K(9472K), 0.0004765 secs]
 11 [GC (Allocation Failure)  2622K->838K(9472K), 0.0001281 secs]
 12 [GC (Allocation Failure)  2630K->842K(9472K), 0.0002448 secs]
 13 [GC (Allocation Failure)  2634K->830K(9472K), 0.0004815 secs]
 14 [GC (Allocation Failure)  2622K->862K(9472K), 0.0001148 secs]
 15 [GC (Allocation Failure)  2654K->870K(9472K), 0.0001238 secs]
 16 [GC (Allocation Failure)  2662K->846K(9472K), 0.0004488 secs]
 17 [GC (Allocation Failure)  2638K->846K(9472K), 0.0001138 secs]
 18 [GC (Allocation Failure)  2638K->846K(9728K), 0.0001107 secs]
 19 [GC (Allocation Failure)  2894K->846K(9472K), 0.0001126 secs]
 20 [GC (Allocation Failure)  2894K->846K(9728K), 0.0001760 secs]
 21 [GC (Allocation Failure)  3150K->846K(9728K), 0.0002964 secs]
 22 [GC (Allocation Failure)  3150K->846K(9728K), 0.0087972 secs]
 23 [GC (Allocation Failure)  3150K->846K(9728K), 0.0003353 secs]
 24 [GC (Allocation Failure)  3150K->846K(9728K), 0.0002302 secs]
 25 [GC (Allocation Failure)  3150K->846K(9728K), 0.0001739 secs]
 26 [GC (Allocation Failure)  3150K->846K(9728K), 0.0242303 secs]
 27 [GC (Allocation Failure)  3150K->846K(9728K), 0.0002367 secs]
 28 [GC (Allocation Failure)  3150K->846K(9728K), 0.0006995 secs]
 29 [GC (Allocation Failure)  3150K->846K(9728K), 0.0004961 secs]
 30 [GC (Allocation Failure)  3150K->846K(9984K), 0.0003110 secs]
 31 [GC (Allocation Failure)  3406K->846K(9728K), 0.0001449 secs]
 32 [GC (Allocation Failure)  3406K->846K(9984K), 0.0008167 secs]
 33 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003906 secs]
 34 [GC (Allocation Failure)  3662K->846K(9984K), 0.0013368 secs]
 35 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002305 secs]
 36 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001524 secs]
 37 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001204 secs]
 38 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002497 secs]
 39 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003225 secs]
 40 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001652 secs]
 41 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005384 secs]
 42 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001642 secs]
 43 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001477 secs]
 44 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001524 secs]
 45 [GC (Allocation Failure)  3662K->846K(9984K), 0.0307698 secs]
 46 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002871 secs]
 47 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002777 secs]
 48 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004491 secs]
 49 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001592 secs]
 50 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002547 secs]
 51 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001779 secs]
 52 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001729 secs]
 53 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002858 secs]
 54 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002815 secs]
 55 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005290 secs]
 56 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001300 secs]
 57 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009583 secs]
 58 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010292 secs]
 59 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004983 secs]
 60 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001568 secs]
 61 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001518 secs]
 62 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001496 secs]
 63 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002003 secs]
 64 [GC (Allocation Failure)  3662K->846K(9984K), 0.0012879 secs]
 65 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001667 secs]
 66 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001536 secs]
 67 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001493 secs]
 68 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003064 secs]
 69 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009474 secs]
 70 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003213 secs]
 71 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001571 secs]
 72 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006827 secs]
 73 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002308 secs]
 74 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003011 secs]
 75 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002933 secs]
 76 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001437 secs]
 77 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001219 secs]
 78 [GC (Allocation Failure)  3662K->846K(9984K), 0.0031484 secs]
 79 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009044 secs]
 80 [GC (Allocation Failure)  3662K->846K(9984K), 0.0015364 secs]
 81 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001592 secs]
 82 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001536 secs]
 83 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003567 secs]
 84 [GC (Allocation Failure)  3662K->846K(9984K), 0.0034899 secs]
 85 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007984 secs]
 86 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002221 secs]
 87 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001512 secs]
 88 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001900 secs]
 89 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010519 secs]
 90 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006379 secs]
 91 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001596 secs]
 92 [GC (Allocation Failure)  3662K->846K(9984K), 0.0028863 secs]
 93 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009128 secs]
 94 [GC (Allocation Failure)  3662K->846K(9984K), 0.0018132 secs]
 95 [GC (Allocation Failure)  3662K->846K(9984K), 0.0014058 secs]
 96 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003375 secs]
 97 [GC (Allocation Failure)  3662K->846K(9984K), 0.0242166 secs]
 98 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003141 secs]
 99 [GC (Allocation Failure)  3662K->846K(9984K), 0.0014105 secs]
100 [GC (Allocation Failure)  3662K->846K(9984K), 0.0036604 secs]
101 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001819 secs]
102 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003639 secs]
103 [GC (Allocation Failure)  3662K->846K(9984K), 0.0388277 secs]
104 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002578 secs]
105 [GC (Allocation Failure)  3662K->846K(9984K), 0.0422050 secs]
106 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002790 secs]
107 [GC (Allocation Failure)  3662K->846K(9984K), 0.0216289 secs]
108 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003148 secs]
109 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004597 secs]
110 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002221 secs]
111 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010382 secs]
112 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005007 secs]
113 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002096 secs]
114 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002174 secs]
115 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001847 secs]
116 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001456 secs]
117 [GC (Allocation Failure)  3662K->846K(9984K), 0.0016282 secs]
118 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002905 secs]
119 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001860 secs]
120 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001527 secs]
121 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006133 secs]
122 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006961 secs]
123 [GC (Allocation Failure)  3662K->846K(9984K), 0.0116160 secs]
124 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001832 secs]
125 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010460 secs]
126 [GC (Allocation Failure)  3662K->846K(9984K), 0.0019464 secs]
127 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001508 secs]
128 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001387 secs]
129 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002112 secs]
130 [GC (Allocation Failure)  3662K->846K(9984K), 0.0015038 secs]
131 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002211 secs]
132 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001723 secs]
133 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001568 secs]
134 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002609 secs]
135 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002124 secs]
136 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001418 secs]
137 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001459 secs]
138 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001437 secs]
139 [GC (Allocation Failure)  3662K->846K(9984K), 0.0026791 secs]
140 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001888 secs]
141 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001549 secs]
142 [GC (Allocation Failure)  3662K->846K(9984K), 0.0015837 secs]
143 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007751 secs]
144 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001720 secs]
145 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002445 secs]
146 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006690 secs]
147 [GC (Allocation Failure)  3662K->846K(9984K), 0.0022680 secs]
148 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002034 secs]
149 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003042 secs]
150 [GC (Allocation Failure)  3662K->846K(9984K), 0.0023358 secs]
151 [GC (Allocation Failure)  3662K->846K(9984K), 0.0261819 secs]
152 [GC (Allocation Failure)  3662K->846K(9984K), 0.0562080 secs]
153 [GC (Allocation Failure)  3662K->846K(9984K), 0.0038828 secs]
154 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002578 secs]
155 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001667 secs]
156 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001257 secs]
157 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006065 secs]
158 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001816 secs]
159 [GC (Allocation Failure)  3662K->846K(9984K), 0.0098407 secs]
160 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008547 secs]
161 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002445 secs]
162 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002227 secs]
163 [GC (Allocation Failure)  3662K->846K(9984K), 0.0312876 secs]
164 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001739 secs]
165 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002389 secs]
166 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001493 secs]
167 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001524 secs]
168 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001452 secs]
169 [GC (Allocation Failure)  3662K->846K(9984K), 0.0016608 secs]
170 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002037 secs]
171 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001512 secs]
172 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001605 secs]
173 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001328 secs]
174 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004706 secs]
175 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002118 secs]
176 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001505 secs]
177 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003088 secs]
178 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001499 secs]
179 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001440 secs]
180 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001465 secs]
181 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002040 secs]
182 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008777 secs]
183 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003480 secs]
184 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002606 secs]
185 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001546 secs]
186 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001521 secs]
187 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001568 secs]
188 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004861 secs]
189 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001561 secs]
190 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001412 secs]
191 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002622 secs]
192 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002087 secs]
193 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006870 secs]
194 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001602 secs]
195 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001844 secs]
196 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002348 secs]
197 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001477 secs]
198 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001480 secs]
199 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006174 secs]
200 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001555 secs]
201 [GC (Allocation Failure)  3662K->846K(9984K), 0.0020238 secs]
202 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004790 secs]
203 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001577 secs]
204 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001515 secs]
205 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008786 secs]
206 [GC (Allocation Failure)  3662K->846K(9984K), 0.0011626 secs]
207 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004457 secs]
208 [GC (Allocation Failure)  3662K->846K(9984K), 0.0023560 secs]
209 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001683 secs]
210 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001540 secs]
211 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003378 secs]
212 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001480 secs]
213 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001456 secs]
214 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001745 secs]
215 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001443 secs]
216 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001409 secs]
217 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004668 secs]
218 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008223 secs]
219 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004224 secs]
220 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001617 secs]
221 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001782 secs]
222 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003191 secs]
223 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002367 secs]
224 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001452 secs]
225 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001409 secs]
226 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001462 secs]
227 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002852 secs]
228 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001496 secs]
229 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001437 secs]
230 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008024 secs]
231 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007720 secs]
232 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001608 secs]
233 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001515 secs]
234 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001434 secs]
235 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001502 secs]
236 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001428 secs]
237 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004314 secs]
238 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003427 secs]
239 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001418 secs]
240 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
241 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001216 secs]
242 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
243 [GC (Allocation Failure)  3662K->846K(9984K), 0.0025109 secs]
244 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001704 secs]
245 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001897 secs]
246 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001611 secs]
247 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001527 secs]
248 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001480 secs]
249 [GC (Allocation Failure)  3662K->846K(9984K), 0.0037686 secs]
250 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001624 secs]
251 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005269 secs]
252 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002270 secs]
253 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009918 secs]
254 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006550 secs]
255 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003197 secs]
256 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003328 secs]
257 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002861 secs]
258 [GC (Allocation Failure)  3662K->846K(9984K), 0.0414909 secs]
259 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001748 secs]
260 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001617 secs]
261 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001244 secs]
262 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002342 secs]
263 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002308 secs]
264 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
265 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001505 secs]
266 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001530 secs]
267 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
268 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002606 secs]
269 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001540 secs]
270 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001801 secs]
271 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002292 secs]
272 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001633 secs]
273 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001521 secs]
274 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001496 secs]
275 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007707 secs]
276 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003502 secs]
277 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001596 secs]
278 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001490 secs]
279 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007953 secs]
280 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001611 secs]
281 [GC (Allocation Failure)  3662K->846K(9984K), 0.0021666 secs]
282 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006077 secs]
283 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002563 secs]
284 [GC (Allocation Failure)  3662K->846K(9984K), 0.0026175 secs]
285 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001683 secs]
286 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001555 secs]
287 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010453 secs]
288 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003885 secs]
289 [GC (Allocation Failure)  3662K->846K(9984K), 0.0039067 secs]
290 [GC (Allocation Failure)  3662K->846K(9984K), 0.0014680 secs]
291 [GC (Allocation Failure)  3662K->846K(9984K), 0.0022773 secs]
292 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001661 secs]
293 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003710 secs]
294 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007968 secs]
295 [GC (Allocation Failure)  3662K->846K(9984K), 0.0080853 secs]
296 [GC (Allocation Failure)  3662K->846K(9984K), 0.0025979 secs]
297 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002874 secs]
298 [GC (Allocation Failure)  3662K->846K(9984K), 0.0540315 secs]
299 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001829 secs]
300 [GC (Allocation Failure)  3662K->846K(9984K), 0.0019299 secs]
301 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007213 secs]
302 [GC (Allocation Failure)  3662K->846K(9984K), 0.0078775 secs]
303 [GC (Allocation Failure)  3662K->846K(9984K), 0.0250296 secs]
304 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001785 secs]
305 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001680 secs]
306 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001639 secs]
307 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001642 secs]
308 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001611 secs]
309 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001210 secs]
310 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001543 secs]
311 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001434 secs]
312 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001639 secs]
313 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002606 secs]
314 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001465 secs]
315 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001291 secs]
316 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001151 secs]
317 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002186 secs]
318 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006012 secs]
319 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007088 secs]
320 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004672 secs]
321 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005147 secs]
322 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002700 secs]
323 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003088 secs]
324 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003070 secs]
325 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005085 secs]
326 [GC (Allocation Failure)  3662K->846K(9984K), 0.0052988 secs]
327 [GC (Allocation Failure)  3662K->846K(9984K), 0.0068434 secs]
328 [GC (Allocation Failure)  3662K->846K(9984K), 0.0176566 secs]
329 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003431 secs]
330 [GC (Allocation Failure)  3662K->846K(9984K), 0.0307346 secs]
331 [GC (Allocation Failure)  3662K->846K(9984K), 0.0137013 secs]
332 [GC (Allocation Failure)  3662K->846K(9984K), 0.0027712 secs]
333 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003462 secs]
334 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004687 secs]
335 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010341 secs]
336 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002821 secs]
337 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006945 secs]
338 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002513 secs]
339 [GC (Allocation Failure)  3662K->846K(9984K), 0.0057389 secs]
340 [GC (Allocation Failure)  3662K->846K(9984K), 0.0011175 secs]
341 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001717 secs]
342 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001536 secs]
343 [GC (Allocation Failure)  3662K->846K(9984K), 0.0145414 secs]
344 [GC (Allocation Failure)  3662K->846K(9984K), 0.0160925 secs]
345 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009216 secs]
346 [GC (Allocation Failure)  3662K->846K(9984K), 0.0159631 secs]
347 [GC (Allocation Failure)  3662K->846K(9984K), 0.0290430 secs]
348 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001788 secs]
349 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001707 secs]
350 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003807 secs]
351 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001767 secs]
352 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006457 secs]
353 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005219 secs]
354 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003151 secs]
355 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002469 secs]
356 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002964 secs]
357 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003092 secs]
358 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002342 secs]
359 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002255 secs]
360 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001795 secs]
361 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002246 secs]
362 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002840 secs]
363 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001692 secs]
364 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005001 secs]
365 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001266 secs]
366 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007371 secs]
367 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002656 secs]
368 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001250 secs]
369 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001465 secs]
370 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001471 secs]
371 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001306 secs]
372 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001340 secs]
373 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002625 secs]
374 [GC (Allocation Failure)  3662K->846K(9984K), 0.0033540 secs]
375 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001652 secs]
376 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001586 secs]
377 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001266 secs]
378 [GC (Allocation Failure)  3662K->846K(9984K), 0.0022947 secs]
379 [GC (Allocation Failure)  3662K->846K(9984K), 0.0024166 secs]
380 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001583 secs]
381 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001515 secs]
382 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
383 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003387 secs]
384 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001925 secs]
385 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002429 secs]
386 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001480 secs]
387 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001459 secs]
388 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006382 secs]
389 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002899 secs]
390 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001543 secs]
391 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001608 secs]
392 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002644 secs]
393 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003546 secs]
394 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002445 secs]
395 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001490 secs]
396 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
397 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002351 secs]
398 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001574 secs]
399 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002445 secs]
400 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001431 secs]
401 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001462 secs]
402 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001477 secs]
403 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002933 secs]
404 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002743 secs]
405 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001602 secs]
406 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001521 secs]
407 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005987 secs]
408 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002115 secs]
409 [GC (Allocation Failure)  3662K->846K(9984K), 0.0057542 secs]
410 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003654 secs]
411 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006186 secs]
412 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004364 secs]
413 [GC (Allocation Failure)  3662K->846K(9984K), 0.0026546 secs]
414 [GC (Allocation Failure)  3662K->846K(9984K), 0.0298837 secs]
415 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001987 secs]
416 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003437 secs]
417 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001527 secs]
418 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001639 secs]
419 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001518 secs]
420 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002911 secs]
421 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002130 secs]
422 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005589 secs]
423 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006149 secs]
424 [GC (Allocation Failure)  3662K->846K(9984K), 0.0033363 secs]
425 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002908 secs]
426 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002283 secs]
427 [GC (Allocation Failure)  3662K->846K(9984K), 0.0031547 secs]
428 [GC (Allocation Failure)  3662K->846K(9984K), 0.0176105 secs]
429 [GC (Allocation Failure)  3662K->846K(9984K), 0.0103212 secs]
430 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004591 secs]
431 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004448 secs]
432 [GC (Allocation Failure)  3662K->846K(9984K), 0.0068689 secs]
433 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006339 secs]
434 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001767 secs]
435 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001558 secs]
436 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001561 secs]
437 [GC (Allocation Failure)  3662K->846K(9984K), 0.0034837 secs]
438 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003017 secs]
439 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002578 secs]
440 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001627 secs]
441 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005045 secs]
442 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001586 secs]
443 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
444 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003368 secs]
445 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002507 secs]
446 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001306 secs]
447 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001997 secs]
448 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003555 secs]
449 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001767 secs]
450 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001518 secs]
451 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001683 secs]
452 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001614 secs]
453 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005026 secs]
454 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001720 secs]
455 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001505 secs]
456 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001614 secs]
457 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001770 secs]
458 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001176 secs]
459 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001216 secs]
460 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002924 secs]
461 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001574 secs]
462 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001378 secs]
463 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001546 secs]
464 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001490 secs]
465 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001409 secs]
466 [GC (Allocation Failure)  3662K->846K(9984K), 0.0030663 secs]
467 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002572 secs]
468 [GC (Allocation Failure)  3662K->846K(9984K), 0.0253565 secs]
469 [GC (Allocation Failure)  3662K->846K(9984K), 0.0034722 secs]
470 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007384 secs]
471 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001701 secs]
472 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002376 secs]
473 [GC (Allocation Failure)  3662K->846K(9984K), 0.0010111 secs]
474 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001555 secs]
475 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004874 secs]
476 [GC (Allocation Failure)  3662K->846K(9984K), 0.0011909 secs]
477 [GC (Allocation Failure)  3662K->846K(9984K), 0.0011402 secs]
478 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006597 secs]
479 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004606 secs]
480 [GC (Allocation Failure)  3662K->846K(9984K), 0.0142543 secs]
481 [GC (Allocation Failure)  3662K->846K(9984K), 0.0104319 secs]
482 [GC (Allocation Failure)  3662K->846K(9984K), 0.0101361 secs]
483 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003993 secs]
484 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005073 secs]
485 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003689 secs]
486 [GC (Allocation Failure)  3662K->846K(9984K), 0.0015545 secs]
487 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002068 secs]
488 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008438 secs]
489 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002426 secs]
490 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002264 secs]
491 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001512 secs]
492 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001166 secs]
493 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002099 secs]
494 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001045 secs]
495 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007010 secs]
496 [GC (Allocation Failure)  3662K->846K(9984K), 0.0006068 secs]
497 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001608 secs]
498 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001306 secs]
499 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009097 secs]
500 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005219 secs]
501 [GC (Allocation Failure)  3662K->846K(9984K), 0.0004196 secs]
502 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007172 secs]
503 [GC (Allocation Failure)  3662K->846K(9984K), 0.0263185 secs]
504 [GC (Allocation Failure)  3662K->846K(9984K), 0.0007054 secs]
505 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001860 secs]
506 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001173 secs]
507 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002989 secs]
508 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001166 secs]
509 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001151 secs]
510 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001686 secs]
511 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001070 secs]
512 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001169 secs]
513 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003023 secs]
514 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002090 secs]
515 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003350 secs]
516 [GC (Allocation Failure)  3662K->846K(9984K), 0.0005281 secs]
517 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003297 secs]
518 [GC (Allocation Failure)  3662K->846K(9984K), 0.0008161 secs]
519 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001642 secs]
520 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003029 secs]
521 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002320 secs]
522 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001117 secs]
523 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001157 secs]
524 [GC (Allocation Failure)  3662K->846K(9984K), 0.0081105 secs]
525 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003459 secs]
526 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001760 secs]
527 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001449 secs]
528 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001337 secs]
529 [GC (Allocation Failure)  3662K->846K(9984K), 0.0129219 secs]
530 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001564 secs]
531 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001452 secs]
532 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001459 secs]
533 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001788 secs]
534 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001145 secs]
535 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001132 secs]
536 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001135 secs]
537 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002665 secs]
538 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001415 secs]
539 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001151 secs]
540 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001400 secs]
541 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001064 secs]
542 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001281 secs]
543 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001045 secs]
544 [GC (Allocation Failure)  3662K->846K(9984K), 0.0003275 secs]
545 [GC (Allocation Failure)  3662K->846K(9984K), 0.0009041 secs]
546 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001555 secs]
547 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001092 secs]
548 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001104 secs]
549 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001247 secs]
550 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001120 secs]
551 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001126 secs]
552 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001110 secs]
553 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001095 secs]
554 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001123 secs]
555 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001110 secs]
556 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001847 secs]
557 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001107 secs]
558 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001079 secs]
559 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001496 secs]
560 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001132 secs]
561 [GC (Allocation Failure)  3662K->846K(9984K), 0.0001107 secs]
562 [GC (Allocation Failure)  3662K->846K(9984K), 0.0002034 secs]
563 1755
564 
565 Process finished with exit code 0
View Code

  果不其然,不只運行速度慢了不少,且能夠推斷出變量b指向的對象在Java堆裏分配內存了。就如以前理論,逃逸分析是JVM層面的工做,若是JVM不進行逃逸分析,那麼即便優化了代碼,也是在堆中分配內存(由於發生了大量的GC日誌記錄~!),而以前的進行逃逸分析運行不只速度很快,且沒有任何GC記錄,說明逃逸分析以後b是在Java棧幀裏分配的內存,方法調用完畢自動清理內存,不會發生內存泄漏,也不GC!


 

  對Java棧——棧上分配優化的小結:

  • 必須是小對象(通常幾十個bytes),且必須是在沒有逃逸的狀況下,若是JVM使用了逃逸分析優化,則該小對象能夠直接分配在棧上,由於棧的空間不大(通常也就到1m封頂了),更沒有堆大。
  • 直接分配在棧上, 方法調用完畢,Java棧幀就當即被移除,故內存能夠自動回收,減輕GC壓力。
  • 大對象(棧的空間不容許)或者逃逸的對象沒法在棧上分配(即便啓動了JVM的逃逸分析優化,且由於Java棧是線程私有的,不共享,局部對象變量被其餘線程或者方法引用了確定不能在棧分配內存)

 


 

  總結到這裏不由有一個疑問,爲何方法調用(包括其餘編程語言的函數調用等)須要使用棧?

  佔坑,留在下一個單元進行總結

 


 

  對JVM基本結構的小結,再次回憶上文提到的JVM的基本結構:

  如今單獨拿出紅色框裏的方法區,Java堆,Java棧區,來看看三者之間如何交互。

  且前面也說了Java堆是全局共享的,幾乎全部的對象都保存到了Java堆,堆是發生GC的主要區域。

  而Java棧是線程私有的,且每一個線程啓動都會建立一個Java棧,棧內還有幀,Java棧中的每一個幀都保存一個方法調用的局部變量、操做數棧、指向常量池的指針等,且每一次方法調用都會建立一個幀,並壓棧。

  還有方法區,它是保存JVM裝載的類的信息的,好比類型的常量池、類中的字段,類中的方法信息、方法的字節碼(bytecode)等,注意這不是絕對的!好比:JDK 6 時,String等字符串常量的信息是置於方法區中的,可是到了JDK 7 時,已經移動到了Java堆。

  因此,方法區也好,Java堆也罷,到底保存了什麼,其實沒有具體定論,要結合不一樣的JVM版原本分析,由於技術是發展的!不過通常認爲,方法區就是保存了JVM裝載的類的信息

  

  下面再看一個(網上找的)更加細緻的JVM內存結構圖(之後會常常看到):

  

  進階:實例說明JVM的棧、堆、和方法區的交互

  看上圖有些複雜,下面用一個例子(來源於互聯網)幫助總結他們三者之間的交互原理。

 1 public class Sample {
 2     private String name;
 3 
 4     public Sample(String name) {
 5         this.name = name;
 6     }
 7 
 8     public void printName() {
 9         System.out.println(this.name);
10     }
11 }
12 
13 public class AppMain {
14 
15     public static void main(String[] args) {
16         Sample test1 = new Sample("測試1");
17         Sample test2 = new Sample("測試2");
18 
19         test1.printName();
20         test2.printName();
21     }
22 }
View Code

  衆所周知,一般Java程序都要從main方法進入,故通常狀況下Java程序都有一個main方法,而它自己也是一個線程(主線程),天然就對應一個Java棧,main方法也就對應一個Java的棧幀了。而根據以前JVM結構的分析,咱們知道類會被JVM裝載,那麼JVM裝載的類的信息放在了方法區裏(包括字段信息,方法自己的字節碼等,固然main方法也不例外),而方法體內的局部變量(包括形參),本例是對象的引用,統一放到Java棧幀裏。而對象自己存放到了Java堆。以下注釋:

 1 /**
 2  * AppMain
 3  *
 4  * 程序運行時,JVM把AppMain這個類的信息(裝載的)所有放入方法區保存
 5  *
 6  * @author Wang Yishuai.
 7  * @date 2016/2/19 0019.
 8  * @Copyright(c) 2016 Wang Yishuai,USTC,SSE.
 9  */
10 public class AppMain {
11 
12     // main方法自己的字節碼也放入方法區保存
13     public static void main(String[] args) {
14         // test引用保存到Java棧幀,類Sample的對象存入Java堆
15         Sample test1 = new Sample("測試 1");
16         Sample test2 = new Sample("測試 2");
17 
18         test1.printName();
19         test2.printName();
20     }
21 }
22 
23 public class Sample {
24     /**
25      * 類的字段信息也存入了方法區
26      */
27     private String name;
28 
29     /**
30      * main方法裏new本類實例以後,Sample構造器做爲一個方法,它的形參name,name引用存入棧,name引用的字符串對象放入堆
31      *
32      * @param name String
33      */
34     public Sample(String name) {
35         this.name = name;
36     }
37 
38     /**
39      * printName 放入了方法區保存
40      */
41     public void printName() {
42         System.out.println(this.name);
43     }
44 }
View Code

  畫成圖就是這樣:類中方法自己(字節碼)存放在方法區,Java棧裏的對象引用指向了Java堆裏的對象,以後堆裏的對象須要的類的信息要去方法區裏(非堆區)讀取。


 

  問題:爲了能讓遞歸方法調用的次數更多一些,應該怎麼作呢?

  衆所周知,遞歸是指函數直接或間接地調用本身,傳統地遞歸過程就是函數調用,涉及返回地址、函數參數、寄存器值等壓棧(在x86-64上一般用寄存器保存函數參數),這樣作的缺點有二:

  1. 效率低,佔內存
  2. 若是遞歸鏈過長,可能會statck over flow(棧區的空間一般是OS設定好的,一般只有幾M)
  由於傳統的遞歸都是在棧上根據調用順序依次申請內存空間(棧幀)進行運算,而後層層回調,這是基於上一層運算依賴於下一層的運算結果(或者說上一層的運算還沒作完,須要下一層返回的結果),好比經典的斐波那契數列第n項計算例子(Fn = Fn-1 + Fn-2,if n = 0和1, then Fn = 1),使用循環去實現:
 1 int fib_1(int n) {
 2     int a = 1;
 3         int b = 1 ;
 4 
 5     for(int i = 0; i < n; i++) {
 6         int a_ = b;
 7                 int b_ = a + b;
 8         a = a_ ;
 9         b = b_ ;
10     }
11 
12     return a
13 }    
View Code

  使用遞歸實現:

1 int fib_2(int n) {
2     if (n <= 1) {
3         return 1 ;
4     } else {
5         return fib_2(n - 1) + fib_2(n - 2) ;
6     }
7 }
View Code

  後來人們發現,對於該遞歸而言,一些壓棧操做並沒有必要,遞歸中的子問題規模幾乎不變,每次只減去了1或者2。若是畫一個遞歸樹,會發現不少相同的子樹!!!說明該實現浪費了不少內存和時間,當解決Fn-1問題時,計算了Fn-2和Fn-3,解決Fn問題時,計算了Fn-1和Fn-2,實際上我只須要計算一次Fn-2就ok了。優化——使用自底向上的算法:線性遞歸

 1 int fib_3(int n) {
 2     int fib_rec(int a , int b , int n) {
 3         if (n <= 1) {
 4             return 1 ;
 5         } else {
 6             return a + fib_rec(b , a + b , n - 1)
 7         }
 8     }
 9 
10     return fib_rec(1 , 1 , n)
11 }
View Code

  依次計算Fn,F0、F一、F二、F3……Fn,花費線性時間,由於個人輸入是線性的。不過還不是更好的,線性遞歸每次調用時,針對上一次調用的結果,它不進行收集(保存),只能依靠順次的展開,這樣也很消耗內存。下面引出一個概念——尾遞歸:尾遞歸,它比線性遞歸多一個參數,這個參數是上一次調用函數獲得的結果,尾遞歸每次調用都在收集結果,避免了線性遞歸不收集結果只能依次展開,消耗內存的壞處。以下:

 1 int fib_4(int n) {
 2     int fib_iter(int a , int b , int n) {
 3         if (n == 0) {
 4             return a;
 5         } else {
 6             return fib_iter(b , a + b , n - 1) ;
 7         }
 8     }
 9 
10     return fib_iter(1 , 1 , n) ;
11 }
View Code

  尾遞歸的狀況是下層計算結果對上層「無用」(上一層運算已經作完,不依賴後續的遞歸),爲了效率,直接將下一層須要的空間覆蓋在上一層上,尾遞歸和通常的遞歸不一樣在對內存的佔用,普通遞歸建立stack累積然後計算收縮,尾遞歸只會佔用恆量的內存(和迭代同樣)。通俗的說,尾遞歸是把變化的參數傳遞給遞歸函數的變量了

  怎麼寫尾遞歸?形式上只要最後一個return語句是單純函數就能夠。如:

return tailrec(x+1);

return tailrec(x+1) + x;

則不能夠。由於沒法更新tailrec()函數內的實際變量,只是新建一個棧。

  更形象的解釋(來自網絡):普通遞歸
function story() {
從前有座山,山上有座廟,廟裏有個老和尚,一天老和尚對小和尚講故事:story(),小和尚聽了,找了塊豆腐撞死了 // 非尾遞歸,下一個函數結束之後此函數還有後續,因此必須保存自己的環境以供處理返回值。
}
View Code

  尾遞歸:

function story() {
從前有座山,山上有座廟,廟裏有個老和尚,一天老和尚對小和尚講故事:story() // 尾遞歸,進入下一個函數再也不須要上一個函數的環境了,得出結果之後直接返回。
}
View Code

  綜上,能夠儘量高效的利用棧空間,增長遞歸調研數。

相關文章
相關標籤/搜索