Гарантирован ли загрузчик классов Java не загружать неиспользуемые классы? - PullRequest
12 голосов
/ 15 августа 2010

Есть ли гарантия, что загрузчик классов Java (по умолчанию, системный) не не пытается загрузить классы, на которые нет ссылок в выполняемом коде? Несколько примеров того, что я имею в виду:

  • Я использую framework.jar, который, как мне известно, содержит в себе ссылки на другие классы library.jar, но я использую только ту часть платформы, которая не содержит этих ссылок. Безопасно ли оставлять library.jar вне дома?
  • Статические блоки запускаются при первой загрузке класса. Если ни один запущенный код не содержит ссылок на определенный класс, уверен ли он, что его статический блок не запущен?

Быстрое тестирование, кажется, работает как предполагалось выше, и в любом случае не имеет смысла загружать неиспользуемые классы, но есть ли гарантия на это?

Дополнение: Кажется, что мои "статические блоки запускаются при первой загрузке класса", приведенная выше инструкция несколько неверна. Определенно возможно загрузить классы (одна вещь) без запуска их (другая вещь). Так что я заинтересован в обоих случаях; гарантирует, что классы не получат загружены и не получат run .

Ответы [ 7 ]

8 голосов
/ 15 августа 2010

Нет такой гарантии 1 в отношении загрузки классов.

Однако вы гарантированно не будете запускать статические блоки преждевременно.События, инициирующие инициализацию класса, указаны в JLS 12.4.1 .

Класс T или интерфейс типа T будут инициализированы непосредственно перед первым возникновением любого из следующих:

  • T - это класс, и создается экземпляр T.
  • T - это класс, и вызывается статический метод, объявленный T.
  • Статическое полеобъявлен T.
  • Используется статическое поле, объявленное T, и поле не является константной переменной (§4.12.4).
  • T является классом верхнего уровня, ивыполняется утверждение assert (§14.10), лексически вложенное в T.

1 - Замечено, что реализации Java текущего поколения не загружают классы без необходимости, но это не гарантия.Единственные гарантии - это то, что написано в официальных спецификациях.

4 голосов
/ 15 августа 2010

Спецификация java сообщает

Процесс загрузки осуществляется классом ClassLoader и его подклассами.Разные подклассы ClassLoader могут реализовывать разные политики загрузки.В частности, загрузчик классов может кэшировать двоичные представления классов и интерфейсов, предварительно выбирать их в зависимости от ожидаемого использования или загружать группу связанных классов вместе.

Таким образом, загрузчик классов может предварительно выбирать файлы классов.

Класс T или интерфейсный тип T будут инициализированы непосредственно перед первым возникновением любого из следующих действий:

  • T является классом и экземпляромT создан.
  • T является классом, и вызывается статический метод, объявленный T.
  • Назначается статическое поле, объявленное T.
  • Статическое поле, объявленноеT используется, и ссылка на поле не является константой времени компиляции (§15.28).Ссылки на константы времени компиляции должны быть преобразованы во время компиляции в копию значения константы времени компиляции, поэтому использование такого поля никогда не вызывает инициализацию.

Статические блоки будут выполняться только при первом использовании класса.

1 голос
/ 15 августа 2010

Если вы не используете рефлексию, то вы можете статически проверить, какие классы используются, с помощью инструмента удаления мертвого кода, такого как ProGuard . Он проанализирует ваш код и определит все используемые классы. На основании этого он удаляет неиспользуемый код, включая неиспользуемый код в библиотеках.

Если ваш код или библиотеки используют отражение для загрузки классов, вам нужно будет выполнить полный тест покрытия вашего приложения и записать в журнал все загруженные классы, которые вы проинструктировали ProGuard сохранить.

1 голос
/ 15 августа 2010

То, что тянет в классах, это ссылки на них из Java-байтового кода (который снова может тянуть в других классах). Если классы, которые вы запускаете, не имеют ссылки на класс X, он не будет загружен.

Обратите внимание, что существуют более новые способы регистрации, например, услуги через META-INF. Эти классы тоже должны быть загружены.

Вы всегда можете запустить с «-verbose», чтобы увидеть, как классы загружаются - порядок ясно показывает, что они загружаются при необходимости.

1 голос
/ 15 августа 2010

Я не думаю, что есть такая гарантия. Во-первых, я видел сканеры кода, которые выполняют такие вещи, как обработка аннотаций из целых иерархий / JAR-пакетов во время запуска приложения; они бы сразу нарушили это предположение.

Почему это имеет значение? Вы обычно после сильно контролируемой загрузки системы, так что все, что имеет значение, будет где-то, где вы все равно захотите это сделать ...

0 голосов
/ 16 августа 2010

Да.

Подумайте о следующем. Если вы добавите следующий код к этому library.jar классу:

 public ShutDown {static { System.exit(-1); }}

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

Способ загрузки классов описан в предыдущих ответах. Если вы внимательно изучите их, ни один из них не будет содержать «Если в банке есть класс, он будет загружен» какого-то рода.

0 голосов
/ 16 августа 2010

Нет таких гарантий, как упоминали другие авторы.Но ваш вопрос и ваше беспокойство не следуют друг от друга.Для того, чтобы вы оставили библиотеку. Вам не нужны такие гарантии.

Существует ряд платформ, которые обнаруживают наличие или отсутствие других платформ во время выполнения.Пример: Commons-logging открывает кучу других фреймворков.Веб-поток Spring обнаруживает структуру сценариев (например, OGNL) во время выполнения.Эти платформы, очевидно, скомпилированы с использованием всех зависимых структур, но они не должны существовать во время выполнения.

Следовательно, вполне допустимо оставлять файл library.jar во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...