• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:jarファイル内のJava クラスを列挙する)

jarファイル内のJava クラスを列挙する

このQ&Aのポイント
  • 与えられたjarファイルからクラスファイルを見つけ出し、その名前・フィールド・メソッド・パラメータ・タイプを列挙する方法についてご教授ください。
  • jarファイル内のJava クラスを列挙するためのデータ処理方法について教えてください。
  • IBM Rational Software ArchitectでJava1.4までのサポートを利用して、jarファイル内のJava クラスを列挙する方法を教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • sasadora
  • ベストアンサー率68% (59/86)
回答No.2

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);   }  } } ※見易さのためにタブを全角スペースに置換しています

pooh_bear
質問者

お礼

ありがとうございます。 参考にさせていただいています。 入力jarファイルは、コマンドラインにての入力ということや、field.getType()が、そのままだと使えなかったりした部分があったので、修正してみています。 そこで質問なのですが、フィールドの列挙内の Field field = (Field)itr.next(); で、キャストが違うというエラーがでます。 どうしてなのでしょうか。

その他の回答 (3)

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.4

パラメータはメソッドのフィールドなので、methodから取得します。 Class[] paramTypes = method.getParameterTypes(); で、パラメータの型の配列が取れます。intなどは、 Integerで取れると思います。 例えば、 func1(String str1, String str2, Integer num) といったメソッドの場合は、 {String.class, String.class, Integer.class}の配列が取得できます。 パラメータ名を取得することはできないっぽいです。 同じように戻り値も、method.getReturnType()で型が受け取れます。

pooh_bear
質問者

お礼

パラメータは、解決できたと思うのですが、 一日あけてプログラムを開き、実行したところ、 Exception in thread "main" java.lang.NoClassDefFoundError: A (wrong name: source/A) というエラーが出てしまいました。 場所は、Class cls = classLoader.loadClass(className); のところでした。 いろいろ試してみたのですが、そのエラーがなくならず、困ってしまいました。 クラスパスの問題ではないと思います。

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.3

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;

pooh_bear
質問者

お礼

あ!という感じです。 一通りのimport文は入っていたのですが、 肝心のjava.lang.reflect.Fieldと java.lang.reflect.Methodがはいっていませんでした。。。 パラメータですが、フィールドやメソッドと同様にやろうと思ったのですが、いまいちどう取得するものか分かりません。 甘えすぎているのはわかっているのですが・・・もしヒントだけでもいただけたら嬉しいです。

  • fortranxp
  • ベストアンサー率26% (181/684)
回答No.1

回答でなくて意見です。 >クラスファイルを見つけ出し、その名前・フィール >ド・メソッド・パラメータ・タイプを列挙させようと 確かクラスファイルは既にコンパイル済みなので これって機械語をディスアセンブルすることに 限りなく近ずくことではありませんか?

関連するQ&A