scala classloaders путаница - PullRequest
       4

scala classloaders путаница

9 голосов
/ 06 октября 2011

Пожалуйста, рассмотрите следующую тестовую программу (используя 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)
  }
}

Я компилирую ее и запускаю с "-cp / tmp", содержащим файл "toto", и получаю следующеевывод:

null
file:/tmp/toto
null

=> системный загрузчик классов не содержит classpath

=> Класс Object не имеет загрузчика классов!

Я что-то там упустил или он есть?(большая) ошибка в scala?!

Спасибо, Арджун

Ответы [ 2 ]

11 голосов
/ 06 октября 2011

Второй ноль объясняется java.lang.Class # getClassLoader ()

Возвращает загрузчик класса для класса. Некоторые реализации могут использовать null для представления загрузчика класса начальной загрузки. Этот метод вернет null в таких реализациях, если этот класс был загружен загрузчиком загрузчик классов.

Так вот почему classOf[Object].getClassLoader возвращает ноль, он загружается загрузчиком классов начальной загрузки (он находится в rt.jar, точнее, в jar, который находится в $ JAVA_HOME / lib).

Первый нуль сложнее объяснить. Кажется, что Scala оставляет системный загрузчик классов как есть и добавляет опции -cp к своему собственному загрузчику классов (ScalaClassLoader в scala / util / ClassLoader.scala).

Используя следующее:

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

Таким образом, загрузчик классов System остается нетронутым, но загрузчик классов Scala получает элементы из -cp, добавленные к нему.

Мораль истории: не используйте системный загрузчик классов в Scala, если вы хотите получить доступ к ресурсам из пути к классам.

РЕДАКТИРОВАТЬ: Хорошо, я исследовал это немного больше, и scala.bat выполняет следующую командную строку (под чистой Windows, сокращена для удобства чтения)

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

Таким образом, опция -cp из командной строки передается только как опция MainGenericRunner, не java. Я считаю, что, глядя на код, в Unix вы можете указать опцию -toolcp для scala, чтобы получить что-то, включенное в путь к классам java. Что-то вроде (полностью не проверено):

$ scala -toolcp /temp Test

Эта опция недоступна в scala.bat. Это означает, что если вы работаете под Windows, вам придется получать ресурсы, используя

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

Я не смог найти проблему в Scala Lang Issues , но если это проблема для вас, поднимите проблему и отправьте исправление. Я уверен, что они будут в восторге: -)

РЕДАКТИРОВАТЬ: Я поднял это как проблему SI 5062 -toolcp должен быть доступен на окнах, в scala.bat , и предоставил запрос на получение для него на github .

0 голосов
/ 06 октября 2011

С Статья Википедии о загрузке классов :

Загрузчик системного класса загружает код, найденный в java.class.path, который сопоставляется с системной переменной CLASSPATH.

Не уверен насчет второго нуля. Может быть, кто-то еще может это прояснить.

...