--- /dev/null
+package jp.igapyon.jcfa;\r
+\r
+import java.io.IOException;\r
+\r
+import jp.igapyon.jcfa.util.JcfaUtil;\r
+\r
+import org.apache.bcel.Constants;\r
+/**\r
+ * Apache Jakarta BCELを用いたクラスファイル(バイトコード)解析サンプル\r
+ */\r
+import org.apache.bcel.classfile.ClassFormatException;\r
+import org.apache.bcel.classfile.ClassParser;\r
+import org.apache.bcel.classfile.Code;\r
+import org.apache.bcel.classfile.JavaClass;\r
+import org.apache.bcel.classfile.Method;\r
+\r
+public class JavaClassFileAnalyzer {\r
+ private static final String CLASS_MODULE = "./bin/test/TestJavaClass001.class";\r
+\r
+ public static final void main(final String[] args) {\r
+ new JavaClassFileAnalyzer().process();\r
+ }\r
+\r
+ private final void process() {\r
+ try {\r
+ final JavaClass jc = new ClassParser(CLASS_MODULE).parse();\r
+ System.out.println("Classname : " + jc.getClassName());\r
+ System.out.println("Parent class: " + jc.getSuperclassName());\r
+\r
+ final org.apache.bcel.classfile.Method[] methods = jc.getMethods();\r
+ for (int indexMethod = 0; indexMethod < methods.length; indexMethod++) {\r
+ final Method method = methods[indexMethod];\r
+ System.out.println(" Method:" + method.getName());\r
+ final Code code = method.getCode();\r
+ if (code == null) {\r
+ continue;\r
+ }\r
+\r
+ final byte[] codes = code.getCode();\r
+ for (int pc = 0; pc < codes.length; pc++) {\r
+ final short opcode = JcfaUtil.byte2UnsignedByte(codes[pc]);\r
+ short operands = Constants.NO_OF_OPERANDS[opcode];\r
+ if (operands < 0) {\r
+ System.out.println(" TODO negative value:"\r
+ + Constants.OPCODE_NAMES[opcode] + ": "\r
+ + operands);\r
+ // break;\r
+ }\r
+\r
+ switch (opcode) {\r
+ case Constants.RETURN: {\r
+ System.out.println(" " + pc + ": "\r
+ + Constants.OPCODE_NAMES[opcode]);\r
+ break;\r
+ }\r
+ case Constants.GETSTATIC: {\r
+ System.out.println(" "\r
+ + pc\r
+ + ": "\r
+ + Constants.OPCODE_NAMES[opcode]\r
+ + ": "\r
+ + JcfaUtil.getConstantFieldrefString(jc,\r
+ codes[pc + 1], codes[pc + 2]));\r
+ break;\r
+ }\r
+ case Constants.LDC: {\r
+ System.out\r
+ .println(" "\r
+ + pc\r
+ + ": "\r
+ + Constants.OPCODE_NAMES[opcode]\r
+ + ": "\r
+ + JcfaUtil.getConstantString(jc,\r
+ codes[pc + 1]));\r
+ }\r
+ break;\r
+ case Constants.INVOKEVIRTUAL:\r
+ case Constants.INVOKESPECIAL: {\r
+ final int operand = JcfaUtil.byte2UnsignedShort(\r
+ codes[pc + 1], codes[pc + 2]);\r
+ System.out.println(" "\r
+ + pc\r
+ + ": "\r
+ + Constants.OPCODE_NAMES[opcode]\r
+ + ": "\r
+ + JcfaUtil.getConstantMethodRefString(jc,\r
+ operand));\r
+ }\r
+ break;\r
+ case Constants.LOOKUPSWITCH:\r
+ int result = JcfaUtil.byte2Int(codes[pc + 1],\r
+ codes[pc + 2], codes[pc + 3], codes[pc + 4]);\r
+ System.out\r
+ .println(" TODO skipping bytes: " + (result));\r
+\r
+ int lookupOp = pc + 5;\r
+\r
+ short diff = JcfaUtil\r
+ .byte2UnsignedByte(codes[lookupOp++]);\r
+ System.out.println(" TODO skipping bytes: " + (diff));\r
+\r
+ int loopCount = JcfaUtil.byte2Int(codes[lookupOp++],\r
+ codes[lookupOp++], codes[lookupOp++],\r
+ codes[lookupOp++]);\r
+ for (int index = 0; index < loopCount; index++) {\r
+ System.out.println(" "\r
+ + JcfaUtil.byte2Int(codes[lookupOp++],\r
+ codes[lookupOp++],\r
+ codes[lookupOp++],\r
+ codes[lookupOp++])\r
+ + ":"\r
+ + (JcfaUtil.byte2Int(codes[lookupOp++],\r
+ codes[lookupOp++],\r
+ codes[lookupOp++],\r
+ codes[lookupOp++]) + pc));\r
+ }\r
+\r
+ short diff2 = JcfaUtil\r
+ .byte2UnsignedByte(codes[lookupOp++]);\r
+ System.out.println(" TODO skipping bytes: " + (diff2));\r
+\r
+ operands += (lookupOp - pc);\r
+\r
+ break;\r
+ default: {\r
+ System.out.println(" " + pc + ": "\r
+ + Constants.OPCODE_NAMES[opcode] + " ("\r
+ + operands + ")");\r
+ }\r
+ break;\r
+ }\r
+ pc += operands;\r
+ }\r
+ }\r
+ } catch (ClassFormatException e) {\r
+ e.printStackTrace();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+package jp.igapyon.jcfa.util;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.DataInputStream;\r
+import java.io.IOException;\r
+\r
+import org.apache.bcel.Constants;\r
+import org.apache.bcel.classfile.ConstantClass;\r
+import org.apache.bcel.classfile.ConstantFieldref;\r
+import org.apache.bcel.classfile.ConstantMethodref;\r
+import org.apache.bcel.classfile.ConstantNameAndType;\r
+import org.apache.bcel.classfile.ConstantPool;\r
+import org.apache.bcel.classfile.ConstantString;\r
+import org.apache.bcel.classfile.ConstantUtf8;\r
+import org.apache.bcel.classfile.JavaClass;\r
+\r
+public class JcfaUtil {\r
+ private JcfaUtil() {\r
+ }\r
+\r
+ public static short byte2UnsignedByte(final byte byte1) {\r
+ short word = byte1;\r
+ if (word < 0) {\r
+ word += 0x100;\r
+ }\r
+ return word;\r
+ }\r
+\r
+ public static int byte2UnsignedShort(final byte byte1, final byte byte2) {\r
+ short word1 = byte1;\r
+ short word2 = byte2;\r
+ if (word1 < 0) {\r
+ word1 += 0x100;\r
+ }\r
+ if (word2 < 0) {\r
+ word2 += 0x100;\r
+ }\r
+ return word1 * 0x100 + word2;\r
+ }\r
+\r
+ public static int byte2Int(final byte byte1, final byte byte2,\r
+ final byte byte3, final byte byte4) throws IOException {\r
+ return new DataInputStream(new ByteArrayInputStream(new byte[] { byte1,\r
+ byte2, byte3, byte4 })).readInt();\r
+ }\r
+\r
+ public static String getConstantString(final JavaClass jc,\r
+ final byte operand) {\r
+ final ConstantPool cp = jc.getConstantPool();\r
+ final ConstantString constRef = (ConstantString) cp.getConstant(\r
+ JcfaUtil.byte2UnsignedByte(operand), Constants.CONSTANT_String);\r
+ return constRef.getBytes(cp);\r
+ }\r
+\r
+ public static String getConstantFieldrefString(final JavaClass jc,\r
+ final byte byte1, final byte byte2) {\r
+ final ConstantPool cp = jc.getConstantPool();\r
+ final ConstantFieldref constRef = (ConstantFieldref) cp.getConstant(\r
+ JcfaUtil.byte2UnsignedShort(byte1, byte2),\r
+ Constants.CONSTANT_Fieldref);\r
+ final ConstantNameAndType constNameAndTypeUtf8 = (ConstantNameAndType) cp\r
+ .getConstant(constRef.getNameAndTypeIndex(),\r
+ Constants.CONSTANT_NameAndType);\r
+ return constRef.getClass(cp) + "#" + constNameAndTypeUtf8.getName(cp)\r
+ + " type:" + constNameAndTypeUtf8.getSignature(cp);\r
+ }\r
+\r
+ public static String getConstantMethodRefString(final JavaClass jc,\r
+ final int operand) {\r
+ final ConstantPool cp = jc.getConstantPool();\r
+ final ConstantMethodref constRef = (ConstantMethodref) cp.getConstant(\r
+ operand, Constants.CONSTANT_Methodref);\r
+ final ConstantClass constClass = (ConstantClass) cp.getConstant(\r
+ constRef.getClassIndex(), Constants.CONSTANT_Class);\r
+ final ConstantUtf8 constClassUtf8 = (ConstantUtf8) cp.getConstant(\r
+ constClass.getNameIndex(), Constants.CONSTANT_Utf8);\r
+ final ConstantNameAndType constNameAndTypeUtf8 = (ConstantNameAndType) cp\r
+ .getConstant(constRef.getNameAndTypeIndex(),\r
+ Constants.CONSTANT_NameAndType);\r
+\r
+ return (constClassUtf8.getBytes() + "#"\r
+ + constNameAndTypeUtf8.getName(cp) + constNameAndTypeUtf8\r
+ .getSignature(cp));\r
+ }\r
+}\r