OSDN Git Service

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