| ǰÑÔ
ÉíΪһ¸öjava³ÌÐòÔ±£¬ÔõôÄܲ»Á˽âJVMÄØ£¬ÌÈÈôÏëѧϰJVM£¬ÄǾÍÓÖ±ØÐëÒªÁ˽âClassÎļþ£¬ClassÖ®ÓÚÐéÄâ»ú£¬¾ÍÈçÓãÖ®ÓÚË®£¬ÐéÄâ»úÒòΪClass¶øÓÐÁËÉúÃü¡£¡¶ÉîÈëÀí½âjavaÐéÄâ»ú¡·Öл¨ÁËÒ»Õû¸öÕ½ÚÀ´½²½âClassÎļþ£¬¿ÉÊÇ¿´Íêºó£¬Ò»Ö±¶¼»¹ÊÇÃÔÃÔºýºý£¬Ëƶ®·Ç¶®¡£ÕýºÃǰ¶Îʱ¼ä¿´¼ûÒ»±¾ÊéºÜ²»´í£º¡¶×Ô¼º¶¯ÊÖдJavaÐéÄâ»ú¡·£¬×÷ÕßÀûÓÃgoÓïÑÔʵÏÖÁËÒ»¸ö¼òµ¥µÄJVM£¬ËäȻûÓÐÍêÕûʵÏÖJVMµÄËùÓй¦ÄÜ£¬µ«ÊǶÔÓÚһЩ¶ÔJVMÉÔ¸ÐÐËȤµÄÈËÀ´Ëµ£¬¿É¶ÁÐÔ»¹ÊǺܸߵġ£×÷Õß½²½âµÄºÜÏêϸ£¬Ã¿¸ö¹ý³Ì¶¼·ÖΪÁËÒ»Õ£¬ÆäÖÐÒ»²¿·Ö¾ÍÊǽ²½âÈçºÎ½âÎöClassÎļþ¡£
Õâ±¾Ê鲻̫ºñ£¬ºÜ¿ì¾Í¶ÁÍêÁË£¬¶ÁÍêºó£¬ÊÕ»ñÆÄ·á¡£µ«ÊÇÖ½ÉϵÃÀ´ÖÕ¾õdz£¬¾øÖª´ËÊÂÒª¹ªÐУ¬Îұ㳢ÊÔ×Å×Ô¼º½âÎöClassÎļþ¡£goÓïÑÔËäÈ»ºÜÓÅÐ㣬µ«ÊÇÖÕ¾¿²»ÊìÁ·£¬ÓÈÆäÊDz»Ì«Ï°¹ßÆä°ÑÀàÐÍ·ÅÔÚ±äÁ¿Ö®ºóµÄÓï·¨£¬»¹ÊÇÀÏÀÏʵʵÓÃjava°É¡£
»°²»¶à˵£¬ÏÈÌù³öÏîÄ¿µØÖ·:https://github.com/HalfStackDeveloper/ClassReader
ClassÎļþ
ʲôÊÇClassÎļþ£¿
javaÖ®ËùÒÔÄܹ»ÊµÏÖ¿çÆ½Ì¨£¬±ãÔÚÓÚÆä±àÒë½×¶Î²»Êǽ«´úÂëÖ±½Ó±àÒëΪƽ̨Ïà¹ØµÄ»úÆ÷ÓïÑÔ£¬¶øÊÇÏȱàÒë³É¶þ½øÖÆÐÎʽµÄjava×Ö½ÚÂ룬·ÅÔÚClassÎļþÖ®ÖУ¬ÐéÄâ»úÔÙ¼ÓÔØClassÎļþ£¬½âÎö³ö³ÌÐòÔËÐÐËùÐèµÄÄÚÈÝ¡£Ã¿¸öÀà¶¼»á±»±àÒë³ÉÒ»¸öµ¥¶ÀµÄclassÎļþ£¬ÄÚ²¿ÀàÒ²»á×÷Ϊһ¸ö¶ÀÁ¢µÄÀ࣬Éú³É×Ô¼ºµÄclass¡£
»ù±¾½á¹¹
Ëæ±ãÕÒµ½Ò»¸öclassÎļþ£¬ÓÃSublime Text´ò¿ªÊÇÕâÑùµÄ£º
ÊDz»ÊÇÒ»Á³ã±ƣ¬²»¹ýjavaÐéÄâ»ú¹æ·¶Öиø³öÁËclassÎļþµÄ»ù±¾¸ñʽ£¬Ö»Òª°´ÕÕÕâ¸ö¸ñʽȥ½âÎö¾Í¿ÉÒÔÁË£º
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]; } |
ClassFileÖеÄ×Ö¶ÎÀàÐÍÓÐu1¡¢u2¡¢u4,ÕâÊÇʲôÀàÐÍÄØ£¿ÆäʵºÜ¼òµ¥£¬¾ÍÊÇ·Ö±ð±íʾ1¸ö×Ö½Ú£¬2¸ö×Ö½ÚºÍ4¸ö×Ö½Ú¡£
¿ªÍ·Ëĸö×Ö½ÚΪ£ºMagic£¬ÊÇÓÃÀ´Î¨Ò»±êʶÎļþ¸ñʽµÄ£¬Ò»°ã±»³Æ×÷magic
number£¨Ä§Êý£©£¬ÕâÑùÐéÄâ»ú²ÅÄÜʶ±ð³öËù¼ÓÔØµÄÎļþÊÇ·ñÊÇclass¸ñʽ£¬classÎļþµÄħÊýΪcafebabe¡£²»Ö»ÊÇclassÎļþ£¬»ù±¾Éϴ󲿷ÖÎļþ¶¼ÓÐħÊý£¬ÓÃÀ´±êʶ×Ô¼ºµÄ¸ñʽ¡£
½ÓÏÂÀ´µÄ²¿·ÖÖ÷ÒªÊÇclassÎļþµÄһЩÐÅÏ¢£¬Èç³£Á¿³Ø¡¢Àà·ÃÎʱêÖ¾¡¢¸¸Àà¡¢½Ó¿ÚÐÅÏ¢¡¢×ֶΡ¢·½·¨µÈ£¬¾ßÌåµÄÐÅÏ¢¿É²Î¿¼¡¶JavaÐéÄâ»ú¹æ·¶¡·¡£
½âÎö
×Ö¶ÎÀàÐÍ
ÉÏÃæËµµ½ClassFileÖеÄ×Ö¶ÎÀàÐÍÓÐu1¡¢u2¡¢u4£¬·Ö±ð±íʾ1¸ö×Ö½Ú£¬2¸ö×Ö½ÚºÍ4¸ö×Ö½ÚµÄÎÞ·ûºÅÕûÊý¡£javaÖÐshort¡¢int¡¢long·Ö±ðΪ2¡¢4¡¢8¸ö×Ö½ÚµÄÓзûºÅÕûÊý£¬È¥µô·ûºÅ룬¸ÕºÃ¿ÉÒÔÓÃÀ´±íʾu1¡¢u2¡¢u4¡£
public class U1 { public static short read(InputStream inputStream) { byte[] bytes = new byte[1]; try { inputStream.read(bytes); } catch (IOException e) { e.printStackTrace(); } short value = (short) (bytes[0] & 0xFF); return value; } }
public class U2 {
public static int read(InputStream inputStream)
{
byte[] bytes = new byte[2];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
int num = 0;
for (int i= 0; i < bytes.length; i++) {
num <<= 8;
num |= (bytes[i] & 0xff);
}
return num;
}
}
public class U4 {
public static long read(InputStream inputStream)
{
byte[] bytes = new byte[4];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
long num = 0;
for (int i= 0; i < bytes.length; i++) {
num <<= 8;
num |= (bytes[i] & 0xff);
}
return num;
}
} |
³£Á¿³Ø
¶¨ÒåºÃ×Ö¶ÎÀàÐͺó£¬ÎÒÃǾͿÉÒÔ¶ÁÈ¡classÎļþÁË£¬Ê×ÏÈÊǶÁȡħÊýÖ®ÀàµÄ»ù±¾ÐÅÏ¢£¬Õⲿ·ÖºÜ¼òµ¥£º
FileInputStream inputStream = new FileInputStream(file); ClassFile classFile = new ClassFile(); classFile.magic = U4.read(inputStream); classFile.minorVersion = U2.read(inputStream); classFile.majorVersion = U2.read(inputStream); |
Õⲿ·ÖÖ»ÊÇÈÈÈÈÉí£¬½ÓÏÂÀ´µÄ´óÍ·ÔÚÓÚ³£Á¿³Ø¡£½âÎö³£Á¿³ØÖ®Ç°£¬ÎÒÃÇÏÈÀ´½âÊÍһϳ£Á¿³ØÊÇʲô¡£
³£Á¿³Ø£¬¹ËÃû˼Ò壬´æ·Å³£Á¿µÄ×ÊÔ´³Ø£¬ÕâÀïµÄ³£Á¿Ö¸µÄÊÇ×ÖÃæÁ¿ºÍ·ûºÅÒýÓá£×ÖÃæÁ¿Ö¸µÄÊÇһЩ×Ö·û´®×ÊÔ´£¬¶ø·ûºÅÒýÓ÷ÖΪÈýÀࣺÀà·ûºÅÒýÓᢷ½·¨·ûºÅÒýÓúÍ×ֶηûºÅÒýÓá£Í¨¹ý½«×ÊÔ´·ÅÔÚ³£Á¿³ØÖУ¬ÆäËûÏî¾Í¿ÉÒÔÖ±½Ó¶¨Òå³É³£Á¿³ØÖеÄË÷ÒýÁË£¬±ÜÃâÁ˿ռäµÄÀË·Ñ£¬²»Ö»ÊÇclassÎļþ£¬Android¿ÉÖ´ÐÐÎļþdexÒ²ÊÇͬÑùÈç´Ë£¬½«×Ö·û´®×ÊÔ´µÈ·ÅÔÚDexDataÖУ¬ÆäËûÏîͨ¹ýË÷Òý¶¨Î»×ÊÔ´¡£javaÐéÄâ»ú¹æ·¶¸ø³öÁ˳£Á¿³ØÖÐÿһÏîµÄ¸ñʽ£º
cp_info { u1 tag; u1 info[]; } |
ÉÏÃæµÄÕâ¸ö¸ñʽֻÊÇÒ»¸öͨÓøñʽ£¬³£Á¿³ØÖÐÕæÕý°üº¬µÄÊý¾ÝÓÐ14ÖÖ¸ñʽ£¬Ã¿ÖÖ¸ñʽµÄtagÖµ²»Í¬
ÓÉÓÚ¸ñʽ̫¶à£¬ÎÄÕÂÖÐÖ»Ìôѡһ²¿·Ö½²½â£º
ÕâÀïÊ×ÏȶÁÈ¡³£Á¿³ØµÄ´óС£¬³õʼ»¯³£Á¿³Ø£º
//½âÎö³£Á¿³Ø int constant_pool_count = U2.read(inputStream); ConstantPool constantPool = new ConstantPool(constant_pool_count); constantPool.read(inputStream); |
½ÓÏÂÀ´ÔÙÖð¸ö¶ÁȡÿÏîÄÚÈÝ£¬²¢´æ´¢µ½Êý×écpInfoÖУ¬ÕâÀïÐèҪעÒâµÄÊÇ£¬cpInfo[]ϱê´Ó1¿ªÊ¼£¬0ÎÞЧ£¬ÇÒÕæÕýµÄ³£Á¿³Ø´óСΪconstant_pool_count-1¡£
public class ConstantPool { public int constant_pool_count; public ConstantInfo[] cpInfo;
public ConstantPool(int count) {
constant_pool_count = count;
cpInfo = new ConstantInfo[constant_pool_count];
}
public void read(InputStream inputStream) {
for (int i = 1; i < constant_pool_count; i++)
{
short tag = U1.read(inputStream);
ConstantInfo constantInfo = ConstantInfo.getConstantInfo(tag);
constantInfo.read(inputStream);
cpInfo[i] = constantInfo;
if (tag == ConstantInfo.CONSTANT_Double || tag
== ConstantInfo.CONSTANT_Long) {
i++;
}
}
}
} |
ÎÒÃÇÏÈÀ´¿´¿´CONSTANT_Utf8¸ñʽ£¬ÕâÒ»ÏîÀïÃæ´æ·ÅµÄÊÇMUTF-8±àÂëµÄ×Ö·û´®£º
CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } |
ÄÇôÈçºÎ¶ÁÈ¡ÕâÒ»ÏîÄØ£¿
public class ConstantUtf8 extends ConstantInfo { public String value;
@Override
public void read(InputStream inputStream) {
int length = U2.read(inputStream);
byte[] bytes = new byte[length];
try {
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
try {
value = readUtf8(bytes);
} catch (UTFDataFormatException e) {
e.printStackTrace();
}
}
private String readUtf8(byte[] bytearr) throws
UTFDataFormatException {
//copy from java.io.DataInputStream.readUTF()
}
} |
ºÜ¼òµ¥£¬Ê×ÏȶÁÈ¡ÕâÒ»ÏîµÄ×Ö½ÚÊý×鳤¶È£¬½Ó×ŵ÷ÓÃreadUtf8(),½«×Ö½ÚÊý×éת»¯ÎªString×Ö·û´®¡£
ÔÙÀ´¿´¿´CONSTANT_ClassÕâÒ»ÏÕâÒ»Ïî´æ´¢µÄÊÇÀà»òÕ߽ӿڵķûºÅÒýÓãº
CONSTANT_Class_info { u1 tag; u2 name_index; }
|
×¢ÒâÕâÀïµÄname_index²¢²»ÊÇÖ±½ÓµÄ×Ö·û´®£¬¶øÊÇÖ¸Ïò³£Á¿³ØÖÐcpInfoÊý×éµÄname_indexÏÇÒcpInfo[name_index]Ò»¶¨ÊÇCONSTANT_Utf8¸ñʽ¡£
public class ConstantClass extends ConstantInfo { public int nameIndex;
@Override
public void read(InputStream inputStream) {
nameIndex = U2.read(inputStream);
}
} |
³£Á¿³Ø½âÎöÍê±Ïºó£¬¾Í¿ÉÒÔ¹©ºóÃæµÄÊý¾ÝʹÓÃÁË£¬±È·½ËµClassFileÖеÄthis_classÖ¸ÏòµÄ¾ÍÊdz£Á¿³ØÖиñʽΪCONSTANT_ClassµÄijһÏî,ÄÇôÎÒÃǾͿÉÒÔ¶ÁÈ¡³öÀàÃû£º
int classIndex = U2.read(inputStream); ConstantClass clazz = (ConstantClass) constantPool.cpInfo[classIndex]; ConstantUtf8 className = (ConstantUtf8) constantPool.cpInfo[clazz.nameIndex]; classFile.className = className.value; System.out.print("classname:" + classFile.className + "\n"); |
×Ö½ÚÂëÖ¸Áî
½âÎö³£Á¿³ØÖ®ºó»¹ÐèÒª½Ó׎âÎöһЩÀàÐÅÏ¢£¬È縸Àà¡¢½Ó¿ÚÀà¡¢×ֶεȣ¬µ«ÊÇÏàÐÅ´ó¼Ò×îºÃÆæµÄ»¹ÊÇjavaÖ¸ÁîµÄ´æ´¢£¬´ó¼Ò¶¼ÖªµÀ£¬ÎÒÃÇÆ½Ê±Ð´µÄjava´úÂë»á±»±àÒë³Éjava×Ö½ÚÂ룬ÄÇôÕâЩ×Ö½ÚÂëµ½µ×´æ´¢ÔÚÄÄÄØ£¿±ð¼±£¬½²½âÖ¸Áî֮ǰ£¬ÎÒÃÇÏÈÀ´Á˽âÏÂClassFileÖеÄmethod_info£¬Æä¸ñʽÈçÏ£º
method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }
|
method_infoÀïÖ÷ÒªÊÇһЩ·½·¨ÐÅÏ¢£ºÈç·ÃÎʱêÖ¾¡¢·½·¨ÃûË÷Òý¡¢·½·¨ÃèÊö·ûË÷Òý¼°ÊôÐÔÊý×é¡£ÕâÀïҪǿµ÷µÄÊÇÊôÐÔÊý×飬ÒòΪ×Ö½ÚÂëÖ¸Áî¾Í´æ´¢ÔÚÕâ¸öÊôÐÔÊý×éÀï¡£ÊôÐÔÓкܶàÖÖ£¬±ÈÈç˵Òì³£±í¾ÍÊÇÒ»¸öÊôÐÔ£¬¶ø´æ´¢×Ö½ÚÂëÖ¸ÁîµÄÊôÐÔΪCODEÊôÐÔ£¬¿´ÕâÃû×ÖÒ²ÖªµÀÊÇÓÃÀ´´æ´¢´úÂëµÄÁË¡£ÊôÐÔµÄͨÓøñʽΪ£º
attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; } |
¸ù¾Ýattribute_name_index¿ÉÒÔ´Ó³£Á¿³ØÖÐÄõ½ÊôÐÔÃû£¬ÔÙ¸ù¾ÝÊôÐÔÃû¾Í¿ÉÒÔÅжÏÊôÐÔÖÖÀàÁË¡£
CodeÊôÐԵľßÌå¸ñʽΪ£º
Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } |
ÆäÖÐcodeÊý×éÀï´æ´¢¾ÍÊÇ×Ö½ÚÂëÖ¸ÁÄÇôÈçºÎ½âÎöÄØ£¿Ã¿ÌõÖ¸ÁîÔÚcode[]Öж¼ÊÇÒ»¸ö×Ö½Ú£¬ÎÒÃÇÆ½Ê±javapÃüÁî·´±àÒë¿´µ½µÄÖ¸ÁîÆäʵÊÇÖú¼Ç·û£¬Ö»ÊÇ·½±ãÔĶÁ×Ö½ÚÂëʹÓõģ¬jvmÓÐÒ»ÕÅ×Ö½ÚÂëÓëÖú¼Ç·ûµÄ¶ÔÕÕ±í£¬¸ù¾Ý¶ÔÕÕ±í£¬¾Í¿ÉÒÔ½«Ö¸Áî·ÒëΪ¿É¶ÁµÄÖú¼Ç·ûÁË¡£ÕâÀïÎÒÒ²ÊÇÔÚÍøÉÏËæ±ãÕÒÁËÒ»¸ö¶ÔÕÕ±í£¬±£´æµ½±¾µØtxtÎļþÖУ¬²¢ÔÚʹÓÃʱ½âÎö³ÉHashMap¡£´úÂëºÜ¼òµ¥£¬¾Í²»ÌùÁË£¬¿ÉÒԲο¼ÎÒ´úÂëÖÐInstructionTable.java¡£
½ÓÏÂÀ´ÎÒÃǾͿÉÒÔ½âÎö×Ö½ÚÂëÁË£º
for (int j = 0; j < methodInfo.attributesCount; j++) { if (methodInfo.attributes[j] instanceof CodeAttribute) { CodeAttribute codeAttribute = (CodeAttribute) methodInfo.attributes[j]; for (int m = 0; m < codeAttribute.codeLength; m++) { short code = codeAttribute.code[m]; System.out.print(InstructionTable.getInstruction(code) + "\n"); } } } |
ÔËÐÐ
Õû¸öÏîÄ¿ÖÕÓÚдÍêÁË£¬½ÓÏÂÀ´¾ÍÀ´¿´¿´Ð§¹ûÈçºÎ£¬Ëæ±ãÕÒÒ»¸öclassÎļþ½âÎöÔËÐУº

¹þ¹þ£¬ÊDz»ÊǺÜÔÞ£¡
|