scala 类加载器混乱

2023-11-22

请考虑以下测试程序(使用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)
  }
}

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

null
file:/tmp/toto
null

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

=> Object 类没有类加载器!

我是否遗漏了一些东西,或者它是 scala 中的一个(大)错误?!

谢谢, 阿琼


第二个空值的解释为java.lang.Class#getClassLoader()

返回该类的类加载器。一些实现可能会使用 null 代表引导类加载器。这个方法会返回 如果此类是由引导程序加载的,则在此类实现中为 null 类加载器。

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

第一个空值更难解释。看来 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)
  }
}

并运行它:

$ scala -cp /temp Test

我们得到以下输出:

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

因此,系统类加载器保持不变,但 Scala 类加载器从 -cp 中获取添加到其中的项目。

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

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

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

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

$ scala -toolcp /temp Test

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

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

我在中找不到问题Scala 语言问题,但如果这对您来说是个问题,请提出问题并提交修复。我相信他们会很兴奋:-)

编辑:我已将此作为问题提出SI 5062 -toolcp 应该在 Windows 上可用,位于 scala.bat 中,并在上提供了一个拉取请求github.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala 类加载器混乱 的相关文章

随机推荐