将java class字节码文件按照不同的区域进行解析处理。
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* Created by dezhonger on 2020/09/26
* <p>
* javaClass文件解析
*/
public class ClazzResolve {
public static void main(String[] args) {
File file = new File("E:/深入剖析class文件结构/第一章/example/Hello.class");
// File file = new File("E:\\Netease\\pri\\target\\classes/Hello.class");
InputStream in = null;
try {
in = new FileInputStream(file);
showAvailableBytes(in);
//读取魔数
readMagicNumber(in);
//读取版本号
showAvailableBytes(in);
readVersion(in);
//读取常量池
showAvailableBytes(in);
readConstantPool(in);
//读取access flag(访问控制符)
showAvailableBytes(in);
readAccessFlag(in);
//this class
readThisClass(in);
//superclass
readSuperClass(in);
//interface
readInterface(in);
//field
readField(in);
//method
readMethod(in);
//attribute
readAttribute(in);
showAvailableBytes(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void readInterface(InputStream in) {
byte[] read = read(in, 2);
int size = (read[0] << 8) + read[1];
System.out.println("接口数量 " +size);
for (int i = 0; i < size; i++) {
read(in, 2);
}
}
private static void readAttribute(InputStream in, int sz) {
//attribute_info[sz]
for (int k = 0; k < sz; k++) {
read(in, 2);
byte[] f = read(in, 4);
int t = (f[0] << 24) + (f[1] << 16) + (f[2] << 8) + f[3];
read(in, t);
}
}
private static void readAttribute(InputStream in) {
byte[] read = read(in, 2);
int size = (read[0] << 8) + read[1];
System.out.println("属性数量 " +size);
readAttribute(in, size);
}
private static void readMethod(InputStream in) {
int len = 2;
byte[] read = read(in, len);
int size = (read[0] << 8) + read[1];
System.out.println("方法数量 " +size);
for (int i = 0; i < size; i++) {
//access_flags
read(in, 2);
//name_index
read(in, 2);
//descriptor_index
read(in, 2);
//attribute_count
byte[] s = read(in, 2);
int sz = (s[0] << 8) + s[1];
//attribute_info[sz]
readAttribute(in, sz);
}
}
private static void readField(InputStream in) {
int len = 2;
byte[] read = read(in, len);
int size = (read[0] << 8) + read[1];
for (int i = 0; i < size; i++) {
//access_flags
read(in, 2);
//name_index
read(in, 2);
//descriptor_index
read(in, 2);
//attribute_count
byte[] s = read(in, 2);
int sz = (s[0] << 8) + s[1];
//attribute_info[sz]
readAttribute(in, sz);
}
}
private static void readSuperClass(InputStream in) {
read(in, 2);
}
private static void readThisClass(InputStream in) {
read(in, 2);
}
private static void readAccessFlag(InputStream in) {
read(in, 2);
}
private static void readConstantPool(InputStream in) {
int len = 2;
byte[] read = read(in, len);
int size = (read[0] << 8) + read[1];
int tagLen = 1;
for (int i = 0; i < size - 1; i++) {
byte[] readTag = read(in, tagLen);
switch (readTag[0]) {
case 1://字符串
byte[] utf8Length = read(in, 2);
read(in, (utf8Length[0] << 8) + utf8Length[1]);
break;
case 3: case 4://int float
read(in, 4);
break;
case 5: case 6://long double
read(in, 8);
break;
case 7://Class
read(in, 2);
break;
case 8://String
read(in, 2);
break;
case 9: case 10: case 11://fieldref methodref interfaceref
read(in, 2);
read(in, 2);
break;
case 12://NameAndType
read(in, 2);
read(in, 2);
break;
case 15: case 16: case 18:
read(in, 2);
read(in, 2);
break;
default:
System.err.println("出错了" + readTag[0]);
break;
}
}
}
private static void readVersion(InputStream in) {
int len = 4;
read(in, len);
}
private static void readMagicNumber(InputStream in) {
int len = 4;
read(in, len);
}
private static byte[] read(InputStream in,int len) {
byte[] bytes = new byte[len];
try {
in.read(bytes);
String[] res = new String[len];
for (int i = 0; i < len; i++){
res[i] = Integer.toHexString(Byte.toUnsignedInt(bytes[i]));
if (res[i].length() == 1) res[i] = "0" + res[i];
// System.out.println(Integer.toHexString(Byte.toUnsignedInt(b)));
}
System.out.println(Arrays.toString(res));
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
/**
* 显示输入流中还剩的字节数
*/
private static void showAvailableBytes(InputStream in) {
try {
System.out.println("当前字节输入流中的字节数为:" + in.available());
} catch (IOException e) {
e.printStackTrace();
}
}
}