- PR -

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

投稿者投稿内容
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-12-12 11:23
引用:

ヒラさんの書き込み (2006-12-12 05:03) より:
下記のようにプログラムを大幅に変更してみました。
が、これだとエラーが出ます。



この状態で自前のクラスローダでごにょごにょするような
プログラムを作るのは自制した方がいいのでは・・・。

JARもURLClassLoaderを使えば自分で読み込む必要はないです。

ClassLoaderのソースを読めばわかることですが、loadClass()系を
オーバーライドする主な目的は親ローダとの委譲関係の上書きです。
単にバイトコードの改変が目的ならば、findClass()をオーバーライド
する方が無難だと思います。

#現状のコードだとクラスローダの親子関係を考慮していないので、
#このクラスローダからはjava.langパッケージすら解決に失敗します。

ついでに、この構造だとクラスの遅延ロードができないので遅いですよ。
意図的にJAR中の全てのクラスを事前にロードしたいのなら別ですけど。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-12 12:03
私も、クラスローダは自作しないほうがよいと思います。(セキュリティの穴になりそうな気が。)

ただ、プログラムの問題で一応わかることを返信しておきます。

defineClassの前に
System.out.println("name=" + name);
を入れるとa/Testになっていたので、
String className = name.replace("\\", ".").replaceAll("\\.class", "");
は間違いで
String className = name.replace("/", ".").replaceAll("\\.class", "");
でしたね。

 単純にjarファイルをそのまま
return defineClass(name, bytes, 0, bytes.length);
すると

Exception in thread "main" java.lang.SecurityException: Prohibited package name:
java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:479)
となるので、この後を知りたいなら、ClassLoaderをよく知っている人に聞いたほうがよいでしょう。(私は、ClassLoaderを作ったことはない)


ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-12 13:17
>あしゅさん、だっちょさん

URLClassLoaderを使いたいのはやまやまですが、そうなるとjarファイルからクラスを読み込むだけになりますよね?
コードからお気づきかと思いますが、この読み込み処理は全体の一部で、読み込んできたバイトコードに他のバイトコードを付け加えて(NotifierClassVisitor)ファイル出力させようと思っているのです。
それだと、URLClassLoaderでは処理できないのではないかと思うのですが・・・。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-12-12 13:20
クラスローダを自作するのは意外と手間になります。
・パッケージの解決
・クラスの解決
・リソースの解決
等を、クラスローダの親子関係を考慮して設計しなければいけないのですが、
多分コンパイルエラーの解決が難しいレベルでは、作れるものではありません。

バイトコード操作といっても、メソッド操作の前後にほにゃらら・・・なら
AOPエンジンなどもありますし、もうちょっと勉強されてからの方がいいと思います。
ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-12 13:25
>かつのりさん

もちろん、もっと勉強してからすべきなのは分かっておりますし、
javaに関して自分の知識が足りなさ過ぎるのも重々承知しております。
しかし、どうしても完成させなければならず、またASMを利用しなければならないという制約の元作っておりますので、こうして質問をするに至ったわけです。
ご理解いただけるとありがたいです。

[ メッセージ編集済み 編集者: ヒラ 編集日時 2006-12-12 13:27 ]
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-12-12 13:38
引用:

ヒラさんの書き込み (2006-12-12 13:17) より:
>あしゅさん、だっちょさん
コードからお気づきかと思いますが、この読み込み処理は全体の一部で、読み込んできたバイトコードに他のバイトコードを付け加えて(NotifierClassVisitor)ファイル出力させようと思っているのです。



もちろん承知の上です。

URLClassLoader#findClass(String)はfinalではないので、
クラスファイルはfindResource(String)経由でJARから取得して
改変したバイトコードをdefineClass()する作りに上書きできます。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-12-12 13:45
クラスローダについては、この場で詳しく説明するのが難しいので
以下のリンク先を読んで勉強してみてください。

http://discypus.jp/wiki/?Java%2F%A5%AF%A5%E9%A5%B9%A5%ED%A1%BC%A5%C0%A1%BC
からの引用ですが、

クラス・ローディング問題の神秘を解く 第1回: クラス・ローディングとデバッグ・ツール 2005年9月29日 (2006-01-29)
http://www-06.ibm.com/jp/developerworks/java/060113/j_j-dclp1.shtml

クラス・ローディング問題の神秘を解く 第2回: クラス・ローディングに関する基本的な例外 2005年12月6日 (2006-01-29)
http://www-06.ibm.com/jp/developerworks/java/060127/j_j-dclp2.shtml

Javaプログラミングのダイナミックス 第1回: クラスとクラスのロード処理 2003年4月29日
http://www-06.ibm.com/jp/developerworks/java/030704/j_j-dyn0429.html

Javaプログラミングのダイナミックス 第4回: Javassistでのクラス変換 2003年9月16日
http://www-06.ibm.com/jp/developerworks/java/040206/j_j-dyn0916.html

Javaプログラミングのダイナミックス 第5回: オンザフライでクラスを変換する 2004年2月3日
http://www-06.ibm.com/jp/developerworks/java/040326/j_j-dyn0203.html

を、じっくり読んでみるといいと思います。

全て読んだ上で分からないところがあれば、また質問してみてください。
ただし、クラスのローディングとコンパイルエラーは別問題なので、
コンパイルエラーくらいは最低限解決出来るようにはしてくださいね。
ヒラ
常連さん
会議室デビュー日: 2006/11/30
投稿数: 20
投稿日時: 2006-12-12 15:07
URLClassLoaderを使って書き換えてみようと思います。

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