一个简单的解析类文件(*.Class)的编译版本的小程序:
public static void main(String args[]) throws Exception { Map<Integer, String> vers = new HashMap<Integer, String>(); vers.put(49, "JDK_5"); vers.put(50, "JDK_6"); vers.put(51, "JDK_7"); vers.put(52, "JDK_8"); // 也可以使用 ASM 读取类的版本号,经测试ASM读取的版本与本程序结果一致。 // ASM 支持的 JDK 版本 // System.out.println(Opcodes.V1_5); // System.out.println(Opcodes.V1_6); // System.out.println(Opcodes.V1_7); // System.out.println(Opcodes.V1_8); // 读取文件数据,文件是当前目录下的First.class FileInputStream fis = new FileInputStream("/test.class"); byte[] data = new byte[fis.available()]; // 读取文件到字节数组 fis.read(data); fis.close(); // 解析主版本号和次版本号码 // int minor_version = (((int) data[4]) << 8) + data[5]; int major_version = (((int) data[6]) << 8) + data[7]; System.out.println("编译版本:" + vers.get(major_version)); }
每个合法的 Java 类文件都具备精确的定义,而正是这种精确的定义,才使得 Java 虚拟机得以正确读取和解释所有的 Java 类文件。
Java 类文件是 8 位字节的二进制流。数据项按顺序存储在 class 文件中,相邻的项之间没有间隔,这使得 class 文件变得紧凑,减少存储空间。在 Java 类文件中包含了许多大小不同的项,由于每一项的结构都有严格规定,这使得 class 文件能够从头到尾被顺利地解析。下面让我们来看一下 Java 类文件的内部结构,以便对此有个大致的认识。
例如,一个最简单的 Hello World 程序:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world"); } }
从上图中可以看到,一个 Java 类文件大致可以归为 10 个项:
使用 ASM ,开发者不需要熟知 class 文件的每一段,以及它们的功能、长度、偏移量以及编码方式,ASM 会给我们照顾好这一切。
使用ASM5解析Class文件的编译版本:
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; import java.io.*; import java.util.HashMap; import java.util.Map; public class ClassInfoPrinter extends ClassVisitor { public ClassInfoPrinter() { super(Opcodes.ASM5); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { Map<Integer, String> vers = new HashMap<Integer, String>(); vers.put(49, "JDK_5"); vers.put(50, "JDK_6"); vers.put(51, "JDK_7"); vers.put(52, "JDK_8"); System.out.println("编译版本:" + vers.get(version)); } public static void main(String[] args) throws IOException { ClassReader classReader = new ClassReader(new FileInputStream("/test.class")); classReader.accept(new ClassInfoPrinter(), ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES + ClassReader.SKIP_CODE); } }
详细:http://www.ibm.com/developerworks/cn/java/j-lo-asm30/index.html