• 締切済み

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

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

  • Java
  • 回答数1
  • ありがとう数2

みんなの回答

  • 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

  • Macで実行可能jarが実行できない

    EclipseでJavaの開発をしているのですが、Windowsで実行可能jarでエクスポートするとダブルクリックで実行できるソースコードが同じコードで、Macでエクスポートすると実行出来ません。 ダブルクリックすると、 Java JARファイル"hoge.jar"を起動できませんでした。 というメッセージが出ます。コンソールから java hoge.jar と実行すると、 Exception in thread "main" java.lang.NoClassDefFoundError: Hoge/jar Caused by: java.lang.ClassNotFoundException: hoge.jar at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) と出ます。 Macは使い始めで余計によくわかりません。よろしくお願いします。

    • ベストアンサー
    • Java
  • JAVA twitter4j エラー

    JAVA twitter4j エラー JAVA初心者です。 http://d.hatena.ne.jp/regeek/20100511/1273599348 で公開されているソースなのですが、コンパイルはとおるのですが、 実行する時に以下のようなエラーをはき、困っています。 ############################## 上のサイトからソースをコピペする(現在のディレクトリをnowとします) /now/Application.java /now/LoginDialog.java /now/TimeLine.java twitter4j-2.1.2.jarを /now/twitter/twitter4j-2.1.2.jarに置く $javac -classpath twitter/twitter4j.jar *.java $java Application ###←ここで以下のようなエラーがでます Exception in thread "main" java.lang.NoClassDefFoundError: twitter4j/TwitterException Caused by: java.lang.ClassNotFoundException: twitter4j.TwitterException at java.net.URLClassLoader$1.run(URLClassLoader.java:217) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:266) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:334) 環境は $java -versionで以下の通り java version "1.6.0_18" OpenJDK Runtime Environment (IcedTea6 1.8) (6b18-1.8-0ubuntu1) OpenJDK Server VM (build 14.0-b16, mixed mode) $javac -versionで以下の通り javac 1.6.0_18 です。 個人的には sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) とあるので、これはもしやUbuntuのOpenJDK Runtimeではだめなのか? と考えているのですが・・・ どなたか解決方法をご教授頂けないでしょうか。よろしくお願いします。

    • ベストアンサー
    • Java
  • LinuxでJava環境

    LinuxでJavaを使った開発をしたいのですが、環境設定でつまずいてしまい 、困っております。 環境 OS:windowsとUbuntuのデュアルブートです。 状況 javaを、 sudo update-alternatives --config java でインストールしましたが、コンパイルができません。 ファイルはデスクトップに置き、java ****.javaで実行しましたが、 Exception in thread "main" java.lang.NoClassDefFoundError: test/java/java Caused by: java.lang.ClassNotFoundException: test.java.java at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) のエラーが出てしまいます. また、eclipseをインストールして、画面を開こうとしても、すぐに消えてしまいます. Linuxの挙動がまったくわかりません。 もしかすると、rootでアレコレコマンドを試したから,再起不能の状態になっているのではないかと危惧しております。 Linuxの知識はゼロの初心者です。 そうかお助けをお願い致します。

  • javaでscalaのクラスを使う

     Scala初心者です^^  Scalaで作ったクラスをJavaで使おうとしています.  しかしなかなかうまくいかなくて…  ソースを下に書いておきます. [ap/hello.scala] class hello(str2: String){ val str = str2 def say(){ println(str) } } [ap/start.java] public class start{ public static void main(String[] args){ hello h = new hello("Hello!"); h.say(); } }  helloクラスのコンストラクタを用いて指定した文字列を helloクラスのsayメソッドで標準出力するだけの簡単なクラスなのですが, うまく実行できず… Exception in thread "main" java.lang.NoClassDefFoundError: ap/start/class Caused by: java.lang.ClassNotFoundException: ap.start.class at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) Kazus-MackBookPro:ScalaLearning macuser$ java ap/start Exception in thread "main" java.lang.NoClassDefFoundError: ap/start (wrong name: start) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) というエラーが出てしまいます.    どこが悪いかわかる方いらっしゃいませんか?  それとも,JavaではScalaで作った.classファイルは使うことができないのでしょうか?  Scalaはまだ覚えて2週間なので,まだ完全に理解できていません><    よろしくお願いします

  • 実行可能jarを実行できない

    PCを替えたら実行可能jarの実行に"javar -jar"が必要になりました。 ubuntu10.04(oracle java 1.6)のeclipseで作り、別のubuntu10.04(oracle java 1.6)なPCで使っていた実行可能COMMAND.jarがubuntu12.04(oracle java 1.7)で実行すると "バイナリファイルを実行できません" となります。 COMMAND.jarへのパスは通っています。 $ java -jar COMMAND.jar なら実行できます。 どうすればjavaコマンド無しに実行できますでしょうか。 2013年6月2日

    • ベストアンサー
    • Java
  • データベースに接続できません

    データベースに接続できません java初心者です eclipseで開発を行っているのですが、どうもエラーがでてきて接続できません よろしくおねがいします エラー内容 Exception in thread "main" java.lang.NoClassDefFoundError: DataBase Caused by: java.lang.ClassNotFoundException: DataBase at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:315) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330) at java.lang.ClassLoader.loadClass(ClassLoader.java:250) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)

  • NoClassDefFoundErrorの解決方法

    netbeansでjava.lang.NoClassDefFoundErrorの解決方法を教えて下さい。 NetBeans IDE 7.0を使ってJAVAで、「Hell World !」を表示するものを 作りました。 ソースコード public class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!"); } } NetBeansで、 「実行]-「ファイルを実行」とすると、「Hello World!」と表示されます。 正しく動きます。 しかし、 「実行」-「プロジェクトを実行」とすると、以下のエラーメッセージがでます。 java.lang.NoClassDefFoundError: helloworld/HelloWorld Caused by: java.lang.ClassNotFoundException: helloworld.HelloWorld at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) Could not find the main class: helloworld.HelloWorld. Program will exit. Exception in thread "main" Java Result: 1 また、コマンドラインから以下の様に実行しても、実行してもエラーとなります。 C:\Program Files\Java\jdk1.6.0_25\bin>java.exe -jar C:\java\HelloWorld\dist\HelloWorld.jar Exception in thread "main" java.lang.NoClassDefFoundError: helloworld/HelloWord Caused by: java.lang.ClassNotFoundException: helloworld.HelloWorld at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) Could not find the main class: helloworld.HelloWorld. Program will exit. そこで、 ソースコードに、「package helloworld;」の記述を行いと期待した結果となりました。 NetBeansで、「実行」-「プロジェクトを実行」 コマンドラインから実行 しても、「Hello World!」と表示されます。 ソースコード package helloworld; public class HelloWorld { public static void main(String args[]) { System.out.println("Hello World!"); } } 何故、 「package helloworld;」の記述の追加で動いたのでしょうか。 あるとないとで、どう違うのでしょうか。 「package helloworld;」は、何を意味しているのでしょうか。 環境は、 JDK1.6(jdk1.6.0_25) クラスパスは未設定。

  • jdbcを利用したpostgres接続

    Solaris9/02 + PostgreSQL7.2.3 で構築しました。 java -version 1.4.0_01 です。 PostgreSQL の Configure時に --with-javaオプションを付け、 /usr/local/pgsql/share/java 配下にpostgres.jarが出来ました。 /home/ssm3u の .cshrcに setenv JAVA_HOME /usr/j2se setenv CLASSPATH /usr/local/pgsql/share/java/postgres.jar:. (postgres.jarファイルとカレント) を追加し、 % vi FirstDBAccess.java import java.sql.*; public class FirstDBAccess {  public static void main(String argv[]) {   try {    Class.forName("org.postgresql.Driver");   } catch (Exception e) {    e.printStackTrace();   }  } } % javac FirstDBAccess.java % java FirstDBAccess と実行すると、 java.lang.ClassNotFoundException: org.postgresql.Driver at java.net.URLClassLoader$1.run(URLClassLoader.java:198) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:186) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265) at java.lang.ClassLoader.loadClass(ClassLoader.java:262) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:322) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:130) at FirstDBAccess.main(FirstDBAccess.java:5) となります。 上記エラーになるのは CLASSPATH設定がおかしい時と思うのですが、 何がおかしいのかわかりません。 Oracleとか他のDBの時はあっさりできたのに・・・ 他に設定が必要なのでしょうか? 見直せば良い点などお教えいただければ助かります。

  • jarファイル内のクラスをインスタンス化する

    http://homepage3.nifty.com/satoshis/java/memo.html#extension 上記のサイトを参考に、jarファイル内のクラスをインスタンス化しようとしているのですが、 clazz.newInstance(); を実行しようとすると、以下のようなエラーが発生します。 java.lang.IllegalAccessException: Class jp.co.AAAAA.BBBBB can not access a member of class CCCCC with modifiers "" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:57) at java.lang.Class.newInstance0(Class.java:302) at java.lang.Class.newInstance(Class.java:261) at jp.co.loft.LogCut.main(LogCut.java:58) ※jp.co.AAAAA.BBBBB は実行クラス、CCCCCはjarファイル内のクラスです。 開発環境は、以下です。 eclipse2.1.1 + jdk1.5.0_02 どんな些細なことでもよいので、ご存知の方、ご教授願えないでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • java.lang.NoClassDefFoundErrorというエラーが出ます その2

    ご質問させて頂きます。 java.lang.NoClassDefFoundErrorというエラーが出ます http://oshiete1.goo.ne.jp/kotaeru.php3?q=952983 の続きの質問なんですが・・・。 次のような実行時エラーが出ます。 java.lang.ClassNotFoundException: org.postgresql.Driver at java.net.URLClassLoader$1.run(URLClassLoader.java:198) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:186) at java.lang.ClassLoader.loadClass(ClassLoader.java:299) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265) at java.lang.ClassLoader.loadClass(ClassLoader.java:255) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:140) at sample1.main(sample1.java:8) そこで、 >PostgreSQLのODBCドライバをCLASSPATHに含めていますか? >postgresql.jarとかpg72jdbc2.jarといったファイルがどこかにあるはずです. と、回答者の方からアドバイスをして頂きました。 ところが、postgresql.jarとかpg72jdbc2.jarもありませんでした。 ネットで検索をしたところ、「postgresql743.jar」というのがありましたので /usr/javaに格納しました。 /etc/profileに、 export PATH=$PATH:/usr/java export CLASSPATH=$CLASSPATH:/usr/java. と追加しました。 しかし、同じエラーが出てします。 対処方法をご存じでしたら、ご教授して頂けたら幸いです。

    • ベストアンサー
    • Java

専門家に質問してみよう