最近搞的一个项目,是使用Ant进行编译和打包的,发布到Linux服务器的Tomcat下运行。tomcat启动后,观察日志发现以下异常Unsupported major.minor version 52.0,项目无法访问。

当大家在日志中看到Unsupported major.minor version 52.0这个字样的时候,有一些开发经验的同学第一时间就能反映出应该是jdk版本的问题造成的,但是具体造成的原因是什么呢?去网上找解决方案,大多数都是只言片语,在这里总结一下问题处理过程。
1. 分析异常
1.1 环境分析
本地开发环境
- Ant 版本:1.9.15
- JAVA环境:1.8.0_241
服务器环境 - JAVA环境:1.7.0_80
- tomcat版本:7.0.90
在本地使用Ant进行源码编译,并打war包,发布到服务器上的tomcat下运行。
1.2 异常字面分析
Unsupported major.minor version 52.0,意思就是服务器上的jdk1.7,在加载编译好的Class文件的时候,发现Class文件版本是52.0,无法支持这个版本。有如下的问题需要逐个明确
- 52.0这个版本是哪来的?
我们在使用某一个JDK版本,使用javac命令进行编译的时候,生成的Class文件中会对编译的时使用的JDK版本进行标记的。这个52.0就是标记,标记与JDK版本是有一个对应关系的,具体如下:
Java SE 8 = 52,
Java SE 7 = 51,
Java SE 6.0 = 50,
Java SE 5.0 = 49,
JDK 1.4 = 48,
JDK 1.3 = 47,
JDK 1.2 = 46,
JDK 1.1 = 45
通过这个对应关系,就可以分析出,要加载的Class文件是使用JDK8编译的。- 如果我们不知道Class是哪个版本的JDK编译的,如何主动去查询?
使用javap -v User.java命令:

- 如果我们不知道Class是哪个版本的JDK编译的,如何主动去查询?
- 为什么jdk7就不能运行jdk8编译的class类
这里涉及到Java中的向下兼容的概念,向下兼容的意思就是高版本的JAVA环境能够运行低版本编译的CLASS文件,相反不能。
具体原因是,java版本从低到高1.5<1.6<1.7<1.8,每升级一个版本jdk都会增加新的特性,因此如果使用的jdk版本是1.8编写的代码,有一些特性在低版本中是没有的。因此低版本的的虚拟机,比如1.7版本,不包含1.8中的新特性,当遇到这些新特性的时候,它是无法弄明白的,因此无法运行1.8编译的Class文件。
2. 解决思路
通过上文的分析,我们得出了结论,我们在开发环境使用了1.8对Java源码进行了编译,而要在服务器上使用1.7环境运行。这时行不通的。那么我们要解决该问题,从以下几个方面
2.1 修改源码编译时使用的JDK版本
- 我们使用Ant进行源码的编译,因此要去Ant中设置使用1.7版本。
- 查看一下build.xml,如果对于ant的配置文件不熟悉见我的另一篇博客Ant配置文件详解及项目应用
<target name="complie" depends="init">
<javac srcdir="${src}" destdir="${build}/WEB-INF/classes" encoding="utf-8" classpathref="classpath" includeantruntime="on"></javac>
</target>
- 我们发现
<javac>标签上并没有设置,那么默认情况下ant使用javac进行编译的时候用的是什么jdk版本呢?默认的使用的是系统配置的JDK版本,也就是环境变量中设置的JAVA版本。本地环境中安装的jdk版本是1.8,因此在使用上述配置的时候,会使用1.8版本进行编译。 - 那么我们要指定具体的JDK版本进行编译,需要按照如下的设置:
<target name="complie" depends="init">
<javac target="1.7" source="1.7" srcdir="${src}" destdir="${build}/WEB-INF/classes" encoding="utf-8" classpathref="classpath" includeantruntime="on"></javac>
</target>
-
实际上就是增加了javac的两个参数,ant底层也是使用的javac命令实现编译的,那么target和source这两个参数的区别是什么呢?
source:指定用哪个版本的编译器对java源码进行编译
target:指定生成的class文件将保证和哪个版本的虚拟机进行兼容 -
这里有值得注意的点,通过source和target指定的jdk版本,只能小于等于系统安装的jdk版本。
- 比如系统安装的是1.8,那么可以指定1.8、1.7、1.6、1.5都可以。
- 但是系统安装的是1.7,如果指定的是1.8,那么就会报错

2.2 处理结果
修改完配置后,执行ant命令,然后发布到服务器上的tomcat下,启动成功。
我们看一下,现在Class中的编译版本标识,已经改为51了,也就是1.7编译了

本文详细介绍了在使用Ant编译项目时遇到的JDK版本不匹配问题,导致服务器上的Tomcat无法运行编译后的Class文件。通过对异常的分析,明确了问题在于使用JDK8编译的Class文件在JDK7环境下运行。解决方案是修改Ant的build.xml配置,指定使用JDK7进行编译,并解释了source和target参数的作用。经过配置调整,成功解决了问题。
2848

被折叠的 条评论
为什么被折叠?



