OSDN Git Service

coding.
[jcfa/jcfa.git] / jcfa / src / jp / igapyon / jcfa / JavaClassFileAnalyzer.java
1 package jp.igapyon.jcfa;\r
2 \r
3 import java.io.File;\r
4 import java.io.IOException;\r
5 \r
6 import jp.igapyon.jcfa.util.JcfaUtil;\r
7 \r
8 import org.apache.bcel.Constants;\r
9 /**\r
10  * Apache Jakarta BCELを用いたクラスファイル(バイトコード)解析サンプル\r
11  */\r
12 import org.apache.bcel.classfile.ClassFormatException;\r
13 import org.apache.bcel.classfile.ClassParser;\r
14 import org.apache.bcel.classfile.Code;\r
15 import org.apache.bcel.classfile.ConstantValue;\r
16 import org.apache.bcel.classfile.Field;\r
17 import org.apache.bcel.classfile.JavaClass;\r
18 import org.apache.bcel.classfile.Method;\r
19 \r
20 public class JavaClassFileAnalyzer {\r
21         private static final String CLASS_MODULE = "./bin/test/TestJavaClass002.class";\r
22 \r
23         public static final void main(final String[] args) {\r
24                 new JavaClassFileAnalyzer().process(new File(CLASS_MODULE), new File(\r
25                                 "./test/output"));\r
26         }\r
27 \r
28         private final void process(final File inputFile, final File outputDir) {\r
29                 try {\r
30                         final JavaClass jc = new ClassParser(inputFile.getCanonicalPath())\r
31                                         .parse();\r
32                         System.out.println("Classname   : " + jc.getClassName());\r
33                         System.out.println("Parent class: " + jc.getSuperclassName());\r
34 \r
35                         analyzeFields(jc);\r
36                         analyzeMethods(jc);\r
37                 } catch (ClassFormatException e) {\r
38                         e.printStackTrace();\r
39                 } catch (IOException e) {\r
40                         e.printStackTrace();\r
41                 }\r
42         }\r
43 \r
44         private void analyzeFields(final JavaClass jc) {\r
45                 final org.apache.bcel.classfile.Field[] fields = jc.getFields();\r
46                 for (int indexField = 0; indexField < fields.length; indexField++) {\r
47                         final Field field = fields[indexField];\r
48                         analyzeField(jc, field);\r
49                 }\r
50         }\r
51 \r
52         private void analyzeField(final JavaClass jc, final Field field) {\r
53                 System.out.println("  Field:" + field.getName());\r
54                 String access = "";\r
55                 access += field.isPublic() ? "public " : "";\r
56                 access += field.isProtected() ? "protected " : "";\r
57                 access += field.isPrivate() ? "private " : "";\r
58                 access += field.isAbstract() ? "abstract " : "";\r
59                 access += field.isStatic() ? "static " : "";\r
60                 access += field.isVolatile() ? "volatile " : "";\r
61                 access += field.isFinal() ? "final " : "";\r
62 \r
63                 String constValue = null;\r
64                 final ConstantValue cv = field.getConstantValue();\r
65                 if (cv != null) {\r
66                         constValue = jc.getConstantPool().getConstantString(\r
67                                         cv.getConstantValueIndex(), Constants.CONSTANT_String);\r
68                 }\r
69                 System.out.println("    " + access + field.getType().toString() + " "\r
70                                 + field.getName()\r
71                                 + (constValue == null ? "" : " = \"" + constValue + "\""));\r
72         }\r
73 \r
74         private void analyzeMethods(final JavaClass jc) throws IOException {\r
75                 final org.apache.bcel.classfile.Method[] methods = jc.getMethods();\r
76                 for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {\r
77                         final Method method = methods[indexMethod];\r
78                         analyzeMethod(jc, method);\r
79 \r
80                 }\r
81         }\r
82 \r
83         private void analyzeMethod(final JavaClass jc, final Method method)\r
84                         throws IOException {\r
85                 System.out.println("  Method:" + method.getName());\r
86                 final Code code = method.getCode();\r
87                 if (code == null) {\r
88                         return;\r
89                 }\r
90 \r
91                 final byte[] codes = code.getCode();\r
92                 for (int pc = 0; pc < codes.length; pc++) {\r
93                         final short opcode = JcfaUtil.byte2UnsignedByte(codes[pc]);\r
94                         short operands = Constants.NO_OF_OPERANDS[opcode];\r
95                         if (operands < 0) {\r
96                                 System.out.println("  TODO negative value:"\r
97                                                 + Constants.OPCODE_NAMES[opcode] + ": " + operands);\r
98                                 // break;\r
99                         }\r
100 \r
101                         switch (opcode) {\r
102                         case Constants.RETURN: {\r
103                                 System.out.println("    " + pc + ": "\r
104                                                 + Constants.OPCODE_NAMES[opcode]);\r
105                                 break;\r
106                         }\r
107                         case Constants.GETSTATIC: {\r
108                                 System.out.println("    "\r
109                                                 + pc\r
110                                                 + ": "\r
111                                                 + Constants.OPCODE_NAMES[opcode]\r
112                                                 + ": "\r
113                                                 + JcfaUtil.getConstantFieldrefString(jc, codes[pc + 1],\r
114                                                                 codes[pc + 2]));\r
115                                 break;\r
116                         }\r
117                         case Constants.LDC: {\r
118                                 System.out.println("    " + pc + ": "\r
119                                                 + Constants.OPCODE_NAMES[opcode] + ": "\r
120                                                 + JcfaUtil.getConstantString(jc, codes[pc + 1]));\r
121                         }\r
122                                 break;\r
123                         case Constants.INVOKEVIRTUAL:\r
124                         case Constants.INVOKESPECIAL: {\r
125                                 final int operand = JcfaUtil.byte2UnsignedShort(codes[pc + 1],\r
126                                                 codes[pc + 2]);\r
127                                 System.out.println("    " + pc + ": "\r
128                                                 + Constants.OPCODE_NAMES[opcode] + ": "\r
129                                                 + JcfaUtil.getConstantMethodRefString(jc, operand));\r
130                         }\r
131                                 break;\r
132                         case Constants.LOOKUPSWITCH:\r
133                                 int result = JcfaUtil.byte2Int(codes[pc + 1], codes[pc + 2],\r
134                                                 codes[pc + 3], codes[pc + 4]);\r
135                                 System.out.println("  TODO skipping bytes: " + (result));\r
136 \r
137                                 int lookupOp = pc + 5;\r
138 \r
139                                 short diff = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
140                                 System.out.println("  TODO skipping bytes: " + (diff));\r
141 \r
142                                 int loopCount = JcfaUtil\r
143                                                 .byte2Int(codes[lookupOp++], codes[lookupOp++],\r
144                                                                 codes[lookupOp++], codes[lookupOp++]);\r
145                                 for (int index = 0; index < loopCount; index++) {\r
146                                         System.out.println("      "\r
147                                                         + JcfaUtil.byte2Int(codes[lookupOp++],\r
148                                                                         codes[lookupOp++], codes[lookupOp++],\r
149                                                                         codes[lookupOp++])\r
150                                                         + ":"\r
151                                                         + (JcfaUtil.byte2Int(codes[lookupOp++],\r
152                                                                         codes[lookupOp++], codes[lookupOp++],\r
153                                                                         codes[lookupOp++]) + pc));\r
154                                 }\r
155 \r
156                                 short diff2 = JcfaUtil.byte2UnsignedByte(codes[lookupOp++]);\r
157                                 System.out.println("  TODO skipping bytes: " + (diff2));\r
158 \r
159                                 operands += (lookupOp - pc);\r
160 \r
161                                 break;\r
162                         default: {\r
163                                 System.out.println("    " + pc + ": "\r
164                                                 + Constants.OPCODE_NAMES[opcode] + " (" + operands\r
165                                                 + ")");\r
166                         }\r
167                                 break;\r
168                         }\r
169                         pc += operands;\r
170                 }\r
171         }\r
172 }