大家都知道,java编译器在编译.java文件时,会在.class文件中写入编译的版本信息,供jvm进行检查。比如一个版本为1.7的jvm读到一个经1.6编译器编译的.class文件,它会接受,因为java语言是 向后兼容的
,但是读到一个经1.8编译器编译的.class文件,它就不接受了,因为这个.class文件里的语法或所用jdk类库等在1.7中不支持。
下面来实践一下。
首先了解一下jdk编译器版本及其对应的class文件版本序号:
jdk编译器版本 | 十六进制 | 十进制 |
---|---|---|
1.5 | 0000 0031 | 49.0 |
1.6 | 0000 0032 | 50.0 |
1.7 | 0000 0033 | 51.0 |
1.8 | 0000 0034 | 52.0 |
然后我写了一个非常简单的类,这个类的语法从jdk 1.0就可以使用:
public class App
{
public static void main( String[] args ){
int i =1;
}
}
用jdk 1.7编译它:
一切正常。
然后打开App.class文件,将它的主版本改为1.6的:
然后使用1.7运行,正常运行。
然后再把主版本改为34(十六进制,十进制为52,代表此class文件是由jdk1.8编译的),使用1.7运行,结果如下:
说明jdk1.7不兼容jdk1.8的class文件。
上面表格中1.5版本的十六进制编号是00000031,往前推算,随意修改version的数值,可能会抛出 java.lang.UnsupportedClassVersionError
、java.lang.ClassFormatError
等Error,具体到改成什么数报什么异常,完全弄清也没什么意义,改天下个jvm的源码,看一下sun.launcher.LauncherHelper.checkAndLoadMain
的校验规则吧,因为Error最早是这个方法抛出来的.