一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

用java程序來解析class文件,實現(xiàn)反編譯

 昵稱M7msy 2010-09-13
我們都知道,Java編譯器負(fù)責(zé)將.java文件編譯成.class文件,class文件存儲的是java字節(jié)碼,與.java文件無關(guān)(只要你愿意寫一個編譯器,也可以將別的語言寫的源代碼編譯成.class文件),本文準(zhǔn)備詳細(xì)解剖class文件的內(nèi)部結(jié)構(gòu),并且把class文件結(jié)構(gòu)讀取并顯示出來。
Class文件的格式由JVM規(guī)范規(guī)定,一共有以下部分:
1. magic number,必須是0xCAFEBABE,用于快速識別是否是一個class文件。
2. version,包括major和minor,如果版本號超過了JVM的識別范圍,JVM將拒絕執(zhí)行。
3. constant pool,常量池,存放所有用到的常量。
4. access flag,定義類的訪問權(quán)限。
5. this class和super class,指示如何找到this class和super class。
6. interfaces,存放所有interfaces。
7. fields,存放所有fields。
8. methods,存放所有methods。
9. attributes,存放所有attributes。
 
先寫一個Test.java:

package example.test;

public final class TestClass {
    public int id = 1234567;
    public void test() {}
}

然后編譯,放在C:\Documents and Settings\Administrator\桌面\解析class文件\TestClass.java。
 
我們用Java來讀取和分析class,ClassAnalyzer的功能便是讀取Test.class,分析結(jié)構(gòu),然后顯示出來,DOS下顯示的內(nèi)容比較少,我們通過StringBuffer最后輸出到txt文件,實現(xiàn)由文件到文件的轉(zhuǎn)變:


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"
      ))));
      //解析數(shù)據(jù)
      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; //長度,字節(jié),B
    double kblength = 0.0D; //長度,千字節(jié),KB
    while (input.read() != -1)
      ++length;
    kblength = length / 1024.0D;
    System.out.println("文件大?。ㄗ止?jié)):" + length + "\n文件大小(KB):" + kblength);
    input.close();
  }
  public static void analyze(DataInputStream input) throws IOException
  {
    // 讀取幻數(shù)
    int magic = u4(input);
    if (magic == 0xCAFEBABE) //-889275714
      System.out.println("magic number = 0xCAFEBABE -----標(biāo)準(zhǔn)class文件");
    else {
      throw new RuntimeException("無效的幻數(shù)!");
    }
    // 讀取副、主版本號
    int minor_ver = u2(input);
    int major_ver = u2(input);
    System.out.println("Version = " + major_ver + "." + minor_ver);
    add("    常規(guī)信息    ");
    add("Minor version:    " + minor_ver);
    add("Major version:    " + major_ver);
    // 讀取常量池表中表項的個數(shù)
    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]; //存儲常量數(shù)據(jù)類型
    analyzeConstant_tag[0] = 0; //系統(tǒng)保留,class中不存在
    for (int i = 1; i < const_pool_count; ++i)
      analyzeConstant(input, i); //分析常數(shù)
    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<access.length;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("超接口個數(shù) = " + 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(); //讀取數(shù)據(jù)類型標(biāo)簽
    analyzeConstant_tag[index] = tag; //存儲常量數(shù)據(jù)類型
    System.out.println("\n常量索引 = " + index + ", 數(shù)據(jù)類型標(biāo)簽 = " + (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); //數(shù)組讀滿才返回
            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 //領(lǐng)域參數(shù)"); //領(lǐng)域參數(shù)
            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[]存儲常量池表中常量數(shù)據(jù)類型(共11種)**********/
int[] tagSpecies = new int[11]; //存儲常量池表中常量各種數(shù)據(jù)類型的計數(shù)
int const_pool_count = analyzeConstant_tag.length; // 讀取常量池表中表項的個數(shù)
for(int i=0;i<const_pool_count;i++) //對數(shù)據(jù)類型的計數(shù)數(shù)組進(jìn)行賦值
  {
    System.out.println(analyzeConstant_tag[i]); //按順序輸出各種數(shù)據(jù)的類型
    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<tagSpecies.length;i++)
System.out.println("數(shù)量"+tagSpecies[i]);/*
analyzeConstant_utf8 = new String[analyzeConstant_utf8_num];
int j = 0;
for(int i=0;i<const_pool_count;i++)
  if(analyzeConstant_tag[i]==1)analyzeConstant_utf8[j++] = "r";
for(int i=0;i<analyzeConstant_utf8.length;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表結(jié)構(gòu)
    ClassFile {
        u4 magic; //幻數(shù)
        u2 minor_version; //副版本號
        u2 major_version; //主版本號
        u2 constant_pool_count; //常量池表中表項的個數(shù)
        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//領(lǐng)域參數(shù)
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); //描述符索引

*****/
 
 
代碼還有很多不足,還有很多沒有解析,下次繼續(xù)吧!
作者:qq379264347
論壇:http://zcb.
轉(zhuǎn)載請保留本段版權(quán)信息,謝謝!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    91亚洲人人在字幕国产| 中文字幕人妻日本一区二区| 国产精品午夜小视频观看| 国产免费一区二区三区av大片| 亚洲精品中文字幕无限乱码| 欧美成人精品国产成人综合| 精品欧美日韩一区二区三区| 最近最新中文字幕免费| 不卡中文字幕在线视频| 女同伦理国产精品久久久| 亚洲一二三四区免费视频| 色婷婷视频免费在线观看| 国产极品粉嫩尤物一区二区| 欧美特色特黄一级大黄片| 日本最新不卡免费一区二区| 色无极东京热男人的天堂| 久久精视频免费视频观看| 高清不卡视频在线观看| 日韩成人免费性生活视频| 亚洲少妇人妻一区二区| 区一区二区三中文字幕| 91人妻丝袜一区二区三区| 风间中文字幕亚洲一区| 久久热在线免费视频精品| 高清国产日韩欧美熟女| 亚洲欧美日产综合在线网| 成人国产一区二区三区精品麻豆| 欧美区一区二区在线观看 | 日本人妻的诱惑在线观看| 免费特黄一级一区二区三区| 欧美一二三区高清不卡| 日韩国产中文在线视频| 人妻露脸一区二区三区| 国产欧美日韩精品一区二| 国产男女激情在线视频| 区一区二区三中文字幕| 精品国模一区二区三区欧美| 亚洲国产av在线视频| 91欧美一区二区三区成人| 欧美一区二区日韩一区二区| 青青草草免费在线视频|