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

Spring 3.1+OpenJDK11环境下类型转换及数组越界问题求助

问题描述
  • 运行环境:OpenJDK 11、Spring 3.1、Tomcat 8.5

初始代码与ClassCastException

编写了如下监听类:

import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
public class TomcatStopListener extends ContextLoaderListener {
    public void contextDestroyed(ServletContextEvent event) {      
        try {           
            WebApplicationContext context = (WebApplicationContext) event.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
            // 后续代码省略
        } catch (Exception e) {
            // 异常处理省略
        }
    }
}

运行时抛出类型转换异常:

java.lang.ClassCastException: org.springframework.beans.factory.BeanDefinitionStoreException incompatible with org.springframework.web.context.WebApplicationContext
        at com.nsn.servlets.TomcatStopListener.contextDestroyed(TomcatStopListener.java:28)
        at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4811)
        at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5467)

2022年9月26日更新:改用API后出现ArrayIndexOutOfBoundsException

改用WebApplicationContextUtils获取上下文:

WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());

抛出数组越界异常,栈信息如下:

Caused by: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 11560
at org.springframework.asm.ClassReader.readClass(Unknown Source)
at org.springframework.asm.ClassReader.accept(Unknown Source)
at org.springframework.asm.ClassReader.accept(Unknown Source)
at org.springframework.core.type.classreading.SimpleMetadataReader.(SimpleMetadataReader.java:59)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:80)
at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:101)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:237)

解决方案

针对ClassCastException的问题

  1. 问题根源:Spring启动失败时,会将BeanDefinitionStoreException存入WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性,而非正常的WebApplicationContext实例,直接强转触发类型转换异常。
  2. 修复方式:
    • 先判断属性类型再转换:
      Object attr = event.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
      if (attr instanceof WebApplicationContext) {
          WebApplicationContext context = (WebApplicationContext) attr;
          // 执行后续逻辑
      } else {
          // 处理上下文初始化失败的情况,如记录日志
      }
      
    • 利用父类方法直接获取:由于类继承自ContextLoaderListener,可直接调用父类的getWebApplicationContext()方法,无需从ServletContext手动获取:
      @Override
      public void contextDestroyed(ServletContextEvent event) {
          try {
              WebApplicationContext context = getWebApplicationContext();
              if (context != null) {
                  // 执行销毁逻辑
              }
          } catch (Exception e) {
              // 异常处理
          }
          // 调用父类方法,保证Spring销毁流程正常执行
          super.contextDestroyed(event);
      }
      

针对ArrayIndexOutOfBoundsException的问题

  1. 问题根源:Spring 3.1依赖的ASM版本过低,无法兼容OpenJDK 11的字节码格式(Java 11字节码版本为55.0,Spring 3.1默认ASM仅支持到Java 7的51.0版本),解析高版本字节码时出现数组越界。
  2. 修复方式:
    • 升级Spring版本:Spring 3.1已停止维护,建议升级到支持Java 11的版本(如Spring Framework 5.3.x),这是最彻底的解决方案,同时能获得安全更新与新特性。
    • 替换ASM依赖(临时方案):若暂时无法升级Spring,可手动将ASM版本升级到支持Java 11的版本(如ASM 9.x),但需注意此方式存在兼容性风险,需充分测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:48:23