<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    @OverWrite BlogJava

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      128 隨筆 :: 0 文章 :: 29 評論 :: 0 Trackbacks
    看兩段代碼:
    import java.util.ArrayList;   
    import java.util.List;   
      
    public class TailRecursionTest {   
        
    public static void main(String[] args) {   
            TailRecursionTest t 
    = new TailRecursionTest();   
            
    for (int i = 0; i < 10000; i++)   
                t.a(
    0);   
        }
       
      
        
    public void a(int j) {   
            j
    ++;   
            List list 
    = new ArrayList<Integer>(100000);   
            
    // 對list進行處理   
        }
       
    }

    沒啥特殊的,僅僅是為了測試,我們將a方法調用10000次,a方法創建一個有100000個元素的list的局部變量。
    第二個程序:
    import java.util.ArrayList;   
    import java.util.List;   
      
    public class TailRecursionTest2 {   
        
    public static void main(String[] args) {   
            TailRecursionTest2 t 
    = new TailRecursionTest2();   
            t.a(
    0);   
        }
       
      
        
    public void a(int j) {   
            System.out.println(j);   
            j
    ++;   
            
    if (j == 10000)   
                
    return;   
            List list 
    = new ArrayList<Integer>(100000);   
            
    // 對list進行處理   
            a(j);   
        }
       
    }
      

    也沒啥特殊的,就是將循環換成了遞歸,a方法做的事情沒變。兩個都跑一下,程序1順利結束,程序2出問題了,啥問題?如下:
    161  
    162  
    163  
    164  
    165  
    Exception in thread 
    "main" java.lang.OutOfMemoryError: Java heap space   
        at java.util.ArrayList.
    <init>(Unknown Source)   
        at TailRecursionTest2.a(TailRecursionTest2.java:
    17)   
        at TailRecursionTest2.a(TailRecursionTest2.java:
    20)   
        at TailRecursionTest2.a(TailRecursionTest2.java:
    20)   
        at TailRecursionTest2.a(TailRecursionTest2.java:
    20)   
        at TailRecursionTest2.a(TailRecursionTest2.java:
    20

    我倒,才運行166次了,heap就滿了。問題在哪呢?oh,yep,你肯定想到了,是不是重復創建list這個大集合引起的呢?它不是局部變量嗎?怎么也會溢出?是的,list是局部變量,在a的方法棧里引用著,指向heap上的大對象,更關鍵的問題在于,java是沒有尾遞歸優化的,遞歸方法是不會使用同一個棧幀,每一次遞歸調用,都將壓入新的棧幀,并且這個棧幀上又new了一個list變量,引用著heap上新的一個大集合。隨著棧深度的增加, jvm里維持著一條長長的方法調用軌跡以便你能回來,在方法沒有返回之前,這些list變量一直被各自的棧幀引用著,不能被GC,你說,能不OOM嗎?

        也許,你想到了個補救方法來挽救程序2,就是每次在處理完list后,我把它設置為null,不讓棧幀繼續引用著它,咱編寫對gc友好的代碼,這不就行了,試試:


    import java.util.ArrayList;   
    import java.util.List;   
      
    public class TailRecursionTest2 {   
        
    public static void main(String[] args) {   
            TailRecursionTest2 t 
    = new TailRecursionTest2();   
            t.a(
    0);   
        }
       
      
        
    public void a(int j) {   
            System.out.println(j);   
            j
    ++;   
            
    if (j == 10000)   
                
    return;   
            List list 
    = new ArrayList<Integer>(100000);   
            
    // 對list進行處理   
            list = null;  //gc友好   
            a(j);   
        }
       
    }
     

    得意洋洋,我跑一下看看,這次跑到4000多次,但是:
       
    4289  
    4290  
    4291  
    4292  
    java.lang.StackOverflowError   
        at sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop(Unknown Source)   
        at sun.nio.cs.ext.DoubleByteEncoder.encodeLoop(Unknown Source)   
        at java.nio.charset.CharsetEncoder.encode(Unknown Source) 

    總結:在java里,遞歸最好咱還是別用,老老實實地while、for;就算遞歸了,最好遞歸方法不要new太大的對象,除非你能確定遞歸的深度不是那么大,否則OOM和堆棧溢出的陰影將籠罩著你。
    posted on 2008-06-03 09:14 vesung 閱讀(1564) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 亚洲视频在线免费看| 99ee6热久久免费精品6| 好男人看视频免费2019中文| 亚洲AV永久无码区成人网站| 91视频精品全国免费观看| 久久久久亚洲AV无码专区网站| 香蕉国产在线观看免费| 亚洲偷自拍拍综合网| 成人片黄网站色大片免费观看APP| 亚洲国产成人久久综合一区77| 日日摸夜夜添夜夜免费视频 | 亚洲精品女同中文字幕| 四虎www免费人成| 另类图片亚洲校园小说区| 亚洲精品WWW久久久久久| 和老外3p爽粗大免费视频| 亚洲成AV人片在线观看无| 久久不见久久见免费视频7| 亚洲最大的视频网站| 久久精品网站免费观看| 亚洲另类自拍丝袜第五页| 免费日本黄色网址| 最新亚洲成av人免费看| 亚洲最大成人网色| 毛片免费观看视频| 杨幂最新免费特级毛片| 国产AV无码专区亚洲A∨毛片| 最近中文字幕免费mv在线视频| 亚洲色少妇熟女11p| 亚洲日韩在线观看免费视频| 久久国产精品成人免费| 亚洲伊人久久大香线蕉在观| 亚洲不卡AV影片在线播放| 久久精品国产这里是免费| 国产精品亚洲四区在线观看| 亚洲天堂在线视频| 国产成人精品免费视频网页大全| 亚洲a∨国产av综合av下载 | 亚洲精品国产电影| 91网站免费观看| 无码人妻一区二区三区免费视频|