Подтвердить что ты не робот

Как могут ant компилировать-и-jar байт-идентичные файлы jar, т.е. Так MD5 соответствует, если изменяется значение .java(и, следовательно, класс .class)?

Резюме

Как вы можете сделать ant несколько раз генерировать байт-идентичные файлы jar из тех же .class файлов?

Фон

Наш процесс сборки делает следующее:

  • получает файлы определения веб-сервисов (wsdl) из другого репозитория источника приложения.
  • запускает wsdl2java для создания файла .java для использования клиентами веб-сервиса (например, наше приложение)
  • компилирует java файлы
  • создает файл .jar из выходного файла компилятора
  • проверяет файл артефакта в исходном элементе управления

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

Проблема

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

Я проверил Интернет и нашел этот вопрос примерно через 5 лет назад:

Если я скомпилирую некоторый код и создаю jar и связанный файл md5 с помощью ANTконтрольная сумма в файле md5 отличается каждый раз, даже если код не изменился. Любая идея, почему это так, как можно обойти? Я подозреваю, что какая-то информация о временной отметке куда-то прибывает.

http://www.velocityreviews.com/forums/t150783-creating-new-jar-same-code-different-md5.html

В ответах я попытался сделать следующее:

  • установите метку времени на "0" во всех файлах .class перед jarring
  • указание файла манифеста, а также установление метки времени 0 для этого манифеста

[Примечание: этот второй шаг кажется неэффективным. См. Ниже]

После каждой сборки файл .jar по-прежнему имеет другую сумму MD5.

Файл CSI: Jar

Я не привязан и проверен, а баны как содержимого, так и временных меток совпадают между "разными" банками с одним исключением: разные временные метки для META-INF/MANIFEST.MF.

код

   <-- touch classes and manifest to set consistent timestamp across builds -->
   <touch millis="0">
    <fileset dir="${mycompany.ws.classes.dir}"/>
   </touch>
   <touch millis="0" file="mymanifest.mf"/>

   <jar destfile="${derived.lib.dir}/mycompanyws.jar"
        manifest="mymanifest.mf"
        basedir="${mycompany.ws.classes.dir}"
        includes="**/com/mycompany/**,**/org/apache/xml/**" 
    />

Другие параметры

Мы могли бы использовать fancier ant для программирования только в файле .jar, если изменились .java файлы.

4b9b3361

Ответ 1

Так как jar - это просто zip файл incognito, вы можете попробовать использовать задачу zip, чтобы добавить файл манифеста под META-INF/ вручную. Надеюсь, что обходит любую внутреннюю магию, связанную с обработкой манифестной задачей в баночке.

Просто боковое примечание, так как похоже, что наличие равных MD5 является критическим, я бы рекомендовал вам добавить тест на здравомыслие как часть сборки, например, скомпилировать специальный "dummy" код, который никогда не меняется в банку и не проверяет jar MD5 соответствует ожидаемому. Это защитит сборку от непредвиденных изменений (например, после обновления до ant, JRE, ОС, изменения часового пояса и т.д.)

Ответ 2

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

  • Временные метки: **/*.class файлы должны иметь одну и ту же метку времени (java.util.zip.ZipEntry.setTime(long)). Кроме того, файл META-INF/MANIFEST.MF и файлы сертификатов (*.RSA, *.DSA и *.SF) добавляются в файл JAR с меткой "now". Поэтому, даже если вы решили не компилировать классы и использовать уже скомпилированные (т.е. Те, у которых есть исходная временная метка JAR), ваш итоговый JAR будет двоичным.
  • MANIFEST.MF Записи Порядок: Обратите внимание, что пары ключ-значение в файле MANIFEST.MF представлены как java.util.HashMap, которые "does not guarantee that the order will remain constant over time.". Таким образом, вы можете столкнуться с другой двоичной разницей при подписании JAR файлов с помощью JDK v5 и JDK v6 jarsigner, так как порядок записей MANIFEST.MF может измениться (http://stackoverflow.com/questions/1879897/order-of -Элементы-в-HashMap-отличаются-когда-The-же-программа-это-обкатку-jvm5-против-jvm6).

Итак, в основном есть два уровня проблемы. Во-первых, инструмент JAR/ZIP, который упаковывает файлы со своими временными метками файловой системы и, таким образом, создает двоичные файлы JAR для одного и того же набора классов Java, которые являются двоичными равными, но были скомпилированы в другое время. Во-вторых, инструмент подписывания JAR, который изменяет файл META-INF/MANIFEST-MF и добавляет больше файлов в архив JAR (сертификаты и контрольные суммы файла файла).

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

Ответ 3

Если бы эта же проблема, приземлился на этой странице. Ответ выше, написанный Jiri Patera, был очень полезен в понимании того, почему я не смог получить md5sums того, что, как я ожидал, будет иметь два одинаковых файла, после того, как вы поставили под себя и отменили файлы jar.

Это решение, которое я использовал вместо:

jar -tvf $JARFILE | grep -v META-INF | perl -p -e's/^\s + (\ d +). *\s + ([\ w] +)/$1 $2/g '| md5sum

Это не дает 100% уверенности в том, что банки эквивалентны, но дает достаточно надежную индикацию.

Он берет список всех файлов в jarfile за вычетом файлов META_INF, анализирует размер файла и имя файла, а затем запускает текст файлов плюс имена файлов через алгоритм md5sum.