久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

用java程序來解析class文件,,實現反編譯

 昵稱M7msy 2010-09-13
我們都知道,,Java編譯器負責將.java文件編譯成.class文件,,class文件存儲的是java字節(jié)碼,,與.java文件無關(只要你愿意寫一個編譯器,,也可以將別的語言寫的源代碼編譯成.class文件),本文準備詳細解剖class文件的內部結構,,并且把class文件結構讀取并顯示出來,。
Class文件的格式由JVM規(guī)范規(guī)定,一共有以下部分:
1. magic number,,必須是0xCAFEBABE,,用于快速識別是否是一個class文件。
2. version,,包括major和minor,,如果版本號超過了JVM的識別范圍,JVM將拒絕執(zhí)行,。
3. constant pool,,常量池,存放所有用到的常量,。
4. access flag,,定義類的訪問權限。
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,,分析結構,,然后顯示出來,DOS下顯示的內容比較少,,我們通過StringBuffer最后輸出到txt文件,,實現由文件到文件的轉變:


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; //長度,,字節(jié),B
    double kblength = 0.0D; //長度,,千字節(jié),,KB
    while (input.read() != -1)
      ++length;
    kblength = length / 1024.0D;
    System.out.println("文件大小(字節(jié)):" + length + "\n文件大?。↘B):" + 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("    常規(guī)信息    ");
    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; //系統(tǒng)保留,,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<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("超接口個數 = " + 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<const_pool_count;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<tagSpecies.length;i++)
System.out.println("數量"+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表結構
    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); //描述符索引

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

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多