2011-07-19 44 views
4
public class Foo { 

    public static void main(String[] args) { 
     foo(); 
    } 

    public static void foo() { 
     try { 
      System.out.println("try"); 
      foo(); 
     } catch (Throwable e) { 
      System.out.println("catch"); 
      foo(); 
     } finally { 
       System.out.println("finally"); 
       foo(); 
     } 
    } 
} 

誰能解釋這段代碼的輸出?java try-catch-finally遞歸問題

1.輸出基於Eclipse(無盡的)客戶端模式:

 

    try 
    try 
    .... 


    ... 
    ... 
    tryfinallyfinally 
    tryfinallyfinally 
    try 
    try 
    try 
    tryfinallyfinally 
    tryfinallyfinally 
    try 
    tryfinallyfinally 
    tryfinallyfinally 
    try 
    .... 
    .... 

在Linux 2.輸出(崩潰)服務器模式:

 

    try 
    try 
    ... 

    ... 
    try 
    try 
    try 
    try 
    try 
    try 
    MISSING EXCEPTION HANDLER for pc 0x00002aaaab1c53f0 and handler bci -1 
     Exception: 

    Compiled exception table : 
    ExceptionHandlerTable (size = 3304 bytes) 
    catch_pco = 700 (1 entries) 
     bci -1 at scope depth 0 -> pco 11039 
    catch_pco = 1736 (1 entries) 
     bci -1 at scope depth 0 -> pco 11473 
    catch_pco = 1756 (1 entries) 
     bci -1 at scope depth 0 -> pco 11433 
    catch_pco = 1776 (1 entries) 

+6

***誰能解釋這段代碼的輸出?***:可能是**你**。你運行這個時得到了什麼? –

+6

...計算器 – MarcoS

+2

輸出確實是意外: 嘗試 嘗試 嘗試 tryfinallyfinally tryfinallyfinally 嘗試 tryfinallyfinally tryfinallyfinally 嘗試 嘗試 tryfinallyfinally tryfinallyfinally 嘗試 tryfinallyfinally tryfinallyfinally 嘗試 嘗試 嘗試 試 –

回答

8

我想我還記得這從書中的「Java謎題」。 try塊會執行一個無界的遞歸,這會很快導致StackOverflowError被拋出。嘗試和捕獲塊恢復遞歸,但與相應較小的剩餘堆棧。然而,隨着每個遞歸調用返回,剩餘堆棧會再次變大...

最終結果是一個調用圖,它根據堆棧的大小形成深度樹;與主流JVM的默認堆棧大小相比,樹會變得非常大,以至於您必須等待很多次,才能完全遍歷數十億年,並終止程序。

編輯:這就是你在客戶端模式下看到的:遍歷調用圖。在服務器模式下,您在Linux上看到的是JVM錯誤或硬件缺陷(錯誤的RAM可能具有此效果)。

+0

我的猜測是這是在Linux上的JIT中的錯誤。 –

+0

許多,許多,更多的零:) - http://stackoverflow.com/a/32319720/2158288 – ZhongYu