
上QQ阅读APP看书,第一时间看更新
解析版本号
class文件结构的版本号分为主版本号和副版本号,它们共同构成class文件格式的版本号[1]。比如一个class文件的主版本号为56,副版本号为0,那么这个class文件结构的版本号就是52.0。副版本号在前,主版本号在后,分别占两个字节。
版本号解析器的职责就是从class文件字节缓存中读取出副版本号和主版本号。按顺序读取,先读取两个字节的副版本号,再读取两个字节的主版本号。版本号解析器的实现如代码清单2-8所示。
代码清单2-8 版本号解析器
public class VersionHandler implements BaseByteCodeHandler { // 版本号解析器排在魔数解析器的后面 @Override public int order() { return 1; } @Override public void read(ByteBuffer codeBuf, ClassFile classFile) throws Exception { // 读取副版本号 U2 minorVersion = new U2(codeBuf.get(), codeBuf.get()); classFile.setMinor_version(minorVersion); // 读取主版本号 U2 majorVersion = new U2(codeBuf.get(), codeBuf.get()); classFile.setMagor_version(majorVersion); } }
class文件格式的各版本号与JDK版本的对应关系如表2-9所示。
表2-9 各版本的对应关系

现在我们随便找个class文件来编写单元测试,验证框架是否能正确解析出该class文件的魔数和版本号,单元测试如代码清单2-10所示。
代码清单2-10 魔数与版本号解析器单元测试
public class MagicAndVersionTest { @Test public void testMagicAndVersionHandler() throws Exception { // 将class文件读取到ByteBuffer ByteBuffer codeBuf = ClassFileAnalysisMain.readFile("RecursionAlgorithmMain.class"); // 解析class文件 ClassFile classFile = ClassFileAnalysiser.analysis(codeBuf); System.out.println(classFile.getMagic().toHexString()); // 打印模数 System.out.println(classFile.getMinor_version().toInt()); // 打印副版本号 System.out.println(classFile.getMagor_version().toInt()); // 打印主版本号 } }
程序运行结果如图2.3所示。

图2.3 魔数与版本号解析器单元测试
注释:
[1] 《Java虚拟机规范》Java SE8版本ClassFile结构