Как JVM начинает искать классы? - PullRequest
10 голосов
/ 20 января 2012
  • Мне было любопытно, что во всех локациях JVM ищет для выполнения программы? Меня больше интересует понимание того, в какой последовательности и где JVM ищет файлы классов, например, он просматривает библиотеки Java, библиотеки расширений, путь к классам в любом каталоге, таком как текущий каталог, из которого вызывается Java? Меня больше интересует поведение JVM, а не то, как класс загрузки загрузчика классов, который, как я знаю, имеет родительский механизм делегирования до root.

  • Если класс выполняется из каталога, где скомпилированный класс хранится в файловой системе, а также в файле JAR в том же каталоге, JVM загрузит оба или только один и какой?

  • Скажем, у вас небезопасный поток Vector, и если мы сравним его производительность с ArrayList, какой из них будет лучше и почему?

Ответы [ 5 ]

7 голосов
/ 20 января 2012

Без использования дополнительного загрузчика классов:

  • Порядок поиска для JVM:
    1. Классы выполнения (в основном, rt.jar in $JRE_HOME/lib `)
    2. Классы расширения (некоторые JAR в $JRE_HOME/lib/ext `)
    3. Classpath, по порядку.Существует четыре варианта указания пути к классам:
      1. Если указан -jar, то этот JAR находится в пути к классам.Независимо от того, какой classpath объявлен как classpath в META-INF/MANIFEST.MF, также учитывается.
      2. Иначе, если было указано -cp, это путь к классу.
      3. Иначе, если установлено $CLASSPATH, тоявляется classpath.
      4. Иначе, текущий каталог, из которого был запущен java, является classpath.
      Таким образом, если я укажу -cp src/A.jar:src/B.jar, то A.jar будет сначала найден, затем B.jar
  • JVM загружает только тот класс, который был найден первым, в соответствии с порядком, в котором каталоги / JAR объявлены в пути к классам.Это важно, если вы используете -cp или $CLASSPATH.
  • В однопоточных сценариях и с недавними JVM, Vector и ArrayList должны иметь аналогичную производительность (ArrayList должна работать немноголучше, если он не synchronized, но в настоящее время блокировка выполняется быстро, когда нет конфликтов, поэтому разница должна быть небольшой).В любом случае, Vector устарел: не используйте его в новом коде.
7 голосов
/ 20 января 2012

Как найти классы.Ответ здесь:

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/findingclasses.html

Ответ для пункта 2: Порядок поиска классов следующий:

  1. классов или пакетов в текущем каталоге.
  2. классы найдены из переменной среды CLASSPATH.[переопределяет 1]
  3. классы, найденные в опции командной строки -classpath.[переопределяет 1,2]
  4. классы, найденные в архивах jar, указанных с помощью параметра командной строки -jar [переопределяет 1,2,3]

Так что если вы используете опцию -jar во время работы, классы взяты из jarfile.

Загружен только один класс.

1 голос
/ 20 января 2012

Меня больше интересует поведение JVM, а не то, как загрузчик классов загружает класс

Извините, но это бессмысленно.Потому что ответ заключается в том, что JVM создает загрузчик классов и позволяет этому загрузчику классов загружать классы.Итак, чтобы понять «поведение JVM», вам нужно понять поведение загрузчика классов.

Но, возможно, ваш вопрос был: как JVM создает загрузчик классов системы?

1 голос
/ 20 января 2012
  1. Я считаю, что Java просматривает текущий каталог, а затем путь к классу в соответствии с аргументом виртуальной машины "-cp".Вы можете поместить любую комбинацию папок классов (например, / project / bin / com / putable), определенных файлов классов (например, /project/bin/com/putable/MyClass.class) и файлов JAR (например, / project / lib /MyJar.jar) на пути к классам.Местоположения разделяются либо двоеточием (ОС на основе Unix), либо точкой с запятой (ОС на базе Windows).Таким образом, все, что находится в classpath, является честной игрой для Java, на которую нужно смотреть при получении определений классов.Что касается последовательности, классы загружаются лениво.Таким образом, они загружаются только тогда, когда это требуется вашему приложению.Если вашему приложению не требуется определенный класс во время его выполнения, тогда этот класс НИКОГДА не будет загружен.

  2. Если вы ничего не поместите в путь к классу, ядумаю, что Java будет загружаться из файла класса, а не из Jar.Если вы укажете один или другой в пути к классам, Java найдет именно это место.Если вы поместите оба в classpath, поведение загрузки классов в Java не определено, и его можно выбрать в зависимости от реализации JVM.

  3. Зависит от того, что вы хотите сделать.Векторы на самом деле всегда безопасны для потоков, в соответствии с Java API, поэтому, если вам не требуется одновременный доступ, ArrayList будет быстрее.Векторы и списки массивов поддерживаются массивами, но они увеличивают емкость с разной скоростью (емкость вектора удваивается всякий раз, когда достигается конец и требуется больше места, но ArrayList увеличивается на 50%).В зависимости от того, как часто вы должны расти или уменьшаться, ответ будет отличаться.Проверьте эту ссылку для получения дополнительной информации:

http://www.javaworld.com/javaworld/javaqa/2001-06/03-qa-0622-vector.html

0 голосов
/ 29 марта 2019

Принятый ответ уже правильный, но в есть более подробная и обновленная официальная спецификация .

Некоторые оговорки как:

Файл класса имеет имя подпути, которое отражает полное имя класса. Например, если класс com.mypackage.MyClass хранится в / myclasses, то / myclasses должен находиться в пути к классу пользователя, а полный путь к файлу класса должен быть /myclasses/com/mypackage/MyClass.class. Если класс хранится в архиве с именем myclasses.jar, то myclasses.jar должен находиться в пути к классу пользователя, а файл класса должен храниться в архиве как com / mypackage / MyClass.class.

И приоритеты в Как Java Launcher находит пользовательские классы

  • Значение по умолчанию, ".", Означающее, что файлы пользовательских классов - это все файлы классов в текущем каталоге (или под ним, если в пакете).
  • Значение переменной среды CLASSPATH, которая переопределяет значение по умолчанию.
  • Значение параметра командной строки -cp или -classpath, которое переопределяет как значение по умолчанию, так и значение CLASSPATH.
  • Архив JAR, указанный в опции -jar, которая переопределяет все остальные значения. Если эта опция используется, все пользовательские классы должны прийти
    из указанного архива.
...