我正在尝试使用简单类MyData
使用javassist分析字节码:
class MyData {
private Collection<String> strings = new ArrayList<String>();
// .....................
public void add(String str) {
strings.add(str); // line number 35
}
// .....................
}
这是我针对此类运行的代码:
ClassFile cf = new ClassFile(new DataInputStream(TryJavassist.class.getResourceAsStream("MyData.class")));
MethodInfo minfo = cf.getMethod("add");
CodeAttribute ca = minfo.getCodeAttribute();
for (CodeIterator ci = ca.iterator(); ci.hasNext();) {
int index = ci.next();
int op = ci.byteAt(index);
System.out.println(op + "=" + Mnemonic.OPCODE[op] + ": " + minfo.getLineNumber(index));
}
它可以工作并打印:
42=aload_0: 35
180=getfield: 35
43=aload_1: 35
185=invokeinterface: 35
87=pop: 35
177=return: 36
第35行调用名为
add()
的集合的方法strings
。我发布的代码片段仅检索
invokeinterface
和第35行。好吧,我知道这是类字段(getfield
)。我想知道如何获取其余信息:
字段名称是
strings
被调用的接口方法是
add()
到目前为止,谷歌搜索和阅读API文档都没有得到任何积极的结果。
最佳答案
这是一项艰苦的工作,需要了解JVM类格式和指令集。
任何答案只能提供部分数据。特别是Javassist。在指令中,通常一个参数是常量池中的索引,其中存在一个对象,该对象具有名称的索引和类型的索引。因此,请注意您正在进入的领域。
如果使用调试信息编译该类,则可以访问私有字段名称(ClassFile.getFields)。
有一个很好的Dump工具,包含了javassist。
private void dumpMyDataClass() throws IOException, BadBytecode, Exception {
ClassFile cf = new ClassFile(new DataInputStream(getClass().getResourceAsStream("MyData.class")));
// Dump fields:
for (Object fieldInfoObj : cf.getFields()) {
FieldInfo fieldInfo = (FieldInfo) fieldInfoObj;
System.out.printf("Field %s; %s%n", fieldInfo.getName(), fieldInfo.getDescriptor());
}
MethodInfo minfo = cf.getMethod("add");
CodeAttribute ca = minfo.getCodeAttribute();
for (CodeIterator ci = ca.iterator(); ci.hasNext();) {
int address = ci.next();
int op = ci.byteAt(address);
String params = "";
switch (op) {
case Opcode.INVOKEINTERFACE:
int a1 = ci.s16bitAt(address + 1);
params += " " + cf.getConstPool().getInterfaceMethodrefName(a1);
System.out.println("a1 = " + a1);
break;
}
System.out.printf("Line %4d. Address %7d: %s%s%n", minfo.getLineNumber(address), address, Mnemonic.OPCODE[op], params);
}
// Command line tool of javassist:
String pathToClass = System.getProperty("user.dir") + "/target/classes/jeggen/test2/MyData.class";
Dump.main(new String[] { pathToClass });
}
关于java - 使用javassist获取操作数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9488136/