バイトコードを生成してみました。
ここでは、次のようなコードを生成しています。
public class ByteCodeGenerator{ public static int eval(){ return 34; } }
なので、下のプログラムを実行すると34が表示されます。
クラスファイルの仕様はここ
Java SE Specifications
バイトコードの一覧は、Wikipediaがアルファベット順になってて見やすい
Java bytecode - Wikipedia
import java.io.*; public class ByteCode { public static void main(String[] a) throws Exception{ String className = "ByteCodeGenerate"; String methodName = "eval"; ByteArrayOutputStream buf = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(buf); dos.writeInt(0xcafebabe);//クラスファイルを識別するマジックナンバー dos.writeShort(0);//マイナーバージョン dos.writeShort(49);//メジャーバージョン //定数の出力 ByteArrayOutputStream constbuf = new ByteArrayOutputStream(); DataOutputStream constos = new DataOutputStream(constbuf); int id = 1; int idClassName = id++; constos.writeByte(1);//識別子 constos.writeUTF(className); int idMethod = id++; constos.writeByte(1);//識別子 constos.writeUTF(methodName); int idType = id++; constos.writeByte(1);//識別子 constos.writeUTF("()I"); int idObj = id++; constos.writeByte(1);//識別子 constos.writeUTF("java/lang/Object"); int idClassObj = id++; constos.writeByte(7);//クラス constos.writeShort(idObj); int idClass = id++; constos.writeByte(7);//クラス constos.writeShort(idClassName); int idCode = id++; constos.writeByte(1);//識別子 constos.writeUTF("Code");//コード用の属性名 constos.close(); constbuf.close(); dos.writeShort(id);//定数の個数(実際の個数より1多くする) dos.write(constbuf.toByteArray()); //クラス dos.writeShort(0x21);// アクセス指定 ACC_SUPER(0x20) | ACC_PUBLIC(0x01) dos.writeShort(idClass);//クラス dos.writeShort(idClassObj);//スーパークラス dos.writeShort(0);//インタフェースの個数 dos.writeShort(0);//フィールドの数 dos.writeShort(1);//メソッドの数 //メソッド dos.writeShort(9);// アクセス指定 ACC_PUBLIC(0x01) | ACC_STATIC(0x08) dos.writeShort(idMethod);//名前 dos.writeShort(idType);//シグネチャ dos.writeShort(1);//属性の数(ここではメソッド本体) dos.writeShort(idCode);//属性名(Code) dos.writeInt(15);//属性の長さ dos.writeShort(1);//最大スタック dos.writeShort(0);//最大変数 dos.writeInt(3);//コードのバイト数 //メソッド dos.writeByte(0x10);//bipush dos.writeByte(34); dos.writeByte(0xac);//ireturn; //メソッドおわり dos.writeShort(0);//例外の数 dos.writeShort(0);//属性の数 dos.writeShort(0);//属性の数 dos.close(); buf.close(); //クラスファイルを読み込んで実行 final byte[] code = buf.toByteArray(); ClassLoader cl = new ClassLoader(){ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { return defineClass(null, code, 0, code.length); } }; Class expClass = cl.loadClass(className); int ret = (Integer)expClass.getMethod(methodName).invoke(null, new Object[0]); System.out.println(ret); } }