网上搜索了一下,关于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

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

java 线程栈 & java.lang.StackOverflowError的更多相关文章

  1. Java 线程--实现java.lang.Runnable接口实现线程

    Java线程的第一种实现方式,主要分两步,第一步是继承java.lang.Thread; 第二步是重写run()方法.接下来我们来看Java线程的第二种实现方式,也是分为两步,第一步,写一个类实现ja ...

  2. Java虚拟机栈(java stack)

    虚拟机栈(java stack) 百度图片搜索里的动图搜索功能不错,可以搜索一些动图,展示操作数栈的操作过程,比较形象.这点google差点意思 虚拟机栈(jvm stacks)是线程独占的 里面是多 ...

  3. 【Java线程】Java内存模型总结

    学习资料:http://www.infoq.com/cn/articles/Java-memory-model-1 Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态, ...

  4. (转)【Java线程】Java内存模型总结

    Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变 ...

  5. Java 线程--继承java.lang.Thread类实现线程

    现实生活中的很多事情是同时进行的,Java中为了模拟这种状态,引入了线程机制.先来看线程的基本概念. 线程是指进程中的一个执行场景,也就是执行流程,进程和线程的区别: 1.每个进程是一个应用程序,都有 ...

  6. Java 线程 — JMM Java内存模型

    JMM Java Memory Model,Java内存模型,属于语言级的内存模型 并发编程中存在的问题: 如何通信:用于线程之间交换信息.两种方式:共享内存,消息传递 如何同步:用于控制不同线程间操 ...

  7. 【Java线程】Java线程池ExecutorService

    示例 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.u ...

  8. 程序员的视角:java 线程(转)

    在我们开始谈线程之前,不得不提下进程.无论进程还是线程都是很抽象的概念,有一个关于进程和线程很形象的比喻能帮我们更好的理解. 进程就像个房子,房子是一个包含了特定属性的容器,例如空间大小.卧室数量等. ...

  9. 程序员的视角:java 线程

    在我们开始谈线程之前,不得不提下进程. 无论进程还是线程都是很抽象的概念,有一个关于进程和线程很形象的比喻能帮我们更好的理解. 进程就像个房子,房子是一个包含了特定属性的容器,例如空间大小.卧室数量等 ...

随机推荐

  1. CentOS7中安装redis5.0

    1. 环境介绍 CentOS7 (未安装Development Tools) 2. 下载Redis5.0-rc3 wget -O redis-5.0-rc3.tar.gz https://github ...

  2. 利用Git工具将本地创建的项目上传到Github上

    前言 作为一个对前沿技术很看好的小青年,怎么能不会用Github呢?一年前我创建了Github,也知道git,但是尝试过用,但是就没弄明白,很多粉丝都问我Github的账号,想关注一波,无奈里面啥都没 ...

  3. 分布式监控系统Zabbix-批量添加聚合图形

    之前部署了Zabbix(3.4.4版本)监控环境,由于主机比较多,分的主机组也比较多,添加聚合图形比较麻烦,故采用python脚本进行批量添加聚合图形.脚本下载地址:https://pan.baidu ...

  4. Net-SNMP V3协议 安装配置笔记(CentOS 6.3/5.6)

    注意:snmp V3,需要需要关闭selinux和防火墙: 关闭selinux方法: #vi /etc/selinux/config 将文件中的SELINUX="" 为 disab ...

  5. linux-文件数据操作awk命令

    最后一列是:交互外壳 单引号里的内容不会被bash扩展 cut 同样可以做到 "\t" 制表符 cut 和 sed 结合同样可以实现 扩展:匿名方法可以有多个,and方法只能有一个 ...

  6. Scrum Meeting day 4

                第四次会议 No_00:工作情况 No_01:任务说明 待完成 已完成 No_10:燃尽图 No_11:照片记录 待更新 No_100:代码/文档签入记录 No_101:出席表 ...

  7. 【课程总结】Linux内核分析课程总结

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 每周实验报告: 反汇编一个简单的C程序 ...

  8. 《linux内核设计与实现》读书笔记——第三章

  9. 20135337——Linux内核分析:第十七章 模块与设备

    第17章 模块与设备 设备类型:在所有 Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对象:内核数据结构中支持面向对象的简单操作 ...

  10. myeclipse快捷方式汇总

    选择你要注释的那一行或多行代码,按Ctrl+/即可,取消注释也是选中之后按Ctrl+/即可. 如果你想使用的快捷键的注释是的话,那么你的快捷键是ctrl+shift+/我以前都是手动注释的,直接打// ...