下面这个类用来显示一个class文件中的内容,也可以调用相应类的方法修改其内容:
package classdump;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import javassist.bytecode.*;
/**
*
* @author zj
*/
public class ClassDump {
private String fileName;
ClassFile cf;
public ClassDump(String s) {
fileName = s;
}
public void init() throws FileNotFoundException, IOException {
cf = new ClassFile(new DataInputStream(new FileInputStream(fileName)));
}
/**
* @return the fileName
*/
public String getFileName() {
return fileName;
}
public void printAll() {
PrintStream out = System.out;
pkvp(out, "minor_version", cf.getMinorVersion());
pkvp(out, "major_version", cf.getMajorVersion());
printConstPool(out);
printAccessFlags(out);
pkvp(out, "this_class", cf.getName());
pkvp(out, "super_class", "[id:" + cf.getSuperclassId() + ",name:" + cf.getSuperclass() + "]");
pkvp(out, "interfaces_count", cf.getInterfaces().length);
for (int i=0;i<cf.getInterfaces().length;i++) {
pkvp(out, "\tinterface" + i , cf.getInterfaces()[i]);
}
pkvp(out, "fields_count", cf.getFields().size());
for (int i = 0; i < cf.getFields().size(); i++) {
FieldInfo fi = (FieldInfo) cf.getFields().get(i);
pkvp(out, "\tfield" + i, "[name:" + fi.getName() + "]");
}
pkvp(out, "methods_count", cf.getMethods().size());
for(int i=0;i<cf.getMethods().size();i++) {
MethodInfo mi = (MethodInfo)cf.getMethods().get(i);
pkvp(out, "\tmethod" + i, "[name:" + mi.getName() + "]" );
}
pkvp(out, "attributes_count", cf.getAttributes().size());
for(int i=0;i<cf.getAttributes().size();i++) {
AttributeInfo ai = (AttributeInfo)cf.getAttributes().get(i);
pkvp(out, "\tattribute" + i, "[name:" + ai.getName() + "]");
}
}
private void printFields(PrintStream out) {
}
private void printAccessFlags(PrintStream out) {
String s = "";
int flags = cf.getAccessFlags();
if ((flags & 0x0001)!=0) s += "public ";
if ((flags & 0x0010)!=0) s += "final ";
if ((flags & 0x0020)!=0) s += "super ";
if ((flags & 0x0200)!=0) s += "interface ";
if ((flags & 0x0400)!=0) s += "abstract ";
pkvp(out, "access_flags", s);
}
private void printConstPool(PrintStream out) {
pkvp(out, "constant_pool_count", cf.getConstPool().getSize());
for (int i = 1; i < cf.getConstPool().getSize(); i++) {
String tag = null;
String value = null;
switch (cf.getConstPool().getTag(i)) {
case ConstPool.CONST_Class:
tag = "class";
value = cf.getConstPool().getClassInfo(i);
break;
case ConstPool.CONST_Double:
tag = "double";
break;
case ConstPool.CONST_Fieldref:
tag = "field reference";
value = "[name:" + cf.getConstPool().getFieldrefName(i) + ",type:" + cf.getConstPool().getFieldrefType(i) + ",class:" + cf.getConstPool().getFieldrefClassName(i) + "]";
break;
case ConstPool.CONST_Float:
tag = "float";
break;
case ConstPool.CONST_Integer:
tag = "integer";
value = Integer.toString(cf.getConstPool().getIntegerInfo(i));
break;
case ConstPool.CONST_InterfaceMethodref:
tag = "interface method reference";
break;
case ConstPool.CONST_Long:
tag = "long";
break;
case ConstPool.CONST_Methodref:
tag = "method reference";
value = "[name:" + cf.getConstPool().getMethodrefName(i) + ",type:" + cf.getConstPool().getMethodrefType(i) + ",class:" + cf.getConstPool().getMethodrefClassName(i) + "]";
break;
case ConstPool.CONST_NameAndType:
tag = "name and type";
value = cf.getConstPool().getNameAndTypeName(i) + ":" + cf.getConstPool().getNameAndTypeDescriptor(i);
break;
case ConstPool.CONST_String:
tag = "string";
value = cf.getConstPool().getStringInfo(i);
break;
case ConstPool.CONST_Utf8:
tag = "utf8";
value = cf.getConstPool().getUtf8Info(i);
break;
default:
tag = Integer.toString(cf.getConstPool().getTag(i));
}
pkvp(out, "\tconst" + i + "(" + tag + ")", value);
}
}
/**
* Print Key Value Pair
* @param out
* @param key
* @param value
*/
private void pkvp(PrintStream out, String key, Object value) {
out.println(key + "=" + value);
}
/**
* @param fileName the fileName to set
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
使用这个类的例子:
public class Main {
public static void main(String[] args) {
try {
ClassDump cd = new ClassDump("d:\\Battle.class");
cd.init();
cd.printAll();
} catch (FileNotFoundException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}