Java, являются ли классы с аннотациями индекса во время компиляции с обработчиком аннотаций хорошей практикой?

Я думаю о создании индекса (даже простого списка, хранящегося в файле) классов, аннотированных определенным типом аннотаций во время компиляции с процессором аннотаций, чтобы ускорить поиск аннотированных классов во время выполнения.

Итак, это хорошая практика? Есть ли недостатки? Если это так хорошо, как мне кажется сейчас, то почему не так много библиотек, чтобы сделать это простым способом (единственная, которую я нашел, это Указатель класса)? Вместо обработки во время выполнения их так много?


person Paolo Dragone    schedule 24.01.2015    source источник
comment
Для меня это звучит как преждевременная оптимизация. Вы выполняли какие-либо тесты?   -  person Elliott Frisch    schedule 24.01.2015
comment
ClassIndex сделал несколько интересных тестов, я сам ничего не делал. Это может быть преждевременная оптимизация, но вопрос остается. Я думаю, что это также важная проблема дизайна моей библиотеки.   -  person Paolo Dragone    schedule 24.01.2015
comment
Цитата из вашей ссылки значительно ускоряет загрузку Java-приложений, сколько раз (обычно) вы бы сказали, что ваши приложения (или приложения ваших пользователей) обычно загружаются во время одного запуска ? Наконец, кажется, что плагин Reflections Maven работает почти так же хорошо (в этом единственном опубликованном тесте)...   -  person Elliott Frisch    schedule 24.01.2015
comment
Предположительно, обработка во время выполнения более распространена, потому что она более полезна и мощна. Обработка во время компиляции работает только для обнаружения классов (или чего-то еще), доступных во время компиляции. Представьте, что вы используете аннотации, чтобы сделать вашу библиотеку подключаемой, или потому что ваша библиотека предоставляет аннотации, которые конечные пользователи должны применять в своем коде (например, Джексон). Обработка аннотаций во время компиляции невозможна, поскольку такие аннотации отсутствуют в коде на момент компиляции вашей библиотеки.   -  person Matt Ball    schedule 24.01.2015
comment
@MattBall, разве мой процессор не запускается во время компиляции клиентского кода, если он находится в META-INF/services/javax.annotation.processing.Processor ??   -  person Paolo Dragone    schedule 24.01.2015
comment
@ElliottFrisch, может быть, это глупо, но если быстрее индексировать во время компиляции, то почему бы и нет?   -  person Paolo Dragone    schedule 24.01.2015
comment
Полностью зависит от процесса сборки клиента.   -  person Matt Ball    schedule 24.01.2015
comment
@MattBall, если я поставлю META-INF/services/javax.annotation.processing.Processor в свою библиотеку, процессор будет включен, если только клиент не отключит его намеренно, верно? Но если он намеренно отключит его, почему он (она) все равно должен использовать мою библиотеку.   -  person Paolo Dragone    schedule 24.01.2015


Ответы (3)


Как автор библиотеки ClassIndex я могу перечислить несколько преимуществ использования обработки аннотаций для индексации аннотаций, а также недостатки, которые, по моему мнению, препятствуют ее широкому внедрению.

Преимущества:

  • Индексирование с использованием обработки аннотаций основано на официальном JSR 269. С другой стороны, сканирование путей к классам зависит от внутренних компонентов Java. Общеизвестно, что у ClassLoaders нет API для получения списка аннотированных классов. Но что более удивительно, так это то, что универсальный ClassLoader не позволяет перечислять папки и файлы JAR, из которых он пытается загрузить классы. Сканеры пути к классам предполагают, что единственным загрузчиком классов, используемым для загрузки классов, является URLClassLoader, который позволяет извлекать исходные URL-адреса для сканирования с помощью метод getURLs().
  • Существуют среды, в которых обычные сканеры пути к классам не работают, то есть случай на Android, где используется формат Dalvik Executable.
  • Постоянная сложность во время выполнения делает индексирование во время компиляции очень быстрым.
  • Project Jigsaw планирует внедрить обнаружение аннотаций в Java . Текущие требования также предполагают индексацию во время компиляции как жизнеспособную реализацию. Он даже вводит метааннотацию @Indexed с той же целью, что и @IndexAnnotated в библиотеке ClassIndex.

Недостатки:

  • JSR 269 плохо поддерживается компиляторами и инструментами Java. В более ранних версиях javac было несколько ошибок. Пользовательский JDT-компилятор Eclipse содержит еще больше ошибок и не поддерживает автоматическое обнаружение обработчиков аннотаций. ClassIndex включает обходные пути для многих из этих проблем.
  • Сканирование пути к классам является фактическим стандартом и очень хорошо поддерживается.
  • Время загрузки приложения редко является узким местом, о котором стоит беспокоиться.
person Sławek    schedule 20.08.2015

Я думаю, что основные недостатки в том, что это сложнее. Обработка аннотаций — это совершенно новый API и концепция, с которой многие разработчики не знакомы. API Reflection проще и более известен. Обычно вы можете выполнять те же задачи во время выполнения.

Если более высокая производительность при запуске имеет решающее значение (что случается редко), то, возможно, стоит добавить сложности.

Хотя я бы не стал доверять тестам. Они заявляют, что «размер пути к классам был установлен на 121 МБ» - произвольное значение, которое делает любое сравнение с жестко запрограммированным или компилируемым временем обработки совершенно бесполезным. Зачем вам все равно сканировать весь путь к классу? Сканирование только классов разработчиков было бы более разумным в большинстве случаев.

Многие платформы используют файлы конфигурации или имеют API для ограничения классов или пакетов, которые необходимо сканировать. Это значительно увеличивает время запуска.

почему не так много библиотек для этого

Многие инструменты/фреймворки OSGi делают это. Аннотации сканируются во время компиляции, а метаданные записываются в файл манифеста jar или создаются более сложные файлы метаданных. Я подозреваю, что основная причина этого заключается в том, чтобы сохранить совместимость с bnd и подобными инструментами, которые использовались для построения и анализа времени компиляции компонентов OSGi до того, как аннотации или обработка аннотаций стали более популярными. Кроме того, компонент OSGi имеет свой собственный жизненный цикл и может появляться и исчезать в любое время. Так что это случай, когда время запуска имеет большее значение, поскольку вы не можете сканировать только один раз при запуске приложения. Вам нужно будет сканировать аннотации всякий раз, когда компонент (повторно) запускается.

Я бы не сказал, что это хорошая или плохая практика. Используйте эту технику, когда она соответствует вашим потребностям. Я бы не стал слишком усложнять ради времени запуска в несколько миллисекунд.

person kapex    schedule 25.01.2015
comment
Спасибо за заметный ответ, действительно помог получить более широкое представление. Размышляя об этом, я на самом деле обнаружил недостаток индексации времени компиляции, который заключается в отсутствии применимости к подключаемым библиотекам, таким как реализации абстрактных фабрик и SPI. Я не уверен, должен ли я поставить это в ответ на мой собственный вопрос. - person Paolo Dragone; 25.01.2015

Вам может быть интересен подпроект JBoss WildFly: Jandex.

Он создает индексы аннотаций во время сборки (и файл индекса можно добавить в JAR) или во время выполнения (аннотации извлекаются путем изучения файлов классов, а не путем отражения), что значительно повышает производительность извлечения аннотаций, поскольку позволяет избежать необходимости фактической загрузки классов.

Jandex звучит очень похоже на то, что вам нужно.

person Gunnar    schedule 16.12.2015