java 線程棧 & java.lang.StackOverflowError


網上搜索了一下,關於java的線程棧:

JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.

 

 

JVM的內存,被划分了很多的區域: (來源:http://www.iteye.com/topic/808550)

1.程序計數器

每一個Java線程都有一個程序計數器來用於保存程序執行到當前方法的哪一個指令。

2.線程棧

線程的每個方法被執行的時候,都會同時創建一個幀(Frame)用於存儲本地變量表、操作棧、動態鏈接、方法出入口等信息。每一個方法的調用至完成,就意味着一個幀在VM棧中的入棧至出棧的過程。如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果VM棧可以動態擴展(VM Spec中允許固定長度的VM棧),當擴展時無法申請到足夠內存則拋出OutOfMemoryError異常。

3.本地方法棧

4.堆

每個線程的棧都是該線程私有的,堆則是所有線程共享的。當我們new一個對象時,該對象就被分配到了堆中。但是堆,並不是一個簡單的概念,堆區又划分了很多區域,為什么堆划分成這么多區域,這是為了JVM的內存垃圾收集,似乎越扯越遠了,扯到垃圾收集了,現在的jvm的gc都是按代收集,堆區大致被分為三大塊:新生代,舊生代,持久代(虛擬的);新生代又分為eden區,s0區,s1區。新建一個對象時,基本小的對象,生命周期短的對象都會放在新生代的eden區中,eden區滿時,有一個小范圍的gc(minor gc),整個新生代滿時,會有一個大范圍的gc(major gc),將新生代里的部分對象轉到舊生代里。

5.方法區 

其實就是永久代(Permanent Generation),方法區中存放了每個Class的結構信息,包括常量池、字段描述、方法描述等等。VM Space描述中對這個區域的限制非常寬松,除了和Java堆一樣不需要連續的內存,也可以選擇固定大小或者可擴展外,甚至可以選擇不實現垃圾收集。相對來說,垃圾收集行為在這個區域是相對比較少發生的,但並不是某些描述那樣永久代不會發生GC(至 少對當前主流的商業JVM實現來說是如此),這里的GC主要是對常量池的回收和對類的卸載,雖然回收的“成績”一般也比較差強人意,尤其是類卸載,條件相當苛刻。

6.常量池

 Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量表(constant_pool table),用於存放編譯期已可知的常量,這部分內容將在類加載后進入方法區(永久代)存放。但是Java語言並不要求常量一定只有編譯期預置入Class的常量表的內容才能進入方法區常量池,運行期間也可將新內容放入常量池(最典型的String.intern()方法)。

 

 

今天研究了一下 java 的線程棧,寫了一段代碼用於測試:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public  class  Test
{
     byte [] data =  new  byte [ 8192 ];
     
     public  static  void  main(String[] args)
     {
         if (args.length ==  0 )
         {
             System.out.println( "確少參數, 正確的命令: java Test <數字>" );
             System.exit( 0 );
         }
         
         int  x = Integer.parseInt(args[ 0 ]);
         
         //這里不論申請多大的空間,都不會拋出 java.lang.StackOverflowError
         byte [] data =  new  byte [ 2048 ];
         
         //遞歸的次數與 線程棧 以及 java.lang.StackOverflowError 有直接關系
         System.err.println( "dg("  + x +  ") = "  + dg(x));
     }  
     
     //遞歸測試
     private  static  int  dg( int  x)
     {
         //測試發現這里申明的變量數與線程棧以及java.lang.StackOverflowError有直接關系      
         int  a =  1 ;
         int  b =  2 ;
         
         //這里不論申請多大的空間,都不會拋出 java.lang.StackOverflowError       
         byte [] data =  new  byte [ 2048 ];
         
         if (x >  1 )
         {
             return  x + dg(--x);
         }
         else
         {
             return  x;
         }
     }
}

 

 

C:\test>java -Xms8M -Xmx8M -Xss1K Test 600

dg(600) = 180300

 

C:\test>java -Xms8M -Xmx8M -Xss1K Test 700

Exception in thread "main" java.lang.StackOverflowError

        at Test.dg(Test.java:26)

        at Test.dg(Test.java:34)

        at Test.dg(Test.java:34)

        at Test.dg(Test.java:34)

 

2014-03-08

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM