Ant не перекомпилирует константы - PullRequest
4 голосов
/ 21 июня 2011

У меня есть проект Java, который включает в себя класс GUIConstants - различные параметры public static final, используемые для разметки графического интерфейса, так как разные компоненты иногда должны быть одинакового размера или цвета или чего-либо другого.

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

Sidenote: Моя гипотеза состоит в том, что, когда класс, который использует переменную final, компилируется, Java вместо этого использует само значение, а не ссылку на то, на что указывает переменная (аналогично тому, как * 1010) * для констант работает в C). Таким образом, даже когда переменная указывает на что-то еще, исходное значение запекается в файле .class. Это правда? (Это не влияет на мою проблему, мне просто любопытно.)

Заранее спасибо.

Ответы [ 5 ]

2 голосов
/ 21 июня 2011

Ваша теория неверна. Java встраивает финалы в пул констант в окружающем файле классов так же, как и любые нефиналы. Специальной «окончательной» оптимизации не существует, за исключением флага, указывающего, что он может быть установлен только во время построения.

Вероятность намного выше, если у вас есть какая-то ошибка в вашей цепочке сборки, например, класс или набор классов, которые "обновляются" из старых источников, или файлы JAR, которые "собираются" из еще не обновленных классов или программы, которые ссылаются на файлы JAR из предыдущих сборок и т. д. Одним из быстрых способов убедиться в этом является удаление всех скомпилированных элементов. Часто это делается с помощью «чистой» цели в файле ant build.xml; однако, эта цель также может быть написана от руки, поэтому не думайте, что она всегда верна (особенно если вы добавили дополнительные промежуточные этапы сборки, такие как улучшение класса и т. д.).

2 голосов
/ 22 июня 2011

Ваша гипотеза почти верна.Это не просто final переменные, а так называемые " постоянные переменные ":

Мы называем переменную примитивного типа или типа String, которая является окончательной и инициализируется с помощьюпостоянное выражение времени компиляции ( §15.28 ) постоянная переменная.Независимо от того, является ли переменная постоянной или нет, это может иметь значение в отношении инициализации класса ( §12.4.1 ), двоичной совместимости ( §13.1 , §13.4.9 ) и определенного присвоения ( §16 ).

Затем в разделе о двоичной совместимости (§13.1) :

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

и ( §13.4.9 ) (мой акцент):

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

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

Когда вы комбинируете это с тем, какjavac задача определяет, какие классы для перекомпиляции вы получаете поведение, которое вы видите:

Только файлы Java, которые не имеют соответствующего файла .class или гдеФайл классов старше, чем файл .java, который будет скомпилирован.

Примечание. Apache Ant использует только имена исходных файлов и файлов классов, чтобы найти классы, которые необходимо перестроить.Он не будет сканировать исходный код и, следовательно, не будет знать о вложенных классах, классах, имена которых отличаются от исходного файла, и так далее.См. Задачу <depend> для проверки зависимостей, основанных не только на времени существования / изменения.

Самый простой способ исправить это - чистая полная компиляция каждый разс чем-то вроде ant clean compile (при условии, что у вас есть цель clean, которая удаляет все ваши файлы классов).Хотя это может быть слишком медленно.

Я также собирался предложить вам посмотреть на задачу depend, как предложено в документации для задачи javac, но, глядя наДокументы для него (я сам на самом деле не использовал его), похоже, это не поможет (см. раздел «Ограничения»):

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

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

1 голос
/ 21 июня 2011

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

0 голосов
/ 15 мая 2017

Ответ DJClayworth в этом answer предлагает использовать конструкцию, подобную следующей, чтобы обмануть компилятор:

public static final int INT_VALUE = Integer.valueOf(100).intValue();

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

Не красивое решение, но хорошее временное решение.

0 голосов
/ 31 августа 2015

Ни одна из "теорий" не кажется правильной, удаление статики не имеет никакого эффекта, перекомпиляция из clean всегда работает, моя сборочная "система" - это почти таинственная пластина, полагающаяся только на источник в подкаталоге, и никаких других внешних jar-файлов, нет "устаревших" "занятия висят вокруг

В моем случае мне нужно полностью перестроить одну область моих источников - я напрямую включаю библиотеку из источника, которая не нуждается в перекомпиляции, но включена в отдельное правило "Deepclean", но изолирована из этого номера ...

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