<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
    主站蜘蛛池模板: 欧洲精品免费一区二区三区| 亚洲成人免费在线观看| 国产大片线上免费看| 国产精品亚洲av色欲三区| 国产精品二区三区免费播放心| 日韩免费人妻AV无码专区蜜桃| 亚洲成电影在线观看青青| 无码一区二区三区AV免费| 亚洲码和欧洲码一码二码三码| 日本高清免费不卡在线| 中文在线观看永久免费| 亚洲综合男人的天堂色婷婷| 大陆一级毛片免费视频观看| 一级毛片高清免费播放| 人人狠狠综合久久亚洲88| 亚洲视频免费观看| 国产麻豆一精品一AV一免费| 中文字幕在线观看亚洲视频| 国产免费资源高清小视频在线观看| 久久高潮一级毛片免费| 亚洲美女人黄网成人女| 日产乱码一卡二卡三免费| 皇色在线视频免费网站| h视频在线免费观看| 亚洲综合色7777情网站777| 久久精品国产亚洲av高清漫画| 日本人护士免费xxxx视频| 欧美三级在线电影免费| 国产免费一区二区三区在线观看| 一级做a爰性色毛片免费| 人妻无码中文字幕免费视频蜜桃| 亚洲成人午夜在线| 国产又粗又猛又爽又黄的免费视频| 久久久久久99av无码免费网站 | 成人免费视频小说| 日本一区午夜艳熟免费| 亚洲熟妇无码AV不卡在线播放| 亚洲成AV人在线观看天堂无码| 亚洲啪啪综合AV一区| 国产精品高清全国免费观看| 日本免费一本天堂在线|