jdk1.5前,默认Xss256k,jdk1.5后默认Xss1m
实验前:对于虚拟机栈的理解
- 虚拟机中每一个线程栈都有一个固定的大小,这个大小的值由Xss参数制定
- 假设进程里有n个线程,那么整个虚拟机栈总共占用了 n*Xss的内存,这个是从这n个线程已启动就已经分配好了
实验后:对于虚拟机栈的理解
- 每次创建一个帧栈时,并不会为其直接分配Xss大小的内存,并且不是刚创建帧栈时如果机器内存不够Xss的大小就报OOM
- Xss只是一个阈值,表示的是一个帧栈的最大可用内存
- 每个栈实际占用内存都是动态地按需分配,线程一帧需要多少内存就分配相应或稍多的内存,但整个帧栈大小不会超过Xss这个阈值,否则报StackOverFlowError
实验代码
/**
* VM Args: -Xss1g -Xmx40g -Xms40g
* @author JohnLiu
*/
public class StackOOM {
public void stackLeakByThread(){
int num=20;
//启动20个线程
while(num>0){
new Thread(new Runnable(){
public void run(){
endlessWork(0);
}
}).start();;
num--;
}
}
public void endlessWork(int count){
System.out.println(Thread.currentThread().getName()+"-"+count);
// 1G的栈下 基本上一千万次调用会发生StackOverFlowError,为了保守起见,设置只递归调用8000000次
if(count<=8000000){
endlessWork(++count);
}else{
//防止出现 stackOverFlowError
while(true){
}
}
}
public static void main(String[] args) {
new StackOOM().stackLeakByThread();
}
}
实验结果
本机内存为47G, 20个线程一起创建后,如果每个线程一创建就分配Xss的空间,那么:堆空间+20个栈的空间=40g+20g=60g>47g,程序不可能会启动成功,但是这个程序能成功启动,并且最后的输出日志如下:
Thread-7-785683
Thread-7-785684
Thread-7-785685
Thread-7-785686
Thread-7-785687
Thread-7-785688
Thread-7-785689
Thread-7-785690
Thread-7-785691
Thread-7-785692
Thread-7-785693
Thread-14-741123
Thread-14-741124
Thread-14-741125
#
[thread 30788 also had an error]# There is insufficient memory for the Java Runtime Environment to continue.
[thread 31128 also had an error]
# Native memory allocation (malloc) failed to allocate 2832 bytes for AllocateHeap
# An error report file with more information is saved as:
# D:\export\hs_err_pid30696.log
[CodeBlob (0x0000000042ff0790)]
Framesize: 0
BufferBlob (0x0000000042ff0790) used for StubRoutines (1)
网友评论