- PR -

Jar ファイルからのクラス読み込み処理

投稿者投稿内容
ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-13 12:30
baseに変更してみました。
→エラーが増えました。
java.lang.ClassNotFoundException: A
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at asm.Adapt.findClass(Adapt.java:60)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at asm.Adapt.main(Adapt.java:142)

親クラスローダで解決できることがわかったので、クラスパスをはずしました。
しかし、以前エラーが変わりありません。

ちなみに、クラスのロードはきちんとできています。

今思ったのですが、findClassの中の、
コード:
if(is == null){
			System.out.println("Unable to load class " + name + " for annotation checking");
			return super.findClass(name);
}else{...


の部分の、return super.findClass(name);
superもおかしいですか?
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-12-13 12:45
やっぱりクラスローダの自作はやめた方が無難だと思いますよ。

現状出ている問題を自力で解決できるレベルであっても、
後々さらに厄介な問題が頻繁に出てくるものです。

その辺りを覚悟して地獄にはまるつもりなら止めませんが・・・。
ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-13 12:49
前のあしゅさんの助言どおり、
自分としては、findClass()をオーバーライドしたつもりだったのですが、
これだと違うのでしょうか。

これ以外の方法でやるとなると、逆にどうしてよいものか分からないのです。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-12-13 12:55
引用:

ヒラさんの書き込み (2006-12-13 12:49) より:
前のあしゅさんの助言どおり、
自分としては、findClass()をオーバーライドしたつもりだったのですが、
これだと違うのでしょうか。



クラスローダの実装方法としてはこれで合っています。
が、それ以外にも問題がいろいろと出てくるので助言しているのです。

参考資料が欲しいのであれば、
Tomcatのbootstrap.jarに含まれるクラスのソースを読んでみましょう。
ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-13 13:17
クラスローダの自作をしないで実行する方法というのは、
きっと今のこのプログラムよりもシンプルなのでしょうが、
どうやっていいのかが分からず結果としてここから動けなくなってしまっています。
これが出来上がらないと次の段階に進めないため、とても困っています。

だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-13 13:20
とりあえずソースのfindClassの
try{
ClassReader cr = new ClassReader(bytes);
...
System.out.println();
}catch(Exception e){
}
の部分はコメントにして動かしてみました。
 
1) main関数の

String[] pargs = new String[args.length-1];
System.arraycopy(args, 1, pargs, 0, pargs.length);
Thread.currentThread().setContextClassLoader(loader);
main.invoke(null, new Object[]{pargs});

は意図はわかりますが、間違ってますね。

Object[] pargs = new Object[args.length-1];
for (int i=1;i<pargs.length;i++) {
pargs[i-1] = args[i];
}
Thread.currentThread().setContextClassLoader(loader);
main.invoke(null, pargs);

2) 単純なクラスで試したところ指定したjarのクラスのmain関数を実行できました。
 もし、ここをコメントにして実行できない場合は、指定したjarファイルが依存するjarファイルをclasspathに追加して実行する必要があります。
 もし、それで実行できる場合は

ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(false);
NotifierClassVisitor ncv = new NotifierClassVisitor(cw);
cr.accept(ncv, false);
bytes = cw.toByteArray();

で作成しているbyte配列が正しくないか、そのクラスデータが必要とするclassへのclassspathが設定されていないと思います。





かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-12-13 13:29
結局のところ、最終的に欲しい出力物ってなんでしょうか?
そのためにクラスローダの自作とバイトコード操作が必須なんでしょうか?

手段だけ提示されると、根本的に間違っているのかも回答者側ではわからないわけで、
目的とか経緯が存在すると、もっといい手段が出てくるかもしれないです。

ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-13 13:41
最終的には、UMLクラス図とバイトコードが一致しているかどうかを確認するプログラムを作ろうと思っています。
今行っているのは、はじめの段階で、バイトコードをよみ、何らかの処理がなされたらnotifyを呼ぶ。そこで出来上がった新しいバイトコードのオブジェクト図とクラス図を比較して一致しているかどうかを確認するという流れの一部です。

スキルアップ/キャリアアップ(JOB@IT)