You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tomcat启动抛出StackOverflowError:bouncycastle类循环继承问题咨询

问题根因

你预设的「Tomcat会先完整解析单个jar包内的所有类再处理下一个jar」的前提不成立,Tomcat的SCI类扫描是深度优先递归处理单个类的继承链,处理过程中会跨jar加载父类,加载结果完全由类加载器的类路径优先级决定,具体触发流程如下:

  1. 扫描触发:首先扫描到bcprov-jdk15:1.45版本的ASN1Boolean类,调用三参数重载的populateJavaClassCache存入缓存,该缓存条目记录的父类为DERBoolean(来自1.45版本的类定义)。
  2. 父类加载:接下来递归处理ASN1Boolean的父类DERBoolean,调用单参数重载的populateJavaClassCache加载该类。如果此时类路径中bcprov-jdk15on:1.60的优先级更高,类加载器返回的是1.60版本的DERBoolean字节码。
  3. 循环映射生成:1.60版本的DERBoolean被解析后存入缓存,该条目记录的父类是ASN1Boolean(来自1.60版本的类定义)。
    此时缓存中已经形成了完整的循环继承映射:
  • org.bouncycastle.asn1.ASN1Boolean → 父类org.bouncycastle.asn1.DERBoolean
  • org.bouncycastle.asn1.DERBoolean → 父类org.bouncycastle.asn1.ASN1Boolean
  1. 栈溢出触发:populateSCIsForCacheEntry方法的核心逻辑是递归遍历类的父类和接口链,匹配@HandlesTypes注解声明的需要处理的类型,遍历到这两个类时直接进入死递归,最终抛出StackOverflowError。

之前的推导误区说明

你认为缓存不会重复存入同全类名的类确实没错,两个类的缓存条目都不会被覆盖,但两个条目分别来自不同版本的类定义,各自的父类指向刚好形成闭环,和你假设的「先全量加载完单个jar所有类再处理下一个jar」的执行顺序完全不一致,因此你预判的「缓存中不存在循环映射」的结论不成立。

内容的提问来源于stack exchange,提问作者Jadic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 22:42:01