本文介绍了斯卡拉类加载器混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

请考虑以下测试程序(使用scala 2.9.0.1)

 对象测试
{
def main(args:Array [String])= {
println(ClassLoader.getSystemClassLoader.getResource( toto))
println(this.getClass.getClassLoader.getResource( toto))
println(classOf [Object] .getClassLoader)
}
}

我编译并使用包含文件 toto的 -cp / tmp运行它,得到以下输出:

 
文件:/ tmp / toto

=>系统类加载器不包含类路径



=> Object类没有类加载器!



我错过了一些东西吗?

谢谢,
Arjun

解决方案

第二个null由

因此,这就是为什么 classOf [Object] .getClassLoader 返回null的原因,它是由引导类加载器加载的(它位于rt.jar中,更具体地说,它位于jar中在$ JAVA_HOME / lib中。)



第一个null较难解释。似乎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测试

我们得到以下输出:

  sun.misc.Launcher$AppClassLoader@11b86e7 
URLClassLoader(
文件:/ C:/developpement/utils/jdk1.6.0_22/ jre / lib / resources.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/rt.jar
文件:/ C:/developpement/utils/jdk1.6.0 _22 / jre / lib / jsse.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/jce.jar
文件:/ C:/ developpement / utils /jdk1.6.0_22/jre/lib/charsets.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/dnsns.jar
文件:/ C: /developpement/utils/jdk1.6.0_22/jre/lib/ext/localedata.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunjce_provider.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/sunmscapi.jar
文件:/ C:/developpement/utils/jdk1.6.0_22/jre/lib/ext/ sunpkcs11.jar
文件:/ C:/DEVELO~1/scala/SCALA-~1.1/bin /../ lib / jline.jar
文件:/ C:/ DEVELO〜1 / scala / SCALA-〜1.1 / bin /../ lib / scala-compiler.jar
文件:/ C:/DEVELO~1/scala/SCALA-~1.1/bin /../ lib / scala-dbc.jar
文件:/ C:/DEVELO~1/scala/SCALA-~1.1/bin /../ lib / scala-library.jar
文件:/ C:/ DEVELO〜1 / scala / SCALA -〜1.1 / bin /../ lib / scala-swing.jar
文件:/ C:/DEVELO~1/scala/SCALA-~1.1/bin /../ lib / scalap.jar
文件:/ C:/ temp /


null

因此系统类加载器保持不变,但是Scala类加载器从-cp中获得了添加到其中的项目。 / p>

故事的寓意:如果要从类路径访问资源,请不要在Scala中使用系统类加载器。



编辑:好的,我对此进行了更多研究,并且scala.bat正在执行以下命令行(在纯Windows下,已缩短可读性)

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

因此,命令行中的-cp选项仅作为选项传递给MainGenericRunner,而不是 java。我相信,通过查看代码,您可以在unix下为scala指定-toolcp选项,以获取Java类路径中包含的内容。诸如此类(完全未经测试):

  $ scala -toolcp / temp测试

此选项在scala.bat中不可用。这意味着,如果您在Windows下工作,则必须使用

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

我在,但是如果您遇到问题,请提出问题并提交修复程序。我敢肯定他们会很高兴的:-)



编辑:我已将此问题发布为中可用,并在。


Please consider the following test program (using scala 2.9.0.1)

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

I compile it and run it with "-cp /tmp" containing a file "toto", and I get the following output:

null
file:/tmp/toto
null

=> the system classloader does not contain the classpath

=> the Object class has no classloader!

Am I missing something there or is it a (big) bug in scala?!

Thanks,Arjun

解决方案

The second null is explained by java.lang.Class#getClassLoader()

So, this is why classOf[Object].getClassLoader returns null, it's loaded by the bootstrap classloader (it is in rt.jar, more specifically, it is in a jar which is in $JAVA_HOME/lib).

The first null is harder to explain. It seems that Scala leaves the system classloader as-is, and only adds the options -cp to it's own classloader (ScalaClassLoader in scala/util/ClassLoader.scala).

Using the following:

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

and running it with:

$ scala -cp /temp Test

we get the following output:

sun.misc.Launcher$AppClassLoader@11b86e7
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

So the System classloader is left untouched, but the Scala classloader gets the items from -cp added to it.

Moral of the story: don't use the system classloader in Scala if you want to access resources from the classpath.

EDIT: Ok, I've investigated this a bit more, and scala.bat is executing the following command line (under pure Windows, shortened for readability)

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

So the -cp option from the command line is only being passed as an option to MainGenericRunner, not the java. I believe, from looking at the code, that under unix you can specify the -toolcp option to scala to get something included in the java classpath. Something like (totally untested):

$ scala -toolcp /temp Test

This option isn't available in scala.bat. Which means if you're working under windows, you'll have to get the resources using

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

I couldn't find an issue in the Scala Lang Issues, but if it's a problem for you, raise an issue and submit a fix. I'm sure they'll be thrilled :-)

EDIT: I have raised this as issue SI 5062 -toolcp should be available on windows, in the scala.bat, and provided a pull request for it on github.

这篇关于斯卡拉类加载器混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 23:01