java -jar 内存溢出_JAVA系统启动栈内存溢出-StackOverflowError

JAVA系统启动栈内存溢出-StackOverflowError

线上服务器启动报错日志如下:

Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [] due to a StackOverflowError. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies. The class hierarchy being processed was [org.bouncycastle.asn1.ASN1EncodableVector->org.bouncycastle.asn1.DEREncodableVector->org.bouncycastle.asn1.ASN1EncodableVector]

at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:2066)

at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2012)

at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1961)

at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1936)

at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1897)

看日志提示是-Xss参数设置过低引起的栈内存溢出,先解释下-Xss参数。

JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右

一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。

但是根据-Xss参数调整栈内存大小之后,再重新启动还是会StackOverflowError。所以栈内存设置过小不是根本原因。

再看下这个错误信息 StackOverflowError,抛出这个错误表明应用程序因为深递归导致栈被耗尽了。

StackOverflowError 是 VirtualMachineError 的扩展类,VirtualMachineError 表明 JVM 中断或者已经耗尽资源,无法运行。

而且,VirtualMachineError 类扩展自 Error 类,这个类用于指出那些应用程序不需捕获的严重问题。因为这些错误是在可能永远不会发生的异常情况下产生,所以方法中没有在它的 throw 语句中声明。

Java 里的 StackOverflowError

Java 应用程序唤起一个方法调用时就会在调用栈上分配一个栈帧, 这个栈帧包含引用方法的参数,本地参数,以及方法的返回地址。

这个返回地址是被引用的方法返回后程序能够继续执行的执行点。如果没有一个新的栈帧所需空间,Java 虚拟机就会抛出 StackOverflowError。

最常见的可能耗光 Java 应用程序的栈的场景是程序里的递归。递归时一个方法在执行过程中会调用自己。 递归被认为是一个强大的多用途编程技术,为了避免出现 StackOverflowError,使用时必须特别小心。

如何处理 StackOverflowError

最简单的解决方案是仔细检查输出信息中的栈路径,查明模式重复的代码行号。这些行号对应的代码被递归调用了。确认这些行后,你必须小心的检查你的代码,弄清楚为什么递归永远不结束。

如果你确认递归实现是正确的,为了允许大量的调用,你可以增加栈的大小。依赖于安装的 Java 虚拟机,默认的线程栈大小可能是 512KB 或者 1MB。你可以使用 -Xss 标识来增加线程栈的大小。这个标识即可以通过项目的配置也可以通过命令行来指定。

-Xss 参数的格式:-Xss[g|G|m|M|k|K]

在看系统启动报错日志信息

The class hierarchy being processed was [org.bouncycastle.asn1.ASN1EncodableVector->org.bouncycastle.asn1.DEREncodableVector->org.bouncycastle.asn1.ASN1EncodableVector]

根据这段提示信息是ASN1EncodableVector 依赖了DEREncodableVector,DEREncodableVector后面又依赖了ASN1EncodableVector ,造成了死循环,导致栈内存消耗殆尽。

然后根据这个类名去项目中搜索查看类结构,根据类名搜索结果如下:

搜索到了两个一模一样的类,由于之前项目启动是没有问题的,而itext-asian-5.2.0.jar 也是最近添加的jar包依赖,所以猜测可能是两个jar包有相同包名的类,导致了死循环依赖,所以直接出现了栈内存溢出问题。

找到了相同的类,那就可以先把项目中没有使用到的bcprov-jdk15-1.43.jar进行排除掉,然后上线,系统启动正常,原来的栈内存溢出问题没有出现。

具体bcprov-jdk15-1.43.jar ASN1EncodableVector 源码如下:

package org.bouncycastle.asn1;

import org.bouncycastle.asn1.DEREncodableVector;

public class ASN1EncodableVector extends DEREncodableVector {

public ASN1EncodableVector() {

}

}

具体itext-asian-5.2.0.jar ASN1EncodableVector 源码如下:

package org.bouncycastle.asn1;

import org.bouncycastle.asn1.ASN1EncodableVector;

public class DEREncodableVector extends ASN1EncodableVector {

/** @deprecated */

public DEREncodableVector() {

}

}

通过源码可以看到ASN1EncodableVector 和DEREncodableVector互为父类和子类,造成了死循环继承。 所以只需要将没有使用的一方jar包依赖排除即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值