JVM虚拟机栈StackOverflowError和OutOfMemoryError

-Xss是指设定每个线程堆栈大小,在JDK1.5之前栈容量默认是256K,之后的默认大小是1M;

yaomingyangdeMacBook-Pro:~ yaomingyang$ java -XX:+PrintFlagsFinal -version |grep  ThreadStackSize
     intx CompilerThreadStackSize                   = 0                                   {pd product}
     intx ThreadStackSize                           = 1024                                {pd product}
     intx VMThreadStackSize                         = 1024                                {pd product}
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

关于虚拟机栈Java虚拟机规范中描述了两种异常:

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
  • 如果虚拟机在扩展栈时无法申请到足够的内存,则将抛出OutOfMemmoryError异常。
1.栈深度StackOverflowError异常测试
package controllers;

public class VMTest {

	private int stackLength = 1;
	
	public void stackLength() {
		int a =1;
		int b=2;
		stackLength++;
		stackLength();
	}
	
	public static void main(String[] args) {
		
		VMTest vm = new VMTest();
		try {
			vm.stackLength();
		}catch (Throwable e) {
			System.out.println("栈深度是:"+vm.stackLength);
			throw e;
		}
		
	}
}


Exception in thread "main" 栈深度是:17890
java.lang.StackOverflowError
	at controllers.VMTest.stackLength(VMTest.java:11)
	at controllers.VMTest.stackLength(VMTest.java:11)
  • 使用-Xss参数减少栈内存容量,会抛出StackOverflowError异常,异常出现时输出的堆栈深度相应的缩小。
  • 增大方法中的本地变量表的长度,结果抛出StackOverflowError异常,输出的堆栈深度相应的缩小。

TIPS:以上实验结果表明,在单线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候都会抛出StackOverflowError异常。

2.虚拟机栈OutOfMemmoryError异常

Xss参数是设定虚拟机中每个线程占用的栈内存大小,而虚拟机栈可分配的内存又跟物理机的内存大小、Java堆内存、方法区等内存大小相关,其它的区分得的内存越大,虚拟机栈能够分得的内存就越小,并发的线程数量也就越小;而如果要想模拟OOM异常可以通过不停的创建线程,直到虚拟机栈内存被使用完。

如下程序会触发OOM异常,但是这个程序可能会导致操作系统假死,慎重测试(我的电脑就被搞死了,没办法强制重启)

package controllers;

public class VMOOTest {

	public void statck() {
		while(true) {
			Thread thread = new Thread(new Runnable() {
				
				@Override
				public void run() {
					while(true) {
						
					}
					
				}
			});
			thread.start();
		}
	}
	public static void main(String[] args) {
		VMOOTest oo = new VMOOTest();
		oo.statck();
	}
}

TIPS:如果是建立过多线程导致内存溢出,在不能减少线程数量或者更换服务器内存的情况的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页