2.4.1.Stack是java栈内存,它等价于C语言中的栈,栈的内存地址是不连续的,每个线程都拥有自己的栈。栈里面存储着的是StackFrame,在《JVM Specification》中文版中被译作java虚拟机框架,也叫做栈帧。StackFrame包含三类信息:局部变量,执行环境,操作数栈。局部变量用来存储一个类的方法中所用到的局部变量。执行环境用于保存解析器对于java字节码进行解释过程中需要的信息,包括:上次调用的方法、局部变量指针和操作数栈的栈顶和栈底指针。操作数栈用于存储运算所需要的操作数和结果。StackFrame在方法被调用时创建,在某个线程中,某个时间点上,只有一个框架是活跃的,该框架被称为Current Frame,而框架中的方法被称为Current Method,其中定义的类为Current Class。局部变量和操作数栈上的操作总是引用当前框架。当Stack Frame中方法被执行完之后,或者调用别的StackFrame中的方法时,则当前栈变为另外一个StackFrame。Stack的大小是由两种类型,固定和动态的,动态类型的栈可以按照线程的需要分配。 下面两张图是关于栈之间关系以及栈和非堆内存的关系基本描述(来自 http://www.programering.com/a/MzM3QzNwATA.html ):
2.4.2.Heap 是用来存放对象信息的,和Stack不同,Stack代表着一种运行时的状态。换句话说,栈是运行时单位,解决程序该如何执行的问题,而堆是存储的单位,解决数据存储的问题。Heap是伴随着JVM的启动而创建,负责存储所有对象实例和数组的。堆的存储空间和栈一样是不需要连续的,它分为Young Generation和Old Generation(也叫Tenured Generation )两大部分。Young Generation分为Eden和Survivor,Survivor又分为From Space和 To Space。
引用一个经典的案例来理解Stack,Heap和Method Area的划分,就是Sring a="xx";Stirng b="xx",问是否a==b? 首先==符号是用来判断两个对象的引用地址是否相同,而在上面的题目中,a和b按理来说申请的是Stack中不同的地址,但是他们指向Method Area中Runtime Constant Pool的同一个地址,按照网上的解释,在a赋值为“xx”时,会在Runtime Contant Pool中生成一个String Constant,当b也赋值为“xx”时,那么会在常量池中查看是否存在值为“xx”的常量,存在的话,则把b的指针也指向“xx”的地址,而不是新生成一个String Constant。我查阅了网络上大家关于String Constant的存储的说说法,存在略微差别的是,它存储在哪里,有人说Heap中会分配出一个常量池,用来存储常量,所有线程共享它。而有人说常量池是Method Area的一部分,而Method Area属于非堆内存,那怎么能说常量池存在于堆中?
Platform
|
Default
|
---|---|
Windows IA32
|
64 KB
|
Linux IA32
|
128 KB
|
Windows x86_64
|
128 KB
|
Linux x86_64
|
256 KB
|
Windows IA64
|
320 KB
|
Linux IA64
|
1024 KB (1 MB)
|
Solaris Sparc
|
512 KB
|
关于栈一般会发生以下两种异常:
而当我在eclipse中调整了-Xss参数到3M之后,该异常消失。
byte
| 值是8位的有符号二进制补码整数 |
short
|
值是16位的有符号二进制补码整数 |
int
|
值是32位的有符号二进制补码整数 |
long
|
值是64位的有符号二进制补码整数 |
char
|
值是表示Unicode字符的16位无符号整数 |
float
|
值是32位IEEE754浮点数
|
double
| 值是64位IEEE754浮点数 |
魔数,魔数的唯一作用是确定这个文件是否为一个能被虚拟机所接受的Class文件。魔数值固定为0xCAFEBABE,不会改变。
minor_version、major_version:
分别为Class文件的副版本和主版本。它们共同构成了Class文件的格式版本号。不同版本的虚拟机实现支持的Class文件版本号也相应不同,高版本号的虚拟机可以支持低版本的Class文件,反之则不成立。
constant_pool_count:
常量池计数器,constant_pool_count的值等于constant_pool表中的成员数加1。
constant_pool[]:
常量池,constant_pool是一种表结构,它包含Class文件结构及其子结构中引用的所有字符串常量、类或接口名、字段名和其它常量。常量池不同于其他,索引从1开始到constant_pool_count -1。
access_flags:
访问标志,access_flags是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。access_flags的取值范围和相应含义见下表:
this_class:
类索引,this_class的值必须是对constant_pool表中项目的一个有效索引值。constant_pool表在这个索引处的项必须为CONSTANT_Class_info类型常量,表示这个Class文件所定义的类或接口。
super_class:
父类索引,对于类来说,super_class的值必须为0或者是对constant_pool表中项目的一个有效索引值。如果它的值不为0,那constant_pool表在这个索引处的项必须为CONSTANT_Class_info类型常量,表示这个Class文件所定义的类的直接父类。当然,如果某个类super_class的值是0,那么它必定是java.lang.Object类,因为只有它是没有父类的。
interfaces_count:
接口计数器,interfaces_count的值表示当前类或接口的直接父接口数量。
interfaces[]:
接口表,interfaces[]数组中的每个成员的值必须是一个对constant_pool表中项目的一个有效索引值,它的长度为interfaces_count。每个成员interfaces[i] 必须为CONSTANT_Class_info类型常量。
fields_count:
字段计数器,fields_count的值表示当前Class文件fields[]数组的成员个数。
fields[]:
字段表,fields[]数组中的每个成员都必须是一个fields_info结构的数据项,用于表示当前类或接口中某个字段的完整描述。
methods_count:
方法计数器,methods_count的值表示当前Class文件methods[]数组的成员个数。
methods[]:
方法表,methods[]数组中的每个成员都必须是一个method_info结构的数据项,用于表示当前类或接口中某个方法的完整描述。
attributes_count:
属性计数器,attributes_count的值表示当前Class文件attributes表的成员个数。
attributes[]:
属性表,attributes表的每个项的值必须是attribute_info结构。