请考虑以下测试程序(使用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)
}
}
Run Code Online (Sandbox Code Playgroud)
我编译它并使用包含文件"toto"的"-cp/tmp"运行它,我得到以下输出:
null
file:/tmp/toto
null
Run Code Online (Sandbox Code Playgroud)
=>系统类加载器不包含类路径
=> Object类没有类加载器!
我在那里遗漏了什么,或者它是scala中的(大)错误?!
谢谢,阿琼
Mat*_*ell 11
第二个null由java.lang.Class#getClassLoader()解释
返回类的类加载器.某些实现可能使用null来表示引导类加载器.如果此类由引导类加载器加载,则此方法将在此类实现中返回null.
所以,这就是为什么classOf[Object].getClassLoader返回null,它由bootstrap类加载器加载(它在rt.jar中,更具体地说,它位于$ JAVA_HOME/lib中的jar中).
第一个null更难解释.似乎Scala按原样离开了系统类加载器,并且只将选项-cp添加到它自己的类加载器(scala/util/ClassLoader.scala中的ScalaClassLoader).
使用以下内容:
object Test {
def main(args:Array[String]) = {
println(ClassLoader.getSystemClassLoader)
println(this.getClass.getClassLoader)
println(classOf[Object].getClassLoader)
}
}
Run Code Online (Sandbox Code Playgroud)
并运行它:
$ scala -cp /temp Test
Run Code Online (Sandbox Code Playgroud)
我们得到以下输出:
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
Run Code Online (Sandbox Code Playgroud)
因此系统类加载器保持不变,但Scala类加载器从-cp添加项目.
故事的道德:如果要从类路径访问资源,请不要在Scala中使用系统类加载器.
编辑:好的,我已经调查了这一点,scala.bat正在执行以下命令行(在纯Windows下,为了便于阅读而缩短)
java.exe -Xmx256M -Xms32M -Dscala.home="xxx" -cp "libsfromscalahome" scala.tools.nsc.MainGenericRunner -cp /temp Test
Run Code Online (Sandbox Code Playgroud)
因此命令行中的-cp选项仅作为MainGenericRunner的选项传递,而不是 java.我相信,通过查看代码,在unix下,您可以为scala指定-toolcp选项以获取java类路径中包含的内容.像(完全未经测试)的东西:
$ scala -toolcp /temp Test
Run Code Online (Sandbox Code Playgroud)
scala.bat中没有此选项.这意味着如果你在Windows下工作,你将不得不使用资源
println(this.getClass.getClassLoader.getResource("toto"))
Run Code Online (Sandbox Code Playgroud)
我在Scala Lang问题中找不到问题,但如果这对您来说是个问题,请提出问题并提交修复.我相信他们会很激动:-)
编辑:我已经提出这个问题,因为问题SI 5062 -toolcp应该在windows上,scala.bat中可用,并在github上为它提供了拉取请求.