Java バイトコードから INVOKESPECIAL 命令で参照されているクラスを読み取ったり、特定したりすることはできますか? はいの場合、どのように?また、ジャンプ後に実行される次の行はどうすればわかりますか?
これを行うプログラムを作成したいことを覚えておいてください。私がやろうとしているのは、バイトコードだけで例外処理を自動的にローカライズする方法を見つけることです。
このフレームワークはhttp://asm.ow2.org/で確認できます。「ASM フレームワークは、バイトコード操作を行うための、最も高速で最も柔軟でよく知られているフレームワークです」
バイトコード操作用のフレームワークはたくさんあります。しかし、個人的にはASMの方が好きです。XML 解析のようなメカニズムは、習得がはるかに簡単です。
たとえば、次のコードを使用INVOKESPECIAL
して、jar ファイル内のすべての呼び出しを一覧表示できます。次のような行が出力されます。
INVOKESPECIAL[ opcode=183, owner=java/lang/StringBuilder, name=<init>, desc=()V]
.
によって参照されるのは の<init>
機能であると言えます。java/lang/StringBuilder
INVOKESPECIAL
JarFile jarFile = new JarFile("xxx.jar");
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
if (jarEntry != null && jarEntry.getName().endsWith(".class")) {
InputStream eis = jarFile.getInputStream(jarEntry);
ClassReader classReader = new ClassReader(eis);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
MyClassVisitor mcw = new MyClassVisitor(Opcodes.ASM4, cw);
classReader.accept(mcw, 0);
eis.close();
}
}
class MyClassVisitor extends ClassVisitor {
private int api;
public MyClassVisitor(int api, ClassWriter cw) {
super(api, cw);
this.api = api;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
return new MyMethodVisitor(api, mv);
}
class MyMethodVisitor extends MethodVisitor {
public MyMethodVisitor(int api, MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if (opcode == Opcodes.INVOKESPECIAL) {
System.out.println("INVOKESPECIAL[ opcode=" + opcode + ", owner=" + owner + ", name=" + name
+ ", desc=" + desc+"]");
}
super.visitMethodInsn(opcode, owner, name, desc);
}
}
}