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

Я использую артефакт (собственный) и буду использовать примерно 25% его функциональности.

Остальные неиспользуемые 75% — это много кода и заранее выделенной памяти.

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

Некоторые структуры классов спроектированы как индексированные/категоризированные компоненты, например:

class Utils {
   static class OfArrays {}
   static class OfCollections {}
}

Другие структуры наследуются:

class Parent {
   static class ClassToBeUsedInArtifact extends Parent {}
   static class IgnoredClass extends Parent {}
}

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

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

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

пример:

//Gradle keyword = `implementation` on all artifacts built.
SomeProject
   ├──(implementation) ArtifactC  (built with pruned ArtifactA and B)
   │            ├ (implementation)─ ArtifactB:1.0.0 
   │            └ (implementation)─ ArtifactA:1.0.0 
   ├──(implementation) ArtifactB:1.0.0 (built with pruned ArtifactA)
   │            └ (implementation)─ ArtifactA:1.0.1
   └──(implementation) ArtifactA:1.0.2 (full artifact)

Если используются специализированные инструменты сборки для удаления мертвого (двоичного) кода:

Сможет ли компилятор (стандартный или нет):

  1. выполнить разрешение зависимостей для каждого экземпляра ArtifactA, чтобы все три использовали одну и ту же версию? (Я предполагаю, что компилятор выберет последнюю версию ArtifactA:1.0.2)

  2. Сможет ли компилятор SomeProject сделать вывод, что ArtifactC должен использовать ArtifactB вместо использования его сокращенной версии?

  3. Я предполагаю, что ArtifactC можно использовать без необходимости реализации ArtifactB и B. Правильно ли это?

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

Преждевременная оптимизация — корень всех зол. Вы делаете слишком много предположений. Крайне маловероятно, что мертвый код потребляет значительную часть памяти или процессорного времени. Измерьте, прежде чем пытаться оптимизировать. Не предполагайте.

Elliott Frisch 29.08.2024 03:54

Да, вы будете возиться с проектами, которые зависят от вашего дела. Ничего здесь не делайте; только последующие проекты должны принимать решения о сокращении — в том крайне маловероятном случае, когда возникнет какая-либо причина для сокращения.

Louis Wasserman 29.08.2024 04:54

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

Thorbjørn Ravn Andersen 29.08.2024 06:22

Знаете ли вы, что это действительно проблема? Как говорит Торбьорн, если вы не обращаетесь к классу в своем коде, он не загружается, поэтому он и его код не занимают никакой памяти (за исключением, возможно, его имени в индексе загрузчика классов). Единственное, что «тратится впустую», — это дисковое пространство для JAR.

Mark Rotteveel 29.08.2024 10:55

Да @MarkRotteveel, я согласен со всеми здесь, спасибо, речь идет о размере дискового пространства jar. В некоторых случаях эта зависимость содержит размер кода, в 4–5 раз превышающий размер реализующего ее артефакта. Что касается ресурсов памяти, они распределены по разным классам, которые служат не только для категорий/индексации, но и для предотвращения ненужного предварительного выделения. Этот артефакт будет артефактом «основополагающего» типа, который в совокупности становится очень важным. Но меня беспокоит размер, так как из-за этого артефакт, реализующий его... (не знаю, правильная ли формулировка) "раздут".

Delark 29.08.2024 17:58

Спасибо @ThorbjørnRavnAndersen, я тестировал несколько структурных шаблонов, чтобы проверить это. Я нашел в случае с родственными классами; один не вызывает классовую нагрузку другого. Теперь мне интересно, вызывают ли внутренние классы (не наследники) загрузку класса своего родителя, даже если загруженный дочерний класс имел статический характер. Что касается моего беспокойства по поводу размера JAR, я не хочу быть человеком, который доставляет «раздутые» артефакты (я не знаю, правильный ли это термин). И если да, то что я должен порекомендовать потребителям моего артефакта?

Delark 29.08.2024 18:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если у вас нет большого опыта и у вас нет действительно веской причины, не пишите вложенные классы.

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

Не умничай. Пишите как можно более понятный код. Вы оцените это позже.

Спасибо, Торбьёрн, чтобы исправить проблему с распределением памяти, я решил использовать ленивые синглтоны, полученные с помощью синхронизации загрузки классов (с использованием записей). Что касается проблемы «раздутости», я решил, что пытаться решить проблему в промежуточном программном обеспечении — это то, чего делать не следует (особенно в Java), и ответственность полностью лежит на конечном продукте, поэтому компилятор конечного продукта выполняет любое необходимое разрешение.

Delark 04.09.2024 00:41

Ленивые одиночки? Что, черт возьми, это делает?

Thorbjørn Ravn Andersen 04.09.2024 00:45

Другие вопросы по теме