Как надежно настроить компоновщик байт-кода посткомпиляции в Eclipse? - PullRequest
2 голосов
/ 03 марта 2020

Мне нужно настроить проект Eclipse с дополнительным компоновщиком, который расширяет байт-код Java, созданный более ранним компоновщиком (в идеале, собственным Eclipse). Мне удалось заставить этот компоновщик правильно запускать и улучшать вывод компоновщика Eclipse Java, но спустя несколько секунд Eclipse перезапускает свой компоновщик Java и сбрасывает байт-код обратно. Он не перезапускает мой конструктор улучшений.

Моя настройка

  • Импортирован как "проект Gradle" в Eclipse 2019-12 (с Buildship).
  • Добавлен вручную (и автоматизирован с помощью Gradle) специальный Ant строитель (который в конечном итоге вызывает Gradle) для улучшения кода, который Eclipse Java строитель создает на месте bin / main. Этот компоновщик настроен на запуск Ручная сборка и Автоматическая сборка , а не После «Очистки» или Во время «Очистки» .
  • По умолчанию вышеприведенное имеет три компоновщика сверху вниз: 1. Gradle Project Builder , 2. Java Builder и 3. my построитель расширений байт-кода (да, он указан последним).

альтернативы, которые я пробовал

  1. Некоторые комбинации установки моего сборщика для запуска после / во время «Чистоты» также безуспешно. Не уверен, к каким именно событиям они относятся, действительно.
  2. Если бы строитель пересмотрел sh проект после ... а также нет - не помогло.
  3. Попробуйте удалить Java Builder, использующий следующий бит в скрипте Gradle (не работал - он возвращается сам по себе):

    eclipse {
        project {
            file {
                whenMerged { projectFile ->
                    projectFile.buildCommands.removeAll { it.name == 'org.eclipse.jdt.core.javabuilder' }
                }
            }
        }
     }
    
  4. Попытался вручную отключить построитель Java и Пусть мой конструктор улучшения байт-кода также создаст сами файлы (используя Gradle). При этом сохраняется следующий файл org.eclipse.jdt.core.javabuilder.launch файл со следующим содержимым ... но после перезапуска сборщик снова включается:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
    <booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.jdt.core.javabuilder"/>
    <mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
    <booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
    </launchConfiguration>
    
  5. Я пытался (и не смог) найти есть некоторый файл рабочей области (в отличие от файла проекта), который также изменяется (отключается) для построения Java.

Вопросы

  1. Каков "правильный" способ настроить Eclipse для улучшения байт-кода после компиляции?
  2. Что заставляет Eclipse перезапускать предыдущие компоновщики без повторного запуска моего?
  3. есть способ исправить (1)?
  4. Как надежно отключить Java строитель?

Может кто-нибудь помочь? Спасибо!

ОБНОВЛЕНИЕ Дополнительные сведения Я добавил 12 сборщиков и заставил их добавить результаты в один файл журнала для исследования. 12 дополнительных строителей являются просто информационными - 4 до строителя Java, 4 между Java и строителем улучшений и 4 после построителя улучшений. Каждый из 12 работает только в одном из четырех условий (следовательно, 3х4). Они расположены следующим образом:

  1. Gradle Project Builder
  2. 1a-after-clean (работает только После «Очистки» )
  3. 1b-manual (работает только Во время ручной сборки )
  4. 1 c -auto (выполняется только Во время автоматической сборки )
  5. 1d во время очистки (работает только Во время «очистки» )
  6. Java Builder
  7. 2a после очистки (работает только После "Очистить" )
  8. 2b-manual (работает только Во время ручной сборки )
  9. 2 c -auto ( работает только во время автоматической сборки )
  10. 2d во время очистки (работает только во время "очистки" )
  11. Builder Enhancement Builder
  12. 3a-after-clean (работает только После «Очистки» )
  13. 3b-manual (работает только Во время ручной сборки )
  14. 3 c -авто (работает только во время автоматической сборки )
  15. 3d-во время очистки (работает только во время "очистки" )
  16. Создайте папку - назовите ее, как вам sh.
  17. В этой папке создайте build.grade файл со следующим содержимым:

    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            classpath 'org.hibernate:hibernate-gradle-plugin:5.4.2.Final'
        }
    }
    
    plugins {
        id 'java'
        id 'eclipse'
    }
    
    apply plugin: 'org.hibernate.orm'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
    }
    
    hibernate {
        sourceSets = [ project.sourceSets.main ]
        enhance {
            enableLazyInitialization = true;
            enableDirtyTracking = true;
            enableAssociationManagement = false;
            enableExtendedEnhancement = false;
        }
    }
    
  18. Создайте там src / main / java / ученик / TestEntity. java также следующим образом:

    package learner;
    
    import javax.persistence.*;
    
    @Entity
    public class TestEntity {
        @Id
        @Column(name = "id", nullable = false, updatable = false)
        private Long id = null;
    
        @Column(name = "name", columnDefinition = "TEXT")
        private String name = null;
    
        public Long getId() {
            return id;
        }
    
        public void setId(final Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(final String name) {
            this.name = name;
        }
    }
    
  19. Выполните gradle compileJava. Откройте получившийся двоичный файл build/classes/java/main/learner/TestEntity.class в ASCII или шестнадцатеричном вьюере и наблюдайте там что-то вроде $$_hibernate_write_name.

  20. Импортируйте этот проект в Eclipse (скажем, 2019-12) как проект Gradle и постройте его , Откройте получившийся bin/main/learner/TestEntity.class и не наблюдайте ничего из этого.

1 Ответ

0 голосов
/ 05 марта 2020

Было несколько вещей, которые мне были неясны / неправильны, и я не мог найти соответствующую документацию, чтобы узнать подробности. Вот краткое изложение того, что нужно знать, чтобы понять это правильно (кое-что из того, что я понял из get go, но не все):

  1. Интеграция Gradle / Buildship в Eclipse пытается сделать использование внутреннего компилятора Eclipse. Это дизайн Eclipse и имеет свои преимущества во время разработки ... а также недостатки в такие времена - невозможность использовать внешние / производственные строители (в данном случае модель Gradle) для создания здания. По этой причине любое улучшение байт-кода (подключаемые модули или нет), работающее внутри Gradle, не будет иметь никакого эффекта в Eclipse вообще (если они не делают что-то, специфичное для Eclipse c). (я понял это правильно)
  2. Чтобы выполнить улучшение байт-кода в Eclipse (не apt или то, что мог бы сделать какой-либо плагин Eclipse), нужно добавить собственные компоновщики и расположить их после значения по умолчанию Java строитель (вручную или автоматически). (я тоже это понял)
  3. В стандартной комплектации Eclipse предлагает два типа компоновщиков - «Муравей» и «Программа». Нет Gradle там. «Программный» вид не кроссплатформенный, только Ant. Ant можно использовать для выполнения каких-либо задач или запуска Gradle кросс-платформенным способом (Java exe c в методе Gradle main ()). (я тоже это понял)
  4. [Я НЕПРАВИЛЬНО ЗДЕСЬ] Eclipse предлагает четыре "события", к которым можно привязать строителя муравьев: После a «Очистка» , Ручная сборка , Автоматическая сборка и Во время «Очистки» . Я не понял, когда они бегут. Например, я подумал, что «Во время очистки» запускается , в то время как происходит очистка, и что После «Очистки» после этого должен запускаться , чтобы пользовательский конструктор мог выполнить собственная чистка после очистки. Я думал, что за этим последует автоматическая сборка, если включена опция «Автоматическая сборка» или в диалоговом окне «Очистка» установлен флажок «Строить сразу» Это НЕ так . После «Очистить» фактически относится к этапу сборки, а не к очистке, и НЕ будет сопровождаться этапом «Автоматическое построение» (этот этап выполняется только тогда, когда сохраняются изменения и активирован «Сборка автоматически»). В файле * .launch компоновщика это гораздо более очевидно - После "Чистого" фактически называется full, а Авто и Ручные сборки называются auto и incremental. Это означает, что En Enh Builder должен быть настроен для работы на После «Очистки» в дополнение к Автоматическое построение и Ручное построение и НЕ ДОЛЖЕН быть настроен на запуск * во время «Очистки». Моя ошибка состояла в том, чтобы установить его только для Авто и Ручная сборок.
  5. [Я БЫЛ НЕПРАВИЛЬНО ЗДЕСЬ] Я указал рабочий набор соответствующих ресурсов на вкладке Параметры сборки для построителя расширений. Я установил эти ресурсы как исходный код (для улучшения) и build.gradle (содержащий энхансер). На большинстве сборок Eclipse решает не запускать сборщик. Теперь очевидная истина 20-20 заключается в том, что соответствующие ресурсы для этого компоновщика - это выходные файлы компоновщика Java (и build.gradle), а не исходный код Java. Тем не менее, это не совсем правильный выбор (в отдельности), так как Eclipse, в нашем случае, заканчивается бесконечным l oop - он думает, что энхансер изменил двоичные файлы и, поскольку он настроен на работу при изменении двоичных файлов , запускает сборку снова. Мы НЕ МОЖЕМ устанавливать соответствующие ресурсы вообще, так как это означает «все / что угодно». Энхансер должен быть сделан таким образом, чтобы НЕ трогать уже улучшенные файлы [ОБНОВЛЕНИЕ] , и этого недостаточно. Читайте дальше.

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

[ОБНОВЛЕНИЕ 1]

[Я ЭТО НЕ ЗНАЛ] Eclipse имеет настройку рабочего пространства (флажок, можно переопределить для проекта) в Предпочтения -> Java -> Компилятор -> Сборка -> Выходная папка с именем " Перестройка файлов классов, измененных другими ", официально обозначаемыми как " Укажите, Файлы классов, которые были изменены другими, должны быть перестроены, чтобы отменить изменение.". По умолчанию это не отмечено / выключено, что кажется правильным для этого случая. Это, однако, не работает как рекламируется . Какой бы ни была настройка, Eclipse Java Builder будет реагировать на свои выходные изменения (как если бы они были входными данными, я называю это дефектом) и «отменять модификацию», вызывая бесконечные циклы сборки. Я обнаружил, что об этом симптоме сообщалось много раз - ищите это. С «правильной» настройкой и без взлома Java строитель продолжает отменять изменения, и Eclipse продолжает их повторять, вызывая бесконечное l oop независимо от настройки. [HACK THAT SEEMS ЧТОБЫ РАБОТАТЬ НАСТОЯЩЕЕ] В дополнение к правильной настройке всего вышеперечисленного, я изменил энхансер, чтобы обеспечить две вещи (может потребоваться только одна или обе, не уверен): (a) что существующие файлы *.class НЕ удалено и воссоздано, но переписано и (b) что их время последнего изменения изменилось на то, что было до улучшения. Это, кажется, обманывает обнаружение модификации Eclipse достаточно, чтобы вырваться из l oop, даже если размеры файлов различны. Это с Eclipse 2019-12 (4.14.0.v20191210-0610), и он может перестать работать с любым обновлением. Я надеюсь, что к тому времени они исправят бесконечный дефект сборки l oop.
...