问题描述
请考虑以下测试程序(使用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.
这篇关于斯卡拉类加载器混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!