BCELって何? †
解析プログラムのひな形 †
package com.example.quiz7;
import java.io.File;
import java.io.FileInputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
public class BcelExam {
public static void main(final String[] args) {
try {
BcelExam thisClass = new BcelExam();
thisClass.dirWalk(new File("target/classes"));
} catch (Exception ex) {
Logger.getLogger(BcelExam.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void dirWalk(File path) throws Exception {
if (path.isDirectory()) {
for (File child : path.listFiles()) {
dirWalk(child);
}
} else if (path.getName().endsWith("jar") || path.getName().endsWith("zip")) {
jarWalk(path);
} else if (path.getName().endsWith("class")) {
JavaClass javaClass = new ClassParser(path.getAbsolutePath()).parse();
classWalk(javaClass);
}
}
private void jarWalk(File jarFile) throws Exception {
try (JarInputStream jarIn = new JarInputStream(new FileInputStream(jarFile));) {
JarEntry entry;
while ((entry = jarIn.getNextJarEntry()) != null) {
if (!entry.isDirectory()) {
String fileName = entry.getName();
if (fileName.endsWith("class")) {
JavaClass javaClass = new ClassParser(jarFile.getAbsolutePath(), fileName).parse();
classWalk(javaClass);
}
}
}
}
}
private void classWalk(final JavaClass javaClass) {
final org.apache.bcel.classfile.Method[] methods = javaClass.getMethods();
for (org.apache.bcel.classfile.Method method : methods) {
methodWalk(javaClass.getClassName(), method);
}
}
private void methodWalk(final String clazz, final org.apache.bcel.classfile.Method method) {
codeWalk(clazz + "#" + method.getName(), method.getCode());
}
private void codeWalk(final String method, final Code code) {
System.out.println(method);
if (code == null) {
// Interfaceの場合
return;
}
for (String line : code.toString().split("\n")) {
System.out.println(line);
}
}
}
- あとは、読み込んだバイトコードを分析して、有向グラフ (dot言語) にしたりする
自分を読み込んだ結果 †
com.example.quiz7.BcelExam#main
Code(max_stack = 4, max_locals = 2, code_length = 43)
0: new <com.example.quiz7.BcelExam> (2)
3: dup
4: invokespecial com.example.quiz7.BcelExam.<init> ()V (3)
7: astore_1
8: aload_1
9: new <java.io.File> (4)
12: dup
13: ldc "target/classes" (5)
15: invokespecial java.io.File.<init> (Ljava/lang/String;)V (6)
18: invokespecial com.example.quiz7.BcelExam.dirWalk (Ljava/io/File;)V (7)
21: goto #42
24: astore_1
25: ldc_w com.example.quiz7.BcelExam (2)
28: invokevirtual java.lang.Class.getName ()Ljava/lang/String; (9)
31: invokestatic java.util.logging.Logger.getLogger (Ljava/lang/String;)Ljava/util/logging/Logger; (10)
34: getstatic java.util.logging.Level.SEVERE Ljava/util/logging/Level; (11)
37: aconst_null
38: aload_1
39: invokevirtual java.util.logging.Logger.log (Ljava/util/logging/Level;Ljava/lang/String;Ljava/lang/Throwable;)V (12)
42: return
Exception handler(s) =
From To Handler Type
0 21 24 java.lang.Exception(8)
Attribute(s) =
LineNumber(0, 21), LineNumber(8, 22), LineNumber(21, 25), LineNumber(24, 23),
LineNumber(25, 24), LineNumber(42, 26)
LocalVariable(start_pc = 8, length = 13, index = 1:com.example.quiz7.BcelExam thisClass)
LocalVariable(start_pc = 25, length = 17, index = 1:Exception ex)
LocalVariable(start_pc = 0, length = 43, index = 0:String[] args)
(Unknown attribute StackMapTable: 00 02 58 07 00 45 11)
com.example.quiz7.BcelExam#dirWalk
Code(max_stack = 3, max_locals = 6, code_length = 110)
0: aload_1
1: invokevirtual java.io.File.isDirectory ()Z (13)
4: ifeq #45
7: aload_1
8: invokevirtual java.io.File.listFiles ()[Ljava/io/File; (14)
11: astore_2
12: aload_2
13: arraylength
14: istore_3
15: iconst_0
16: istore %4
18: iload %4
20: iload_3
21: if_icmpge #42
24: aload_2
25: iload %4
27: aaload
28: astore %5
30: aload_0
31: aload %5
33: invokespecial com.example.quiz7.BcelExam.dirWalk (Ljava/io/File;)V (7)
36: iinc %4 1
39: goto #18
42: goto #109
45: aload_1
46: invokevirtual java.io.File.getName ()Ljava/lang/String; (15)
49: ldc "jar" (16)
51: invokevirtual java.lang.String.endsWith (Ljava/lang/String;)Z (17)
54: ifne #69
57: aload_1
58: invokevirtual java.io.File.getName ()Ljava/lang/String; (15)
61: ldc "zip" (18)
63: invokevirtual java.lang.String.endsWith (Ljava/lang/String;)Z (17)
66: ifeq #77
69: aload_0
70: aload_1
71: invokespecial com.example.quiz7.BcelExam.jarWalk (Ljava/io/File;)V (19)
74: goto #109
77: aload_1
78: invokevirtual java.io.File.getName ()Ljava/lang/String; (15)
81: ldc "class" (20)
83: invokevirtual java.lang.String.endsWith (Ljava/lang/String;)Z (17)
86: ifeq #109
89: new <org.apache.bcel.classfile.ClassParser> (21)
92: dup
93: aload_1
94: invokevirtual java.io.File.getAbsolutePath ()Ljava/lang/String; (22)
97: invokespecial org.apache.bcel.classfile.ClassParser.<init> (Ljava/lang/String;)V (23)
100: invokevirtual org.apache.bcel.classfile.ClassParser.parse ()Lorg/apache/bcel/classfile/JavaClass; (24)
103: astore_2
104: aload_0
105: aload_2
106: invokespecial com.example.quiz7.BcelExam.classWalk (Lorg/apache/bcel/classfile/JavaClass;)V (25)
109: return
...
- invokespecial の行を拾っていけば呼び出し関係のグラフを作れるだろう
Java#Jakarta