- ベストアンサー
jarファイル内のJava クラスを列挙する
- 与えられたjarファイルからクラスファイルを見つけ出し、その名前・フィールド・メソッド・パラメータ・タイプを列挙する方法についてご教授ください。
- jarファイル内のJava クラスを列挙するためのデータ処理方法について教えてください。
- IBM Rational Software ArchitectでJava1.4までのサポートを利用して、jarファイル内のJava クラスを列挙する方法を教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
JARファイルからクラスファイル名を取得したら、 クラスローダーでロードして、あとはリフレクションAPIを使えば、大体の情報は得られます。 ただし、この方法では欠点があって、 あるクラスに依存するクラスが、クラスパスに存在しないとClassNotFoundExceptionになります。 (これを解決する方法があるのかも知れないですが分かりません) サンプルでは、メソッド名は手抜きしています。 フィールドと同じようにリフレクションAPIでパラメータや戻り値も取得できるはずです。 関連の情報は得られないと思うので、取得した情報から作り出すしかないと思います。 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()); } //メソッドの列挙 for (Iterator itr = Arrays.asList(cls.getDeclaredMethods()).iterator(); itr.hasNext();){ Method method = (Method)itr.next(); System.out.println("Method: " + method); } } } ※見易さのためにタブを全角スペースに置換しています
その他の回答 (3)
- sasadora
- ベストアンサー率68% (59/86)
パラメータはメソッドのフィールドなので、methodから取得します。 Class[] paramTypes = method.getParameterTypes(); で、パラメータの型の配列が取れます。intなどは、 Integerで取れると思います。 例えば、 func1(String str1, String str2, Integer num) といったメソッドの場合は、 {String.class, String.class, Integer.class}の配列が取得できます。 パラメータ名を取得することはできないっぽいです。 同じように戻り値も、method.getReturnType()で型が受け取れます。
お礼
パラメータは、解決できたと思うのですが、 一日あけてプログラムを開き、実行したところ、 Exception in thread "main" java.lang.NoClassDefFoundError: A (wrong name: source/A) というエラーが出てしまいました。 場所は、Class cls = classLoader.loadClass(className); のところでした。 いろいろ試してみたのですが、そのエラーがなくならず、困ってしまいました。 クラスパスの問題ではないと思います。
- sasadora
- ベストアンサー率68% (59/86)
import 文を書いていなかったので、 違うパッケージのFieldをインポートしてないでしょうか? java.lang.reflect.Fieldになります。 (getTypeが使えないというのも、同じ理由かも) 一応、インポート文も提示しておきます。 import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.Enumeration; import java.util.Iterator; import java.util.jar.JarEntry; import java.util.jar.JarFile;
お礼
あ!という感じです。 一通りのimport文は入っていたのですが、 肝心のjava.lang.reflect.Fieldと java.lang.reflect.Methodがはいっていませんでした。。。 パラメータですが、フィールドやメソッドと同様にやろうと思ったのですが、いまいちどう取得するものか分かりません。 甘えすぎているのはわかっているのですが・・・もしヒントだけでもいただけたら嬉しいです。
- fortranxp
- ベストアンサー率26% (181/684)
回答でなくて意見です。 >クラスファイルを見つけ出し、その名前・フィール >ド・メソッド・パラメータ・タイプを列挙させようと 確かクラスファイルは既にコンパイル済みなので これって機械語をディスアセンブルすることに 限りなく近ずくことではありませんか?
お礼
ありがとうございます。 参考にさせていただいています。 入力jarファイルは、コマンドラインにての入力ということや、field.getType()が、そのままだと使えなかったりした部分があったので、修正してみています。 そこで質問なのですが、フィールドの列挙内の Field field = (Field)itr.next(); で、キャストが違うというエラーがでます。 どうしてなのでしょうか。