2011-10-06 9 views
9

私はそれをコンパイルし、「-cpを/ tmp」ファイル「TOTO」を含むとそれを実行しScalaのクラスローダが混乱

object test 
{ 
    def main(args:Array[String]) = { 
    println(ClassLoader.getSystemClassLoader.getResource("toto")) 
    println(this.getClass.getClassLoader.getResource("toto")) 
    println(classOf[Object].getClassLoader) 
    } 
} 

(Scalaの2.9.0.1を使用して)、次のテストプログラムを検討してください、と私は取得します次の出力:

null 
file:/tmp/toto 
null 

=>システムクラスローダは、クラスパスが含まれていない

=> Objectクラスは何のクラスローダを持っていません!

私はそこに何かがないか、それともスケーラの(大きな)バグですか?

おかげで、 アルジュン

答えて

11

二ヌルがクラスのクラスローダを返します

java.lang.Class#getClassLoader()

によって説明されます。実装によっては、ブートストラップクラスローダーを表すのに nullを使用することがあります。このメソッドは、このクラスがブートストラップ クラスローダによってロードされた場合、そのような実装では nullを返します。だから、

、なぜclassOf[Object].getClassLoader戻っヌルこれは、それが(それがrt.jar内で、より具体的には、$ JAVA_HOME/libにあるjarファイルである)、ブートストラップクラスローダによってロードされています。

最初のヌルは説明するのが難しいです。 Scalaはシステムクラスローダをそのまま残し、独自のクラスローダ(scala/util/ClassLoader.scalaのScalaClassLoader)にオプション-cpを追加するだけです。

object Test { 
    def main(args:Array[String]) = { 
    println(ClassLoader.getSystemClassLoader) 
    println(this.getClass.getClassLoader) 
    println(classOf[Object].getClassLoader) 
    } 
} 

し、それを実行して:

$ scala -cp /temp Test 

我々は次のような出力が得られます。次を使用して

[email protected] 
URLClassLoader(
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/resources.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/rt.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/jsse.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/jce.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/charsets.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/dnsns.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/localedata.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunjce_provider.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunmscapi.jar 
    file:/C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunpkcs11.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/jline.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-compiler.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-dbc.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-library.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scala-swing.jar 
    file:/C:/DEVELO~1/scala/SCALA-~1.1/bin/../lib/scalap.jar 
    file:/C:/temp/ 
) 

null 

ので、システムクラスローダが放置されていますが、 Scalaクラスローダは、-cpから追加された項目を取得します。

ストーリーのモラル:クラスパスからリソースにアクセスするには、Scalaのシステムクラスローダーを使用しないでください。

編集:私はこれをもう少し調べて、スカラーです。バットは、ない javaの(読みやすくするために短縮され、純粋なWindows環境下で、)次のコマンドラインだから、コマンドラインから-cpオプションはMainGenericRunnerにオプションとして渡されている

java.exe -Xmx256M -Xms32M -Dscala.home="xxx" -cp "libsfromscalahome" scala.tools.nsc.MainGenericRunner -cp /temp Test 

を実行しています。私はコードを見て、unixでは-toolcpオプションをスカラーに指定してjavaクラスパスに含まれるものを得ることができると信じています。何かのように(完全にテストされていない):

$ scala -toolcp /temp Test 

このオプションはscala.batでは使用できません。あなたは窓の下で作業している場合、あなたは

println(this.getClass.getClassLoader.getResource("toto")) 

を使用してリソースを取得する必要がありますを意味している私はScala Lang Issuesで問題を見つけ、それはあなたのための問題だ場合は、問題を提起し、提出することができませんでした修正。

EDIT:これは問題SI 5062 -toolcp should be available on windows, in the scala.batとして提起し、githubにプルリクエストを提供しました。

0

Wikipedia's classloader articleから:

システムクラスローダは、システムCLASSPATH変数にのjava.class.pathで見つけたコード、 マップをロードします。

2番目のnullについてはわかりませんが、たぶん誰かがそれをクリアすることができます。