大家好,今天小编来为大家解答over flow在线观看免费樱花动漫这个问题,StackOverFlowError很多人还不知道,现在让我们一起来看看吧!
每一个JVM线程都拥有一个私有的JVM线程栈,用于存放当前线程的JVM栈帧(包括被调用函数的参数、局部变量和返回地址等)。如果某个线程的线程栈空间被耗尽,没有足够资源分配给新创建的栈帧,就会抛出`java.lang.StackOverflowError`错误。本文总结了StackOverflowError常见原因及其解决方法,如有遗漏或错误,欢迎补充指正。
线程栈是如何运行的?首先给出一个简单的程序调用代码示例,如下所示:
publicclassSimpleExample{npublicstaticvoidmain(Stringargs[]){na();n}npublicstaticvoida(){nintx=0;nb();n}npublicstaticvoidb(){nCary=newCar();nc();n}npublicstaticvoidc(){nfloatz=0f;n}n}
当`main()`方法被调用后,执行线程按照代码执行顺序,将它正在执行的方法、基本数据类型、对象指针和返回值包装在栈帧中,逐一压入其私有的调用栈,整体执行过程如下图所示:
首先,程序启动后,`main()`方法入栈。然后,`a()`方法入栈,变量`x`被声明为`int`类型,初始化赋值为`0`。注意,无论是`x`还是`0`都被包含在栈帧中。接着,`b()`方法入栈,创建了一个`Car`对象,并被赋给变量`y`。请注意,实际的`Car`对象是在Java堆内存中创建的,而不是线程栈中,只有`Car`对象的引用以及变量`y`被包含在栈帧里。最后,`c()`方法入栈,变量`z`被声明为`float`类型,初始化赋值为`0f`。同理,`z`还是`0f`都被包含在栈帧里。当方法执行完成后,所有的线程栈帧将按照后进先出的顺序逐一出栈,直至栈空为止。
StackOverFlowError是如何产生的?如上所述,JVM线程栈存储了方法的执行过程、基本数据类型、局部变量、对象指针和返回值等信息,这些都需要消耗内存。一旦线程栈的大小增长超过了允许的内存限制,就会抛出`java.lang.StackOverflowError`错误。
下面这段代码通过无限递归调用最终引发了`java.lang.StackOverflowError`错误。
publicclassStackOverflowErrorExample{npublicstaticvoidmain(Stringargs[]){na();n}npublicstaticvoida(){na();n}n}
在这种情况下,`a()`方法将无限入栈,直至栈溢出,耗尽线程栈空间,如下图所示。
Exceptioninthread"main"java.lang.StackOverflowErrorntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)ntatStackOverflowErrorExample.a(StackOverflowErrorExample.java:10)
如何解决StackOverFlowError?
引发`StackOverFlowError`的常见原因有以下几种:
无限递归循环调用(最常见)。执行了大量方法,导致线程栈空间耗尽。方法内声明了海量的局部变量。native代码有栈上分配的逻辑,并且要求的内存还不小,比如`java.net.SocketInputStream.read0`会在栈上要求分配一个64KB的缓存(64位Linux)。除了程序抛出`StackOverflowError`错误以外,还有两种定位栈溢出的方法:
进程突然消失,但是留下了crash日志,可以检查crash日志里当前线程的stack范围,以及RSP寄存器的值。如果RSP寄存器的值超出这个stack范围,那就说明是栈溢出了。如果没有crash日志,那只能通过coredump进行分析。在进程运行前,先执行`ulimit-cunlimited`,当进程挂掉之后,会产生一个core.[pid]的文件,然后再通过`jstack$JAVA_HOME/bin/javacore.[pid]`来看输出的栈。如果正常输出了,那就可以看是否存在很长的调用栈的线程,当然还有可能没有正常输出的,因为jstack的这条从core文件抓栈的命令其实是基于ServiceabilityAgent实现的,而SA在某些版本里有Bug。常见的解决方法包括以下几种:
修复引发无限递归调用的异常代码,通过程序抛出的异常堆栈,找出不断重复的代码行,按图索骥,修复无限递归Bug。排查是否存在类之间的循环依赖。排查是否存在在一个类中对当前类进行实例化,并作为该类的实例变量。通过JVM启动参数`-Xss`增加线程栈内存空间,某些正常使用场景需要执行大量方法或包含大量局部变量,这时可以适当地提高线程栈空间限制,例如通过配置`-Xss2m`将线程栈空间调整为2mb。线程栈的默认大小依赖于操作系统、JVM版本和供应商,常见的默认配置如下表所示:
提示:实际生产系统中,可以对程序日志中的StackOverFlowError配置关键字告警,一经发现,立即处理。
关于over flow在线观看免费樱花动漫的内容到此结束,希望对大家有所帮助。
还没有评论,来说两句吧...