• 締切済み

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

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を使っている個所です。

みんなの回答

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

Linux環境で試してみましたが、実行可能JARファイルを-jarオプションで起動した場合でもsun.misc.Launcher$AppClassLoaderが使われて現象を再現できませんでした。 しかし、どのClassLoaderが使われるかに依存しないコードに変えるべきだろうと思います。-jarオプションで実行するときに使われるClassLoaderについての規定はおそらく仕様にないでしょうし、Sun (Oracle)以外のJava実装がsun.misc.Launcher$AppClassLoaderという名前のクラスを持っているとは限りませんから。 ちなみに、java.net.URLClassLoaderにもgetResource()メソッドはあります。getResource()を使っている部分が問題だと分かっているなら、URLClassLoaderの場合の動作は期待したものとどのように違うのですか?

mnejing
質問者

お礼

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環境があるのでそちらでも試した見たいと思います。 タイムアップで、意向とは異なりますがソース修正も考えないといけないかもです。

関連するQ&A