- - PR -
バイトコードへの追加書き込み
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-11-30 02:45
こんにちは。
Javaバイトコードを読み込み、フィールドが変更されたり、メソッドが変更されたらイベントハンドラーで報告するという処理を付け加えてファイルに出力したいと思います。 その後、オブジェクトダイアグラムと任意のクラス図を比較してそのオブジェクトがクラス図に沿っているかどうかをチェックするという一連の流れの第一段階として、先ほどあげた処理が必要となってきます。 ASMを利用という制約があるので、Javassistは使えないかと思います。(調べたところ、便利そうなのですが) バイトコードを読み込む際、classRoaderで読み込んでくるのでしょうが、いまいち取り掛かりがつかめません。 以前jarファイル内の、Javaプログラムから各クラスの要素を取得したことはあるので、それを利用できるのかと思いますが、javaプログラムではなく、バイトコードでも全く同じプログラムで動くのでしょうか。 ちなみに、jarファイル利用の時にはASMを利用しなかったので、以下のようなプログラムを使っていました。 ------- File file = new File("c:/hoge.jar"); JarFile jarfile = new JarFile(file); //JARファイルを読み込むクラスローダーを生成 URLClassLoader classLoader = new URLClassLoader(new URL[]{file.toURL()}); Thread.currentThread().setContextClassLoader(classLoader); for (Enumeration en = jarfile.entries(); en.hasMoreElements();){ JarEntry entry = (JarEntry)en.nextElement(); if (entry.getName().endsWith(".class")){ //クラスの完全修飾名に置換 "jp/co/Hoge.class"→"jp.co.Hoge.class" String className = entry.getName().replaceAll("/", "\\\\.").replaceAll("\\\\.class$", ""); //クラスをロード Class cls = classLoader.loadClass(className); //クラス名 System.out.print(cls.isInterface() ? "Interface: " : "Class: "); System.out.print(cls.getName()); System.out.print(cls.getSuperclass() == null ? "" : " extends " + cls.getSuperclass().getName()); //フィールドの列挙 System.out.println(); for (Iterator itr = Arrays.asList(cls.getDeclaredFields()).iterator(); itr.hasNext();){ Field field = (Field)itr.next(); System.out.println("Attribute: " + field.getName() + " : " + field.getType()); } // メソッドの列挙等々.... } } 初歩的な質問で申し訳ありませんが、よろしくお願いします。 | ||||||||||||
|
投稿日時: 2006-11-30 10:27
質問の意図がよくわかりません。もう少し整理してもらえませんか。
フィールドの状態やメソッドの中身の変化を検出するためにASMを使用しているが、 リフレクションAPIと同等なこともASMでやりたい、それは可能だろうか? ということでしょうか。 | ||||||||||||
|
投稿日時: 2006-11-30 11:08
「Javaプログラム」と「バイトコード」をどう使い分けてるのでしょうか。 どちらもclassファイルをさしているのではないのですか? jarファイルをさしてJavaプログラムと言っているのかな…
バイトコードを読み込んだ上で、バイトコードに手を加えて 別のclassファイルとして書き出す、というように読めますが…。 似たような話といえばAspectJでアスペクトのウィービングに際して そのようなことをやっているという話を聞いたことがありますが。(うろ覚え) バイトコードをいじりたいのであれば、VMがバイトコードをどう扱っているか 基礎知識として抑えておきましょう。 http://www.amazon.co.jp/exec/obidos/ASIN/489471356X/ Javassistというのは寡聞にして知りませんでしたが、 最近ではバイトコードをいじるライブラリまで出てるんですねぇ。
バイトコードを書き換えるのは実行時チェックを行うためかと思いましたが。 こういった処理は通常はコンパイルと同レベルで静的に行うものではないのですか? 単に動的チェックを行うだけならバイトコード書き換えではなく JDI(Java Debug Interface)などの手法も考えられると思います。 | ||||||||||||
|
投稿日時: 2006-11-30 12:31
すみません。すっかり勘違いしていました。
Javaプログラムと、バイトコードは同じことですね。 とても分かりづらい投稿ですみません。 nagiseさんのおっしゃるとおり、「バイトコードを読み込んだ上で、バイトコードに手を加えて別のclassファイルとして書き出す」ということです。 もっと詳しくいうと、 ・jarファイルの中にvalify()というメソッドが含まれている ・valify()が呼ばれたときに任意のUMLclassファイルと比較する ・jarファイルがUMLclassファイルとあっているかどうかチェック。 ・もしあっていなければ、エラーを表示する というものを作ろうと思っています。 その流れのうちの一部である、バイトコードを読み込んだ上で、バイトコードに手を加えて別のclassファイルとして書き出す部分についてお聞きしていました。 お分かりいただけたでしょうか? | ||||||||||||
|
投稿日時: 2006-11-30 13:29
「jarファイルの中」に「valify()というメソッド」が含まれているというのが ちょっと理解しがたいですが。 jarファイルに検証用のvalify()というメソッドをもったクラスが含まれているとか? それとも総当りでvalify()というメソッドを持つクラスを探す? で、UMLとの比較は実行時に動的に行わないといけないんですか? そういう仕様です、と言われればそれまでですが。 根底を覆すような話で悪いのですけども、どうにもclassファイルの 書き換えまでして動的にやらないといけない理由がさっぱりわからない。 valify()なんていう検証用のメソッドに対して検証を行うんなら 最初からvalify()ってメソッドを持つインターフェースを用意して UMLとの整合性を検証すればよいのではなくて? | ||||||||||||
|
投稿日時: 2006-11-30 13:30
「バイトコードを読み込んだ上で、バイトコードに手を加えて別のclassファイルとして書き出す」
について、ASMで可能か不可能かを知りたいのでしたら可能です。 ASMはそういうライブラリですから。 #valifyってメソッドはtypoですか?verifyの間違え? | ||||||||||||
|
投稿日時: 2006-11-30 13:55
>かつのりさん
すみません。verify()の間違いです。 お聞きしたかったのは、可能かどうかではなく、始めに書いたプログラムですとクラスローダーを使ってしまっています。 そうではなくて、クラスリーダーをつかったASMで書くとすると、どうなるのかを伺いたいと思いました。 本当に分かりづらくてすみません。 >nagiseさん はい。そうです。verify()というメソッドを持ったクラスが含まれているという意味です。 そして、動的に行わなければならないという仕様です。 | ||||||||||||
|
投稿日時: 2006-11-30 14:05
目的達成のためのアプローチの仕方が間違っている気がしてなりませんが、 仕様と言われればそれまでなのでこの件は追求しないことにします。
それはサンプルコードを代わりに書いてくれという意味だと捉えていいのですか? |