• 締切
  • すぐに回答を!

実行環境によってクラスローダーが変わる!?

  • 質問No.7494148
  • 閲覧数550
  • ありがとう数2
  • 気になる数0
  • 回答数1
  • コメント数0

お礼率 100% (5/5)

Linuxのマシンで、eclipseで実行した場合と、実行可能なJARファイルを実行した場合で、使われるクラスローダーが変わってしまい、プログラムが正常に動作しません。

eclipseから実行した場合は、"sun.misc.Launcher$AppClassLoader"が使われ。
Exportした、Runnable JAR fileを、実行した場合は"java.net.URLClassLoader"が使われます。

JARの実行はシェルにて、下記のようにしています。
 export JAVA_HOME=/・・・/jdk1.6.0_30
 $JAVA_HOME/jre/bin/java -jar xxxx.jar
※JAVA_HOME、CLASSPATH設定は無い状態で、シェルを実行しています。
※JAVA_HOMEをコメントアウトしても、状況は変わりませんでした。

eclipseでは、上記シェルのJAVA_HOMEで指定したものと、ビルドパスのライブラリに指定されたものが同じパスのものであることを確認しています。
JARで実行した場合も、"sun.misc.Launcher$AppClassLoader"が使われた欲しいのですが、どうすれば良いでしょうか。

クラスローダーについて、あまり知識がなくお助けいただけないでしょうか。よろしくお願いいたします。

補足
Windows環境では、Eclipse環境でもJAR環境でも"sun.misc.Launcher$AppClassLoader"が使われ正常に動作します。

蛇足
問題個所は、Java Persistence APIのeclipselink、org.eclipse.persistence.internal.jpa.deploymentパッケージのPersistenceUnitProcessor.javaで、クラスローダーのgetResourceを使っている個所です。

回答 (全1件)

  • 回答No.1

ベストアンサー率 69% (495/711)

Linux環境で試してみましたが、実行可能JARファイルを-jarオプションで起動した場合でもsun.misc.Launcher$AppClassLoaderが使われて現象を再現できませんでした。

しかし、どのClassLoaderが使われるかに依存しないコードに変えるべきだろうと思います。-jarオプションで実行するときに使われるClassLoaderについての規定はおそらく仕様にないでしょうし、Sun (Oracle)以外のJava実装がsun.misc.Launcher$AppClassLoaderという名前のクラスを持っているとは限りませんから。

ちなみに、java.net.URLClassLoaderにもgetResource()メソッドはあります。getResource()を使っている部分が問題だと分かっているなら、URLClassLoaderの場合の動作は期待したものとどのように違うのですか?
お礼コメント
mnejing

お礼率 100% (5/5)

salsberryさん
こんにちは、わざわざ再現確認までありがとうございます。

まず、ClassLoaderに依存しないコードに変えるべきということですが、クラスローダーを使っているのは、Eclipse projects(http://www.eclipse.org/eclipselink/)のクラス部分なので、出来れば原因をつきとめてソース修正は回避したいと考えています。

PersistenceUnitProcessorクラスのfindPersistenceArchivesメソッドにて、クラスローダーのgetResourcesが使われていて、実行環境の相対パスから設定ファイルを取得したいみたいなのですが

public static Set<Archive> findPersistenceArchives(ClassLoader loader, String descriptorPath){
Archive archive = null;
Set<Archive> archives = new HashSet<Archive>();

Enumeration<URL> resources = loader.getResources(descriptorPath);
while (resources.hasMoreElements()){

URL descUrl = resources.nextElement();
URL puRootUrl = computePURootURL(descUrl, descriptorPath);


}

sun.misc.Launcher$AppClassLoaderだと、descriptorPathに対して
descriptorPath -> "META-INF/persistence.xml"
  ↓
descUrl -> "//opt/Import/build/classes/META-INF/persistence.xml"
puRootUrl -> "file://opt/Import/build/classes/"
ちゃんとローカルの設定ファイルを見つけれるのですが

java.net.URLClassLoaderだと
descriptorPath -> "META-INF/persistence.xml"
  ↓
descUrl -> "META-INF/persistence.xml"
puRootUrl -> "uri:/"
みたいな感じで、ファイルを見つけることができません。

再現寛容にて、試行錯誤してみましたがやっぱりダメです。来週にもうひとつLinux環境があるのでそちらでも試した見たいと思います。
タイムアップで、意向とは異なりますがソース修正も考えないといけないかもです。
投稿日時:2012/05/26 21:11
結果を報告する
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ