乐趣区

存疑-JVMCFRE003-bad-major-version-offset6

今天 Deploy 静态资源包到我们 Production 环境, package 中只涉及到静态资源文件, 例如数据库连接信息, SQL 查询语句等. 成功部署后, 启动服务报错如下:

Exception in thread "main" java.lang.UnsupportedClassVersionError: JVMCFRE003 bad major version; class=support/operations/gtm/iosbackendmanager/BackendManager, offset=6
    at java.lang.ClassLoader.defineClassImpl(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:324)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:155)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:715)
    at java.net.URLClassLoader.access$400(URLClassLoader.java:94)
    at java.net.URLClassLoader$ClassFinder.run(URLClassLoader.java:1169)
    at java.security.AccessController.doPrivileged(AccessController.java:492)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:598)
    at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:777)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:750)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:341)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:731)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
</verbosegc>

经过分析和排查, 我们认为是本地 RAD(eclipse 的一种)的 JDK level 问题, server 上 java 版本是 1.7, Ant 打包涉及的 source 和 target 均是 1.7, 但本地 RAD 的 JDK 编译版本是 1.8, 将其改为 1.7, 打包部署后, 进程正常启动.


对这个问题, 网络上普遍的说法是 ”是因为我们使用高版本的 JDK 编译的 Java class 文件试图在较低版本的 JVM 上运行” , 所以解决办法通常都是更改本地 JDK 编译环境, 很典型的例子是这个: UnsupportedClassVersionError: JVMCFRE003 bad major version in WebSphere AS 7 . 但在这个 case 里, 我 deploy 的部分不涉及任何已编译的 class. 所以在此存在两个疑问:

  1. offset= 6 是什么意思?
  2. JDK 编译环境版本是否会影响静态资源的编译?

这也是第一次使用自动化打包和部署工具 (UCD) 来部署这一部分. 因为是生产环境, 所以在做这个 Change 之前还是比较紧张的, 预想的问题主要有两个:
1, Deploy process 问题, 2, 静态资源乱码问题.
第一个确实出了一点故障, 没有 bin 路径的改动, 但在 process 的步骤里没有选择 ”allow failure”, 所以在复制 bin 文件夹时会报文件夹为空的错并停止运行. 选上 allow failure 即可.
2, 乱码问题是一如既往, 而这个版本的更改中更是涉及到了有 currency 符号: “¤”. 所以只能文件以东欧编码 ISO-8859- 2 形式保存. 这还需要更多的调查, 源码对于 utf8 和其他格式编码的处理逻辑.
这次是预想的问题都没有发生, 反而出现奇奇怪怪的问题, 搞的大家都很紧张, 好在问题已经解决. 不过还需要更多的调查.

how to check the jdk version used to compile a .class file – duplicate

退出移动版