ある文字列を含むメソッドを呼び出しているメソッドを探す
2014/04/24
asm
java
javaです。
「ある文字列を含むメソッドを呼び出しているメソッドを探す」です。
かなりわかりずらいですが。自分でもいったい何がしたいのかわからなくなってしまってたりします。
イメージとしては、eclipseで検索して特定の文字列を含んでいるメソッドを探して、そのメソッドを参照しているクラスを探すという感じです。
なんとかidみたいなものをマジックワードとしてもっていて、それが埋め込まれているメソッドを呼び出しているメソッドを探したい。
asmを使ってます。
「ある文字列を含むメソッドを呼び出しているメソッドを探す」です。
かなりわかりずらいですが。自分でもいったい何がしたいのかわからなくなってしまってたりします。
イメージとしては、eclipseで検索して特定の文字列を含んでいるメソッドを探して、そのメソッドを参照しているクラスを探すという感じです。
なんとかidみたいなものをマジックワードとしてもっていて、それが埋め込まれているメソッドを呼び出しているメソッドを探したい。
asmを使ってます。
package a;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
public class TestAsm2 {
interface IExecutor {
public void execute(File file) throws Exception;
}
public static class SearchM {
public String className;
final public List<String> list = new ArrayList<String>();
}
public static class Holder {
public String name;
final public List<String> list = new ArrayList<String>();
public boolean hit() {
return 0 < list.size();
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("name:[").append(name).append("] list:[")
.append(list).append("] hit:[").append(hit()).append("]");
return builder.toString();
}
}
public static void main(String[] args) throws Exception {
a();
}
static void a() throws Exception {
final URL url = TestAsm2.class.getResource("/");
searchAll(new File(url.toURI()), new IExecutor() {
@Override
public void execute(File f) throws Exception {
Holder holder = searchWord(new FileInputStream(f), "aaa_1234");
// System.out.println(holder);
if (holder.hit()) {
final SearchM searchM = new SearchM();
searchM.className = holder.name;
searchM.list.addAll(holder.list);
searchAll(new File(url.toURI()), new IExecutor() {
@Override
public void execute(File file) throws Exception {
Holder holder = searchMethod(new FileInputStream(
file), searchM);
if (holder.hit()) {
System.out.println(">>>>>>" + holder);
}
}
});
}
}
});
}
public static void searchAll(File root, IExecutor executor)
throws Exception {
if (!root.isDirectory())
return;
File[] files = root.listFiles();
for (File f : files) {
if (f.isDirectory()) {
searchAll(f, executor);
continue;
}
if (!f.getName().endsWith(".class")) {
continue;
}
executor.execute(f);
}
}
/**
* 指定された文字列をメソッドに含むクラスと、メソッド名をみつけます。
*
* @param is
* @param word
* @return
*/
static Holder searchWord(InputStream is, String word) {
final Holder holder = new Holder();
try {
ClassReader reader = new ClassReader(is);
ClassNode classNode = new ClassNode();
reader.accept(classNode, 0);
List<MethodNode> methodList = classNode.methods;
for (MethodNode methodNode : methodList) {
Iterator<AbstractInsnNode> instraIter = methodNode.instructions
.iterator();
while (instraIter.hasNext()) {
AbstractInsnNode abi = instraIter.next();
// System.out.println(abi.getClass());
if (abi instanceof LdcInsnNode) {
// LdcInsnNode であるものから
LdcInsnNode ldcI = (LdcInsnNode) abi;
// System.out.println("LDC node value: " + ldcI.cst);
if (word.equals(ldcI.cst)) {
holder.name = classNode.name;
holder.list.add(methodNode.name);
}
continue;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return holder;
}
static Holder searchMethod(InputStream is, SearchM searchM) {
final Holder holder = new Holder();
try {
ClassReader reader = new ClassReader(is);
ClassNode classNode = new ClassNode();
reader.accept(classNode, 0);
List<MethodNode> methodList = classNode.methods;
for (MethodNode methodNode : methodList) {
Iterator<AbstractInsnNode> instraIter = methodNode.instructions
.iterator();
while (instraIter.hasNext()) {
AbstractInsnNode abi = instraIter.next();
if (abi instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) abi;
if (methodInsnNode.owner.equals(searchM.className)
&& searchM.list.contains(methodInsnNode.name)) {
// 使っているクラス名
holder.name = classNode.name;
// 使っているメソッド
holder.list.add(methodNode.name);
}
continue;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return holder;
}
}
: