一次StackOverFlow问题的排查记录

起因

做为公司的基础架构,要负责给其他的项目组搭建内网的项目,今天在给一个项目搭建内网测试环境的时候,项目无法正常启动,报StackOverflow的问题,问项目负责的开发,他说本地可以正常启动的,但是需要加一个特殊的jvm启动参数 -Xss2m

排查

项目下载下来以后,首先编译就是一个问题,有报了OutOfMemoryError,然后按文档处理配置了内存以后,继续排查。

IDEA编译报错:java.lang.OutOfMemoryError: Java heap space和java.lang.StackOverflowError
https://blog.youkuaiyun.com/ForeverAnt/article/details/90209554

既然已经知道了结果了,所以就想从结果查起,想知道-Xss这个参数到底有什么用户,就查了一下 xss到底是什么,大意就是

-Xss 参数为设置单个线程栈的大小,不同系统(linux,win,mac)以及不同的架构 64位及32位,默认的设置都不一样,mac和Linux默认的的是1024k`

Each thread in a Java application has its own stack. The stack is used to hold return addresses, function/method call arguments, etc. So if a thread tends to process large structures via recursive algorithms, it may need a large stack for all those return addresses and such. With the Sun JVM, you can set that size via that parameter.
Java应用程序中的每个线程都有其自己的堆栈。 堆栈用于保存返回地址,函数/方法调用参数等。因此,如果线程倾向于通过递归算法处理大型结构,则所有这些返回地址等都需要大型堆栈。 使用Sun JVM,可以通过该参数设置该大小

JVM option -Xss - What does it do exactly?
https://stackoverflow.com/questions/4967885/jvm-option-xss-what-does-it-do-exactly

JVM常用基础参数栈内存Xss讲解
https://blog.youkuaiyun.com/qq_33229669/article/details/103937083

知道了大概的意思以后,我就想,既然是内存的问题,那是不是就得分析一下,用MAT(Eclipse Memory Analyzer) dump一下分析了看看,idea装了visualvm插件后配置了一下jdk的visualvm的地址,以后, 在idea的启动栏里面就有了启动并分析的按钮了,点了这个启动以后,就能有应用内存和线程的监控视图了,然后点击堆dump按钮,还能dump出当前的应用的内存进行分析,将dump出的.hprof 文件导入到 MAT 软件里面,就能进行另一项目分析了(MAT的有内存泄漏检查的提示,比visualvm的提示更详细一些)
在这里插入图片描述
在这里插入图片描述
然后就看到了,内存对象中最大的竟然是superssedExceptions的一个map
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后我就进行不下去了,因为在程序启动以后,会出这个异常,我不知道这个异常是起因还是结果,我猜测的是结果,因为StackOverflow了,所以导致出了非常非常多的BeanCreationException,导致内存也不断的涨啊涨啊涨的,这个问题排查了两天,还是从结果出发进行排查的,结果还是没排查出来。后面研究虚拟机的时候,看看能不能回头再想想这个问题。

结论:如果出现了StackOverFlow的问题,可以尝试增加-Xss的参数。

另外:在排查过程中,我使用了一个之前排查别的问题中发现的方法,如果别的包中的类,需要进行调试,或者加输出,在当前的项目中,增加一个与该类相同的包的目录,然后将该类的源码拷到这个目录中,然后在里面增加日志输出或者是打断点,因为类加载是有先后顺序的,同包同类的情况下后面加载的会覆先加载的,而且项目本身的类是最后加载的,所以这是一个小技巧,在排查问题的时候可以使用。

就这样吧,遇到不好解决的问题,就算查到了解决方法的文档,也要自己写一遍或者拷到自己的收藏中一份,人生没有白走的路。

与错误相关文章
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8061621	
mac java visualvm_IDEA安装 VisualVM 及使用
https://blog.youkuaiyun.com/sinat_24230393/article/details/93596359
VisualVM 使用
https://www.cnblogs.com/happy-rabbit/p/6232581.html
使用 VisualVM 和 JProfiler 进行性能分析及调优
https://cloud.tencent.com/developer/article/1648995
JVM heap dump分析
https://www.jianshu.com/p/c34af977ade1
eclipse-memory-analyzer使用说明
https://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/
### OssClient 创建实例时出现 StackOverflowError 的解决方案 当遇到 `NestedServletException` 和 `Handler dispatch failed; nested exception is java.lang.StackOverflowError` 错误时,通常表明程序中存在某种无限递归调用或循环依赖问题。以下是针对此问题的具体分析和解决办法: #### 1. **检查是否存在循环依赖** 在 Spring 应用中,如果两个 Bean 或多个组件之间形成了循环依赖关系,则可能导致栈溢出错误。对于 OssClient 实例化过程中可能出现的此类问题,需仔细审查其构造函数以及初始化逻辑。 - 如果 OssClient 是通过自定义工厂方法或其他方式注入到其他 Bean 中,请确认这些 Bean 是否间接引用了彼此,从而形成闭环[^3]。 ```java @Bean public OssClient ossClient() { return new OssClient(); } ``` 上述代码片段展示了如何声明一个简单的 Bean 定义。然而,在实际项目中可能涉及复杂的依赖链路,因此建议启用调试模式并打印完整的堆栈跟踪信息以便定位具体位置。 #### 2. **排查重载方法中的潜在风险** 某些情况下,开发者可能会无意间覆盖父类的关键方法(如 `toString()`、`hashCode()` 或者 `equals()`),而未正确实现它们的功能。这同样会引发类似的异常行为。 假设我们在扩展阿里云 OSS SDK 提供的基础功能时重新实现了某个核心方法却忽略了边界条件处理: ```java @Override public String toString() { return this.toString(); // 死循环! } ``` 上面的例子清楚地说明了一个典型的编程失误——自我调用造成无穷回归最终耗尽内存资源进而抛出 `StackOverflowError` 异常[^4]。 为了避免这种情况发生,应当遵循标准约定来编写这些特殊用途的方法体内容,并利用单元测试验证预期效果。 #### 3. **优化复杂对象图结构** 当应用程序操作的数据模型较为庞大且相互关联紧密的时候,也可能因为序列化或者反序列化的不当设计而导致性能瓶颈甚至崩溃现象。特别是 MyBatis 批量查询场景下传入过多嵌套字段作为筛选依据时更容易触发该类问题[^5]。 为此可以采取以下措施缓解压力: - 减少不必要的属性加载; - 使用 DTO (Data Transfer Object) 转换机制隔离原始实体与外部表现形式之间的差异; - 对于特别大的集合数据考虑分页获取而非一次性读取全部记录。 #### 4. **修正配置文件语法错误** 最后还有一种可能性来源于框架本身的设置项解析失败所引起的连锁反应。比如前面提到过的 Spring Security 配置案例就是因为拼写上的小小疏忽致使整个认证流程无法正常启动运行。 所以务必认真核对所有涉及到第三方库集成部分的相关参数设定是否准确无误。 --- ### 总结 综上所述,要彻底根除因创建 OssClient 实例而导致的 `StackOverflowError` 故障,可以从以下几个方面入手逐一排除隐患:消除任何显式或隐式的循环依赖状况;谨慎对待继承体系内的基础成员函数改写工作;合理规划大型业务系统的内部交互架构以提升效率降低负载;严格把控各项技术选型配套文档资料的学习掌握程度确保不出差错。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值