JAVA stack overflow

Java stack overflow small note

Today occasionally someone asked how to write Java code so that it is thrown at runtime stack overflow exception, seemingly simple question related to the knowledge of the Java virtual machine, specially recorded in this article.

Java Virtual Machine architecture Introduction

The "Java Virtual Machine Specification" (the Virtual Machine of The Java Specification) for data area Java virtual machine is running (Run-Time Data Areas) of description, the virtual machine is running, which is configured as shown in FIG:
FIG, PC register, Java virtual machine and native method stacks stack for the thread private, the method area (including runtime constants taken) and the heap is shared between threads of storage space. Stack overflow In response to questions, there are two zones associated with it, including the Java virtual machine stacks and native method stacks. Check out "Java Virtual Machine Specification" stack overflow for the following two Description:
For a Java virtual machine stack

The following exceptional conditions are associated with Java Virtual Machine stacks:

  • If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
  • If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

对于本地方法栈

The following exceptional conditions are associated with native method stacks:

  • If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a StackOverflowError.
  • If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

由此可见对于Java虚拟机栈与本地方法栈都定义了相似的两种溢出:

  1. 线程请求栈上分配内存时,内存不足:此溢出一般出现在线程递归调用方法时。在线程调用方法时虚拟机创建栈帧保存方法调用信息,在方法调用完成后销毁栈帧释放存储,如果在方法调用过程中无法创建栈帧则会报出StackOverflowError异常。
  2. 动态扩展栈或线程创建时无法分配足够内存:此溢出一般出现在创建新的线程时。创建新的线程,需要在栈上为其分配存储,如果此时栈上存储不足以分配则会报出OutOfMemoryError异常。

代码实现

以下代码在Mac版JDK8中实现及运行,由于HotSpot实现中没有分Java虚拟机栈及本地方法栈[1],故以下代码只针对Java虚拟机栈。Hotspot中设置栈容量的参数为-Xss,后续实验均设置-Xss1M,使用Junit4进行测试

分配栈帧失败(StackOverflowError)

代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class  {

public void callMyself(int depth) {
System.out.println(depth);
callMyself(++depth);
}
}

public class StackOverflowTest {

public void callMyself() throws Exception {
StackOverflow overflow = new StackOverflow();
overflow.callMyself(0);
}

}

最终会抛出java.lang.StackOverflowError,且最终能够达到的栈深度主要与栈内存最大大小与栈帧中局部变量占用的空间有关。使用如下代码最大深度会明显变小

1
2
3
4
5
6
7
8
public class  {

public void callMyself(int depth) {
int a,b,c,d,e,f,g,h,i,j,k;
System.out.println(depth+"|");
callMyself(++depth);
}
}

为线程分配栈上内存失败(OutOfMemoryError)

代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class OutOfMemory {
public void createThread() {
while (true) {
Thread t = new Thread(() -> {
while (true) {
System.out.println(System.currentTimeMillis());
}
});
t.start();
}
}
}

public class OutOfMemoryTest {

public void createThread() throws Exception {
OutOfMemory outOfMemory = new OutOfMemory();
outOfMemory.createThread();
}
}

The final will throw OutOfMemoryError.

For the supplement to OutOfMemoryError

In the HotSpot virtual machine implementation, to create Java threads are mapped to the operating system thread, if you can not create an operating system threads will throw an exception, in particular: java.lang.OutOfMemoryError: unable to create new native thread.
In experiments in MacOS, generally less than 2048 (several tests to 2023), because the default number of threads per process most Mac allocated for 2048. You can use the sysctl kern.num_taskthreadscommand to query. If you need to break through the restrictions can refer to the official solution .
It was found in centOS in max_user_processes and stack size the number of threads parameter will limit each process.

Ref
. [1] Zhou Zhiming depth understanding of the Java Virtual Machine [M] Beijing: Mechanical Industry Press, 53

Original: Big Box  JAVA stack overflow


Guess you like

Origin www.cnblogs.com/chinatrump/p/11597155.html