import java.io.*;
public class ClassAnalyzer
{
public static StringBuffer sb = new StringBuffer();
public static byte[] analyzeConstant_tag;
public static String[] analyzeConstant_utf8;
public static DataOutputStream dataout;
public static void main(String[] args)
{
DataInputStream input = null;
try {
FileOutputStream out = new FileOutputStream("C:\\Documents and Settings\\Administrator\\桌面\\解析class文件\\ReadClass.tmp");
BufferedOutputStream buffout = new BufferedOutputStream(out);
dataout = new DataOutputStream(buffout);
input = new DataInputStream(new BufferedInputStream(new FileInputStream(
"C:\\Documents and Settings\\Administrator\\桌面\\解析class文件\\TestClass.class"
)));
//获取文件大小
FileSize(new DataInputStream(new BufferedInputStream(new FileInputStream(
"C:\\Documents and Settings\\Administrator\\桌面\\解析class文件\\TestClass.class"
))));
//解析数据
analyze(input);
}
catch (Exception e) {
System.out.println("解析失败!");
} finally {
try { input.close(); dataout.close();} catch (Exception e) {}
}
}
public static void FileSize(DataInputStream input) throws IOException {
int length = 0; //长度,字节,B
double kblength = 0.0D; //长度,千字节,KB
while (input.read() != -1)
++length;
kblength = length / 1024.0D;
System.out.println("文件大小(字节):" + length + "\n文件大小(KB):" + kblength);
input.close();
}
public static void analyze(DataInputStream input) throws IOException
{
// 读取幻数
int magic = u4(input);
if (magic == 0xCAFEBABE) //-889275714
System.out.println("magic number = 0xCAFEBABE -----标准class文件");
else {
throw new RuntimeException("无效的幻数!");
}
// 读取副、主版本号
int minor_ver = u2(input);
int major_ver = u2(input);
System.out.println("Version = " + major_ver + "." + minor_ver);
add(" 常规信息 ");
add("Minor version: " + minor_ver);
add("Major version: " + major_ver);
// 读取常量池表中表项的个数
short const_pool_count = u2(input);
System.out.println("constant pool size = " + const_pool_count);
add("Constant pool count: " + const_pool_count);
// 读取每个常量
analyzeConstant_tag = new byte[const_pool_count]; //存储常量数据类型
analyzeConstant_tag[0] = 0; //系统保留,class中不存在
for (int i = 1; i < const_pool_count; ++i)
analyzeConstant(input, i); //分析常数
jiexitmp(); //解析tmp文件
// 读取Class的声明中使用的修饰符掩码并解析
short access_flags = u2(input);
System.out.print("access_flags = " + access_flags);
String access_flags_16= "0x"+Integer.toHexString(access_flags);
int[] access = {0x0001,0x0010, 0x0020,0x0200,0x0400};
String[] access_str = {"public","final","","interface","abstract"}; //NO.2--super
String access_tmp = "";
for(int i=0;i
{
if((access_flags & access[i]) == access[i])
{
if(i == 0)access_tmp += access_str[i];
else if(i != 2)access_tmp += " " + access_str[i];
}
}
System.out.println(" [" + access_tmp + " ]");
add("Access flags: " + access_flags_16 + " [" + access_tmp + " ]");
//读取类或者接口的全限定名称
short this_class_index = u2(input);
short super_class_index = u2(input);
System.out.println("This class = " + this_class_index);
System.out.println("Super class = " + super_class_index);
add("This class: " + this_class_index);
add("Super class: " + super_class_index);
// read interfaces count:
short interfaces_count = u2(input);
System.out.println("超接口个数 = " + interfaces_count);
add("Interfaces count: " + interfaces_count);
// read each interface:
for(int i=1; i<=interfaces_count; i++) {
short interface_index = u2(input);
System.out.println("No. " + i + " interface index = " + interface_index);
}
}
public static byte u1(DataInputStream input) throws IOException
{
return input.readByte();
}
public static Short u2(DataInputStream input) throws IOException
{
return input.readShort();
}
public static int u4(DataInputStream input) throws IOException
{
return input.readInt();
}
public static long u8(DataInputStream input) throws IOException
{
return input.readLong();
}
public static void add(String str) throws IOException
{
sb.append(str+"\n");
}
public static void analyzeConstant(DataInputStream input, int index) throws IOException {
// 用于读:
byte n8;
short n16;
int n32;
long n64;
float f;
double d;
byte[] buffer;
byte tag = input.readByte(); //读取数据类型标签
analyzeConstant_tag[index] = tag; //存储常量数据类型
System.out.println("\n常量索引 = " + index + ", 数据类型标签 = " + (int)tag);
switch(tag)
{
case 1: // utf-8 string
System.out.println(" 常量类型 = Utf8 //Utf8存储格式"); //Utf8存储格式
n16 = u2(input);
System.out.println(" length = " + n16);
dataout.writeShort(n16);
buffer = new byte[n16];
input.readFully(buffer); //数组读满才返回
System.out.println(" value = " + new String(buffer));
dataout.writeUTF(new String(buffer));
break;
case 3: // integer
System.out.println(" 常量类型 = Integer //Integer存储格式"); //Integer存储格式
n32 = u4(input);
System.out.println(" value = " + n32);
dataout.writeInt(n32);
break;
case 4: // float
System.out.println(" 常量类型 = Float //Float存储格式"); //Float存储格式
f = u4(input);//input.readFloat();
System.out.println(" value = " + f);
dataout.writeFloat(f);
break;
case 5: // long
System.out.println(" 常量类型 = Long //Long存储格式"); //Long存储格式
n64 = u8(input);
System.out.println(" value = " + n64);
dataout.writeLong(n64);
break;
case 6: // double
System.out.println(" 常量类型 = Double //Double存储格式"); //Double存储格式
d = u8(input);
System.out.println(" value = " + d);
dataout.writeDouble(d);
break;
case 7: // class or interface reference
System.out.println(" 常量类型 = Class //类索引"); //类索引
n16 = u2(input);
System.out.println(" index = " + n16 + " (在哪里可以找到类名)");
dataout.writeShort(n16);
break;
case 8: // string
System.out.println(" 常量类型 = String //字符串索引"); //字符串索引
n16 = u2(input);
System.out.println(" index = " + n16);
dataout.writeShort(n16);
break;
case 9: // field reference
System.out.println(" 常量类型 = Fieldref //领域参数"); //领域参数
n16 = u2(input);
System.out.println("class index = " + n16 + " (在哪里可以找到类名)");
dataout.writeShort(n16);
n16 = u2(input);
System.out.println("nameAndType = " + n16 + " (在哪里可以找到的名称和类型)");
dataout.writeShort(n16);
break;
case 10: // method reference
System.out.println(" 常量类型 = Methodref //方法参考"); //方法参考
n16 = u2(input);
System.out.println("class index = " + n16 + " (在哪里可以找到类)");
dataout.writeShort(n16);
n16 = u2(input);
System.out.println("nameAndType = " + n16 + " (在哪里可以找到名称和类型)");
dataout.writeShort(n16);
break;
case 11: // interface method reference
System.out.println(" 常量类型 = InterfaceMethodref //接口方法参考值"); //接口方法参考值
n16 = u2(input);
System.out.println("class index = " + n16 + " (在哪里可以找到接口)");
dataout.writeShort(n16);
n16 = u2(input);
System.out.println("nameAndType = " + n16 + " (在哪里可以找到名称和类型)");
dataout.writeShort(n16);
break;
case 12: // name and type reference
System.out.println(" 常量类型 = NameAndType //名称和类型"); //名称和类型
n16 = u2(input);
System.out.println(" name index = " + n16 + " (在哪里可以找到这个名字)");
dataout.writeShort(n16);
n16 = u2(input);
System.out.println(" descripter = " + n16 + " (在哪里可以找到描述符)");
dataout.writeShort(n16);
break;
default:
throw new RuntimeException("Invalid constant pool flag: " + tag);
} //end switch
}
public static void jiexitmp()
{
DataInputStream input = null;
try {
input = new DataInputStream(new BufferedInputStream(new FileInputStream(
"C:\\Documents and Settings\\Administrator\\桌面\\解析class文件\\ReadClass.tmp"
)));
/**********analyzeConstant_tag[]存储常量池表中常量数据类型(共11种)**********/
int[] tagSpecies = new int[11]; //存储常量池表中常量各种数据类型的计数
int const_pool_count = analyzeConstant_tag.length; // 读取常量池表中表项的个数
for(int i=0;i
{
System.out.println(analyzeConstant_tag[i]); //按顺序输出各种数据的类型
switch (analyzeConstant_tag[i])
{
case 1:
++tagSpecies[0];
break;
case 3:
++tagSpecies[1];
break;
case 4:
++tagSpecies[2];
break;
case 5:
++tagSpecies[3];
break;
case 6:
++tagSpecies[4];
break;
case 7:
++tagSpecies[5];
break;
case 8:
++tagSpecies[6];
break;
case 9:
++tagSpecies[7];
break;
case 10:
++tagSpecies[8];
break;
case 11:
++tagSpecies[9];
break;
case 12:
++tagSpecies[10];
break;
}
}
for(int i=0;i
System.out.println("数量"+tagSpecies[i]);/*
analyzeConstant_utf8 = new String[analyzeConstant_utf8_num];
int j = 0;
for(int i=0;i
if(analyzeConstant_tag[i]==1)analyzeConstant_utf8[j++] = "r";
for(int i=0;i
System.out.println("NO."+i+" "+analyzeConstant_utf8[i]);
*/
}
catch (Exception e) {
System.out.println("解析失败!");
} finally {
try { input.close(); } catch (Exception e) {}
}
}
} //End
/*****
byte u1 Short u2 int u4
ClassFile表结构
ClassFile {
u4 magic; //幻数
u2 minor_version; //副版本号
u2 major_version; //主版本号
u2 constant_pool_count; //常量池表中表项的个数
cp_info constant_pool[constant_pool_count-1]; //每个常量的信息
u2 access_flags; //类修饰符掩码
u2 this_Class; //类或者接口的全限定名称
u2 super_Class; //父类全限定名称
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
1//Utf8存储格式
dataout.writeShort(n16); //length
dataout.writeUTF(new String(buffer)); //字符串
3//Integer存储格式
dataout.writeInt(n32);
4//Float存储格式
dataout.writeFloat(f);
5//Long存储格式
dataout.writeLong(n64);
6//Double存储格式
dataout.writeDouble(d);
7//类索引
dataout.writeShort(n16);
8//字符串索引
dataout.writeShort(n16);
9//领域参数
dataout.writeShort(n16); //类名
dataout.writeShort(n16); //名称和类型
10//方法参考
dataout.writeShort(n16); //类名
dataout.writeShort(n16); //名称和类型
11//接口方法参考值
dataout.writeShort(n16); //接口
dataout.writeShort(n16); //名称和类型
12//名称和类型
dataout.writeShort(n16); //名字索引
dataout.writeShort(n16); //描述符索引
*****/
代码还有很多不足,还有很多没有解析,下次继续吧!
作者:qq379264347
转载请保留本段版权信息,谢谢!