package example.test;
public final class TestClass {
public int id = 1234567;
public void test() {}
}
然后编译,放在C:\example\test\Test.class。
我们用Java来读取和分析class,ClassAnalyzer的功能便是读取Test.class,分析结构,然后显示出来:
package classfile.format;
import java.io.*;
public class ClassAnalyzer {
public static void main(String[] args) {
DataInputStream input = null;
try {
input = new DataInputStream(new BufferedInputStream(new FileInputStream(
"C:\\example\\test\\TestClass.class"
)));
analyze(input);
}
catch(Exception e) {
System.out.println("Analyze failed!");
}
finally {
try { input.close(); } catch(Exception e) {}
}
}public static void analyze(DataInputStream input) throws IOException {
// read magic number:
int magic = input.readInt();
if(magic==0xCAFEBABE)
System.out.println("magic number = 0xCAFEBABE");
else
throw new RuntimeException("Invalid magic number!");
// read minor version and major version:
short minor_ver = input.readShort();
short major_ver = input.readShort();
System.out.println("Version = " + major_ver + "." + minor_ver);
// read constant pool:
short const_pool_count = input.readShort();
System.out.println("constant pool size = " + const_pool_count);
// read each constant:
for(int i=1; i<const_pool_count; i++) {
analyzeConstant(input, i);
}
}public static void analyzeConstant(DataInputStream input, int index) throws IOException {
byte flag = input.readByte();
// for read:
byte n8;
short n16;
int n32;
long n64;
float f;
double d;
byte[] buffer;
System.out.println("\nconst index = " + index + ", flag = " + (int)flag);
switch(flag) {
case 1: // utf-8 string
System.out.println(" const type = Utf8");
n16 = input.readShort();
System.out.println(" length = " + n16);
buffer = new byte[n16];
input.readFully(buffer);
System.out.println(" value = " + new String(buffer));
break;
case 3: // integer
System.out.println(" const type = Integer");
n32 = input.readInt();
System.out.println(" value = " + n32);
break;
case 4: // float
System.out.println(" const type = Float");
f = input.readFloat();
System.out.println(" value = " + f);
break;
case 5: // long
System.out.println(" const type = Long");
n64 = input.readLong();
System.out.println(" value = " + n64);
break;
case 6: // double
System.out.println(" const type = Double");
d = input.readDouble();
System.out.println(" value = " + d);
break;
case 7: // class or interface reference
System.out.println(" const type = Class");
n16 = input.readShort();
System.out.println(" index = " + n16 + " (where to find the class name)");
break;
case 8: // string
System.out.println(" const type = String");
n16 = input.readShort();
System.out.println(" index = " + n16);
break;
case 9: // field reference
System.out.println(" const type = Fieldref");
n16 = input.readShort();
System.out.println("class index = " + n16 + " (where to find the class)");
n16 = input.readShort();
System.out.println("nameAndType = " + n16 + " (where to find the NameAndType)");
break;
case 10: // method reference
System.out.println(" const type = Methodref");
n16 = input.readShort();
System.out.println("class index = " + n16 + " (where to find the class)");
n16 = input.readShort();
System.out.println("nameAndType = " + n16 + " (where to find the NameAndType)");
break;
case 11: // interface method reference
System.out.println(" const type = InterfaceMethodref");
n16 = input.readShort();
System.out.println("class index = " + n16 + " (where to find the interface)");
n16 = input.readShort();
System.out.println("nameAndType = " + n16 + " (where to find the NameAndType)");
break;
case 12: // name and type reference
System.out.println(" const type = NameAndType");
n16 = input.readShort();
System.out.println(" name index = " + n16 + " (where to find the name)");
n16 = input.readShort();
System.out.println(" descripter = " + n16 + " (where to find the descriptor)");
break;
default:
throw new RuntimeException("Invalid constant pool flag: " + flag);
}
}
}
输出结果为:
magic number = 0xCAFEBABE
Version = 48.0
constant pool size = 22const index = 1, flag = 1
const type = Utf8
length = 22
value = example/test/TestClassconst index = 2, flag = 7
const type = Class
index = 1 (where to find the class name)const index = 3, flag = 1
const type = Utf8
length = 16
value = java/lang/Objectconst index = 4, flag = 7
const type = Class
index = 3 (where to find the class name)const index = 5, flag = 1
const type = Utf8
length = 2
value = idconst index = 6, flag = 1
const type = Utf8
length = 1
value = Iconst index = 7, flag = 1
const type = Utf8
length = 6
value = <init>const index = 8, flag = 1
const type = Utf8
length = 3
value = ()Vconst index = 9, flag = 1
const type = Utf8
length = 4
value = Codeconst index = 10, flag = 12
const type = NameAndType
name index = 7 (where to find the name)
descripter = 8 (where to find the descriptor)const index = 11, flag = 10
const type = Methodref
class index = 4 (where to find the class)
nameAndType = 10 (where to find the NameAndType)const index = 12, flag = 3
const type = Integer
value = 1234567const index = 13, flag = 12
const type = NameAndType
name index = 5 (where to find the name)
descripter = 6 (where to find the descriptor)const index = 14, flag = 9
const type = Fieldref
class index = 2 (where to find the class)
nameAndType = 13 (where to find the NameAndType)const index = 15, flag = 1
const type = Utf8
length = 15
value = LineNumberTableconst index = 16, flag = 1
const type = Utf8
length = 18
value = LocalVariableTableconst index = 17, flag = 1
const type = Utf8
length = 4
value = thisconst index = 18, flag = 1
const type = Utf8
length = 24
value = Lexample/test/TestClass;const index = 19, flag = 1
const type = Utf8
length = 4
value = testconst index = 20, flag = 1
const type = Utf8
length = 10
value = SourceFileconst index = 21, flag = 1
const type = Utf8
length = 14
value = TestClass.java
我们暂时只读取到constant pool,后面的信息下次再继续 :)
参考:《Inside the Java Virture Mechine》