zoukankan      html  css  js  c++  java
  • spring3.*和jdk8版本冲突问题及解决方案

    背景描述

    15年的一个老系统,使用的ssh框架,在1.6jdk下运行了五年,最近因部署环境切换,新环境对JDK版本统一升级为1.8版本,在1.8版本jdk下,系统启动报错。

    (整个问题排查过程由新环境平台厂商大牛整理,并征求同意后发出来。)

    问题概述

    先说结论和解决方案:

    • 问题描述:spring3.* 版本不支持JDK8,启动时报错。

    • 问题原因:spring使用asm类库操作Java class文件,spring3.* 依赖的asm类库版本比较老,而JDK8之后Java class格式有变化,老版本的asm类库不能支持导致报错。

    • 解决方式和建议:

      1. 升级spring到spring4以上版本(新应用或老应用大改推荐)

        • spring4开始正式支持JDK8,实际是升级了配套的asm类库到可以支持JDK8的版本

        • 适用于新应用(新应用也强烈不建议使用spring3版本)

        • 对于老应用从spring3升级到spring4/5可能会引发很多兼容性的问题,最好是整个spring生态一起升级到新版本,但这样工作量会比较大,因此只适合老应用大改。

      2. 升级spring到spring3.2.18版本(老应用小改推荐):

        • Spring3.2.18版本是spring3系列最后一个版本

        • 保持了spring3的兼容性,同时asm类库也升级到了可以支持JDK8的版本

        • 可以比较好的平衡:改动量小,能解决spring3和jdk8的冲突问题,又不必让老应用面临升级spring4大版本的风险

      3. 降级JDK到7(老应用完全改不了的最后方案)

        • 不建议采用,JDK7过于陈旧,而且会导致后续没法使用JDK8的特性和支持这些特性的类库

        • 偏离主流技术栈(统一使用JDK8),增加开发运维的复杂度

        • 建议:只有在上面两个方法都无法使用时,不得已而为之的最后备选方案

    问题排查

    如果对这个问题的细节有兴趣,请细看下面的内容。

    问题原始错误信息和输入

    JDK 8和spring 3.x不匹配,应用在启动时初始化spring时报错,实际异常如下:

     

    问题分析

    从异常信息看,是spring在启动初始化时,通过 spring-asm 类库操作Java class文件时报错:

    Caused by: java.lang.IllegalArgumentException
        at org.springframework.asm.ClassReader.<init>(Unknown Source)
        at org.springframework.asm.ClassReader.<init>(Unknown Source)
        at org.springframework.asm.ClassReader.<init>(Unknown Source)
        at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:52)
        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:257)
        ... 47 more
    

    Spring官方对这个问题的分析:

    IllegalArgumentException initializing an application compiled with Java 8:

    社区2013年就报告了这个版本冲突问题,从分析上看是spring使用的 asm 类库版本太低,而JDK8之后Java class格式有变化,老版本的asm类库不能支持处理 Jdk8 的class文件导致报错抛异常。

    ASM类库介绍

    特别高亮一下 ASM 类库,ASM 是Java社区广泛使用的Java字节码操作和分析框架工具,可以用来修改已有的java class文件或者动态生成java class。

    ASM对java 8的支持,始于 2013年10月发布的 asm 5.0 bata 版本:

    因此,要解决和JDK8的版本冲突问题,就必须升级spring配套的asm类库到asm5.0版本。

    Spring使用ASM类库的方式

    Spring重度依赖ASM,但spring使用ASM类库的方式比较特殊,历史上有三次变更:

    1. 直接使用官方ASM(spring1和spring2):

      这是普通使用jar包依赖的方式,在spring 的maven依赖中引入asm,以spring 2 最后一个版本 spring 2.5.6为例:

       <dependency>
                  <groupId>asm</groupId>
                  <artifactId>asm</artifactId>
                  <version>2.2.3</version>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>asm</groupId>
                  <artifactId>asm-commons</artifactId>
                  <version>2.2.3</version>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>asm</groupId>
                  <artifactId>asm-util</artifactId>
                  <version>2.2.3</version>
                  <optional>true</optional>
              </dependency>

      注意 asm.jar 中的 java package 名是 org.objectweb.asm

    2. spring-asm(spring3.0和spring3.1版本)

      Spring3之后没有再按照普通的方式使用asm官方类库,而是做了一次 repackge,将asm的java package 从 org.objectweb.asm 改名为 org.springframework.asm,然后打包并发布为单独的 spring-asm 类库如 spring-asm-3.0.5.RELEASE.jar

      对比如下图:

      在这里可以看到 spring-asm 类库的历史版本记录,从3.0.0版本开始,到3.1.4版本结束:

      https://repo.spring.io/release/org/springframework/spring-asm/

    3. asm in spring-core(spring3.2及之后的版本)

      在spring3.2版本之后,spring修改了repackage asm的方式,package名维持不变,但是不再使用 spring-asm 这样的单独类库,而是把 asm 的内容打包到了 spring-core 中:

      spring3.2系列早期版本repackage 的是 asm 4.0 版本,依然不支持jdk8;但在后期版本(应该是从3.2.14或者3.2.16)开始就repackage了支持 asm 5.0版本。

      从 spring 的 java docs 文档中可以看到:

      https://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/asm/package-summary.html

      Spring's repackaging of org.objectweb.asm 5.0 (for internal use only).

      简单和安全起见,升级到3.2最后一个版本 3.2.18 是可以确认支持jdk8。

    问题验证

    出现问题的应用,使用的spring版本是 spring 3.0.5 ,配套的spring-asm 3.0.5 对应的asm是3.0版本,不支持jdk8,因此报错。

    验证了以下几种解决方案:

    • 降级JDK到7版本,验证通过:使用了Orcale JDK7U80版本,这是JDK7最后一个小版本

    • 升级spring到3.2.18版本,验证通过

    参考资料

     

  • 相关阅读:
    java web 工程更改名字
    [转]Eclipse下开发Struts奇怪异常:org.apache.struts.taglib.bean.CookieTei
    【转】myeclipse 自定义视图Customize Perspective 没有反应
    latex建立参考文献的超链接
    latex 脚注编号也成为超链接
    自定义标签TLD文件中,rtexprvalue子标签的意思
    设计模式观察者
    设计模式模板方法
    设计模式策略
    设计模式享元
  • 原文地址:https://www.cnblogs.com/rimmy/p/13849225.html
Copyright © 2011-2022 走看看