解析java的*.class文件

来源:互联网 发布:mac 还原出厂设置 编辑:程序博客网 时间:2024/05/16 15:15

这几天在写解析*.class文件的程序,实现class的反编译功能:目前所能实现的反编译是只含有方法的interface(不能反编译带有属性的interface)。不知道如何将源码打包上传,这里只帖出解析*.class文件的部分代码:

package com.hexin.study.interpreter;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Administrator
 *
 * 更改所生成类型注释的模板为
 * 窗口 > 首选项 > Java > 代码生成 > 代码和注释
 */
public class ClassParseFactory extends AbstractParseFactory {
 
 private int CLASS_ATTRIBUTES = 16;
 
 private short CONSTANT_POOL_COUNT = 0;
 
 private short INTERFACES_COUNT = 0;
 
 private short FIELDS_COUNT = 0;
 
 private short METHODS_COUNT = 0;
 
 private short ATTRIBUTES_COUNT = 0;

 /* (非 Javadoc)
  * @see com.hexin.study.interpreter.AbstractParseFactory#parse()
  */
 public Context parse(File f) {
  ClassContext cc = new ClassContext();
  try {
   DataInputStream dis = new DataInputStream(new FileInputStream(f));
   int i = 0;
   for(int m=0;m<CLASS_ATTRIBUTES;m++){
    parseClass(dis,cc,i);
    i++;
   }
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return cc;
 }
 
 private void parseClass(DataInputStream dis,ClassContext cc,int i) throws IOException{
  byte[] b = null;
  switch(i){
   case Constant.MAGIC:
    b = new byte[4];
    dis.read(b);
    cc.setMAGIC(getHex(b));
    break;
   case Constant.MINOR_VERSION:
    cc.setMINOR_VERSION(dis.readShort());
    break;
   case Constant.MAJOR_VERSION:
    cc.setMAJOR_VERSION(dis.readShort());
    break;
   case Constant.CONSTANT_POOL_COUNT:
    CONSTANT_POOL_COUNT = dis.readShort();
    cc.setCONSTANT_POOL_COUNT(CONSTANT_POOL_COUNT);
    break;
   case Constant.CONSTANT_POOL:
    List list = new ArrayList();
    for(int l=1;l<CONSTANT_POOL_COUNT;l++)
     parseCP(dis,list);
    cc.setCONSTANT_POOL(list);
    break;
   case Constant.ACCESS_FLAGS:
    cc.setACCESS_FLAGS(dis.readShort());
    break;
   case Constant.THIS_CLASS:
    cc.setTHIS_CLASS(dis.readShort());
    break;
   case Constant.SUPER_CLASS:
    cc.setSUPER_CLASS(dis.readShort());
    break;
   case Constant.INTERFACES_COUNT:
    INTERFACES_COUNT = dis.readShort();
    cc.setINTERFACES_COUNT(INTERFACES_COUNT);
    break;
   case Constant.INTERFACES:
    List l = new ArrayList();
    parseInfo(dis,l,INTERFACES_COUNT);
    cc.setINTERFACES(l);
    break;
   case Constant.FIELDS_COUNT:
    FIELDS_COUNT = dis.readShort();
    cc.setFIELDS_COUNT(FIELDS_COUNT);
    break;
   case Constant.FIELDS:
    List l_f = new ArrayList();
    parseFieldInfo(dis,l_f,FIELDS_COUNT);
    cc.setFIELDS(l_f);
    break;
   case Constant.METHODS_COUNT:
    METHODS_COUNT = dis.readShort();
    cc.setMETHODS_COUNT(METHODS_COUNT);
    break;
   case Constant.METHODS:
    List l_m = new ArrayList();
    parseMethodInfo(dis,l_m,METHODS_COUNT);
    cc.setMETHODS(l_m);
    break;
   case Constant.ATTRIBUTES_COUNT:
    ATTRIBUTES_COUNT = dis.readShort();
    cc.setATTRIBUTES_COUNT(ATTRIBUTES_COUNT);
    break;
   case Constant.ATTRIBUTES:
    Map m = new HashMap();
    parseAttributeInfo(dis,m,ATTRIBUTES_COUNT);
    cc.setATTRIBUTES(m);
   break;
  }
 } 
 
 private void parseFieldInfo(DataInputStream dis,List l,int length) throws IOException{
  for(int i=0;i<length;i++){
   FieldNode fn = new FieldNode();
   fn.setAccessFlags(dis.readShort());
   fn.setNameIndex(dis.readShort());
   fn.setDescriptorIndex(dis.readShort());
   short count = dis.readShort();
   fn.setAttributesCount(count);
   parseAttributeInfo(dis,fn.getM(),count);
  }
 }
 
 private void parseMethodInfo(DataInputStream dis,List l,int length) throws IOException{
  for(int i=0;i<length;i++){
   MethodNode mn = new MethodNode();
   mn.setAccessFlags(dis.readShort());
   mn.setNameIndex(dis.readShort());
   mn.setDescriptorIndex(dis.readShort());
   short count = dis.readShort();
   mn.setAttributesCount(count);
   parseAttributeInfo(dis,mn.getM(),count);
   l.add(mn);
  }
 }
 
 private void parseAttributeInfo(DataInputStream dis,Map m,int length) throws IOException{
  for(int i=0;i<length;i++){
   m.put(i+"_attibute_name_index",String.valueOf(dis.readShort()));
   int count = dis.readInt();
   m.put(i+"_attibute_length",String.valueOf(count));
   List l = new ArrayList();
   for(int n=0;n<count;n++){
    l.add(String.valueOf(dis.readByte()));
   }
   m.put(i+"_attibute_info",l);
  }
 }
 
 private void parseInfo(DataInputStream dis,List list,int length) throws IOException{
  for(int i=0;i<length;i++){
   list.add(String.valueOf(dis.readShort()));
  }
 }
 
 private void parseCP(DataInputStream dis,List list) throws IOException{
  byte f = dis.readByte();//判断是什么类别(utf-8,float。。。)
  switch(f){
   case 1://utf-8 string
    short i = dis.readShort();//得到utf-8得长度
    byte[] b = new byte[i];
    dis.readFully(b);
    list.add(new String(b));
    break;
   case 3://integer
    list.add(String.valueOf(dis.readInt()));
    break;
   case 4://float
    list.add(String.valueOf(dis.readFloat()));
    break;
   case 5://long
    list.add(String.valueOf(dis.readLong()));
    break;
   case 6://double
    list.add(String.valueOf(dis.readDouble()));
    break;
   case 7://class or interface reference
    list.add(String.valueOf(dis.readShort()));
    break;
   case 8://string  name_index
    list.add(String.valueOf(dis.readShort()));
    break;
   case 9://field reference
    list.add(String.valueOf(dis.readShort()));
    list.add(String.valueOf(dis.readShort()));
    break;
   case 10://method reference
    list.add(String.valueOf(dis.readShort()));
    list.add(String.valueOf(dis.readShort()));
    break;
   case 11://interface method reference
    list.add(String.valueOf(dis.readShort()));
    list.add(String.valueOf(dis.readShort()));
    break;
   case 12://name and type reference
    list.add(String.valueOf(dis.readShort()));
    list.add(String.valueOf(dis.readShort()));
    break;
   default:
  }
 }
 
 private String getHex(byte[] b){
  StringBuffer sb = new StringBuffer();
  for(int i=0;i<b.length;i++){
   for(int m=0;m<2;m++){
    int tmp = 0;
    if(m==0) tmp = (b[i] & 240)>>4;
    else tmp = b[i] &15;
    if(tmp == 10) sb.append("A");
    if(tmp == 11) sb.append("B");
    if(tmp == 12) sb.append("C");
    if(tmp == 13) sb.append("D");
    if(tmp == 14) sb.append("E");
    if(tmp == 15) sb.append("F");
    if(tmp < 10) sb.append(tmp);
   }   
  }
  return sb.toString();
 }
 
}

class的解析功能在这个类里面,存放结果的是下面的类:

package com.hexin.study.interpreter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Administrator
 *
 * 更改所生成类型注释的模板为
 * 窗口 > 首选项 > Java > 代码生成 > 代码和注释
 */
public class ClassContext implements Context {
 
 private String MAGIC = null;
 
 private short MINOR_VERSION = -1;
 
 private short MAJOR_VERSION = -1;
 
 private short CONSTANT_POOL_COUNT = -1;
 
 private List CONSTANT_POOL = new ArrayList();
 
 private short ACCESS_FLAGS = -1;
 
 private short THIS_CLASS = -1;
 
 private short SUPER_CLASS = -1;
 
 private short INTERFACES_COUNT = -1;
 
 private List INTERFACES = new ArrayList();
 
 private short FIELDS_COUNT = -1;
 
 private List FIELDS = new ArrayList();//存储FieldNode对象
 
 private short METHODS_COUNT = -1;
 
 private List METHODS = new ArrayList();//存储MethodNode对象
 
 private short ATTRIBUTES_COUNT = -1;
 
 private Map ATTRIBUTES = new HashMap();

 /**
  * @return
  */
 public short getACCESS_FLAGS() {
  return ACCESS_FLAGS;
 }

 /**
  * @return
  */
 public short getATTRIBUTES_COUNT() {
  return ATTRIBUTES_COUNT;
 }

 /**
  * @return
  */
 public short getCONSTANT_POOL_COUNT() {
  return CONSTANT_POOL_COUNT;
 }

 /**
  * @return
  */
 public short getFIELDS_COUNT() {
  return FIELDS_COUNT;
 }

 /**
  * @return
  */
 public List getINTERFACES() {
  return INTERFACES;
 }

 /**
  * @return
  */
 public short getINTERFACES_COUNT() {
  return INTERFACES_COUNT;
 }

 /**
  * @return
  */
 public String getMAGIC() {
  return MAGIC;
 }

 /**
  * @return
  */
 public short getMAJOR_VERSION() {
  return MAJOR_VERSION;
 }

 /**
  * @return
  */
 public short getMETHODS_COUNT() {
  return METHODS_COUNT;
 }

 /**
  * @return
  */
 public short getMINOR_VERSION() {
  return MINOR_VERSION;
 }

 /**
  * @return
  */
 public short getSUPER_CLASS() {
  return SUPER_CLASS;
 }

 /**
  * @return
  */
 public short getTHIS_CLASS() {
  return THIS_CLASS;
 }

 /**
  * @param s
  */
 public void setACCESS_FLAGS(short s) {
  ACCESS_FLAGS = s;
 }

 /**
  * @param s
  */
 public void setATTRIBUTES_COUNT(short s) {
  ATTRIBUTES_COUNT = s;
 }


 /**
  * @param s
  */
 public void setCONSTANT_POOL_COUNT(short s) {
  CONSTANT_POOL_COUNT = s;
 }

 /**
  * @param s
  */
 public void setFIELDS_COUNT(short s) {
  FIELDS_COUNT = s;
 }

 /**
  * @param list
  */
 public void setINTERFACES(List list) {
  INTERFACES = list;
 }

 /**
  * @param s
  */
 public void setINTERFACES_COUNT(short s) {
  INTERFACES_COUNT = s;
 }

 /**
  * @param string
  */
 public void setMAGIC(String string) {
  MAGIC = string;
 }

 /**
  * @param s
  */
 public void setMAJOR_VERSION(short s) {
  MAJOR_VERSION = s;
 }

 /**
  * @param s
  */
 public void setMETHODS_COUNT(short s) {
  METHODS_COUNT = s;
 }

 /**
  * @param s
  */
 public void setMINOR_VERSION(short s) {
  MINOR_VERSION = s;
 }

 /**
  * @param s
  */
 public void setSUPER_CLASS(short s) {
  SUPER_CLASS = s;
 }

 /**
  * @param s
  */
 public void setTHIS_CLASS(short s) {
  THIS_CLASS = s;
 }

 /**
  * @return
  */
 public List getCONSTANT_POOL() {
  return CONSTANT_POOL;
 }

 /**
  * @param list
  */
 public void setCONSTANT_POOL(List list) {
  CONSTANT_POOL = list;
 }

 /**
  * @return
  */
 public Map getATTRIBUTES() {
  return ATTRIBUTES;
 }

 /**
  * @param map
  */
 public void setATTRIBUTES(Map map) {
  ATTRIBUTES = map;
 }

 /**
  * @return
  */
 public List getFIELDS() {
  return FIELDS;
 }

 /**
  * @return
  */
 public List getMETHODS() {
  return METHODS;
 }

 /**
  * @param list
  */
 public void setFIELDS(List list) {
  FIELDS = list;
 }

 /**
  * @param list
  */
 public void setMETHODS(List list) {
  METHODS = list;
 }

 /* (非 Javadoc)
  * @see com.hexin.study.interpreter.Context#getContent()
  */
 public String getContent() {
  StringBuffer sb = new StringBuffer();
  sb.append("MAGIC: "+MAGIC);
  sb.append("/nVERSION: "+MAJOR_VERSION+"."+MINOR_VERSION);
  sb.append("/nCONSTANT_POOL_COUNT: "+CONSTANT_POOL_COUNT);
  sb.append("/nCONSTANT_POOL: ");
  int tmp = CONSTANT_POOL.size();
  for(int i=0;i<tmp;i++)
   sb.append("/n "+CONSTANT_POOL.get(i));
  sb.append("/nACCESS_FLAGS: "+ACCESS_FLAGS);
  sb.append("/nTHIS_CLASS: "+THIS_CLASS);
  sb.append("/nSUPER_CLASS: "+SUPER_CLASS);
  sb.append("/nINTERFACES_COUNT: "+INTERFACES_COUNT);
  sb.append("/nINTERFACES: ");
  sb.append("/nFIELDS_COUNT: "+FIELDS_COUNT);
  sb.append("/nFIELDS: ");
  sb.append("/nMETHODS_COUNT: "+METHODS_COUNT);
  sb.append("/nMETHODS: ");
  for(int i=0;i<METHODS.size();i++){
   MethodNode mn = (MethodNode)METHODS.get(i);
   sb.append(mn.toString());
  }
  sb.append("/n/nATTRIBUTES_COUNT: "+ATTRIBUTES_COUNT);
  sb.append("/nATTRIBUTES: ");
  return sb.toString();
 }

}

整个编写过程不甚理想,咳,设计模式没掌握,写的时候心态比较急,只考虑功能的实现。对class中的attribute没有理解清楚,不过目前的功能实现上已经能反编译一些非常简单的咚咚,也算是一个进步吧。故此,把部分主要的源码帖出来,欢迎大家批评指正。

参考文献:《深入java虚拟机》中文版第二版

原创粉丝点击