Класс org.eclipse.jdt.core.JDTCompilerAdapter не может быть загружен из-за недопустимой зависимости

Я создаю Java-агент, который будет использоваться для модификации байт-кода для некоторых классов. org.eclipse.jdt.core.JDTCompilerAdapter это один из них. Я использую javassit, чтобы изменить некоторые execute() метод org.eclipse.jdt.core.JDTCompilerAdapter, Поэтому я включил ecj как в моем агентском проекте (используя gradle)

compile group: 'org.eclipse.jdt.core.compiler' ,name: 'ecj', version :'4.3.1'

Так как мне нужно использовать несколько классов из ecj.

Цель агента - перехватить вызовы метода execute, изменить метод execute, чтобы добавить некоторые вызовы к некоторым моим классам с целью запуска некоторой обработки.

Я тестирую агента против простого Java-проекта с 2 классами. проект построен с использованием муравья JDTCompilerAdapter в качестве компилятора.

Вот файл build.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="TestProject">
<property file="build.properties" />

<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.7"/>
<property name="source" value="1.7"/>
<path id="PClasspath">
    <pathelement location="bin"/>
</path>


<target name="init">
    <mkdir dir="bin"/>
    <copy includeemptydirs="false" todir="bin">
        <fileset dir="src">
            <exclude name="**/*.java"/>
        </fileset>
    </copy>
</target>
<target name="clean">
    <delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="init" name="build">

    <javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
        <src path="src"/>
        <classpath refid="PClasspath"/>

    </javac>
</target>
<!--
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
    <copy todir="${ant.library.dir}">
        <fileset dir="${ECLIPSE_JDT_CORE}" includes="*.jar"/>
    </copy>
</target>-->
<target  name="build-e" >

    <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
    <antcall target="build"/>
</target>

Агент должен использоваться при создании проекта. Поэтому для тестирования агента я использую эту команду:

java -jar agent-wrapper.jar --outdir ./out --exec ./build_wrapper.sh

build_wrapper.sh содержит это (я добавил зависимость ecj, чтобы я мог скомпилировать проект с JDTCompilerAdapter как у меня в bulid.xml <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>:

../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar  build-e

Идея состоит в том, что агент-обертка будет анализировать аргумент (outdir используется для генерации некоторого материала, а exec - это скрипт, используемый для запуска сборки моего тестового проекта), чтобы получить команду для выполнения из build_wrapper.sh (в этом случае ../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e) и добавьте себя в качестве агента Java в команду.

Проблема возникает во время выполнения агента. Вот вывод:

    java -jar  custom-agent.jar --outdir ./out --exec ./build_wrapper.sh                              [10:18:53]
Picked up JAVA_TOOL_OPTIONS: -javaagent:/Users/dev/TestAgent/project/custom-agent.jar=OUTDIR=/Users/dev/TestAgent/project/./out 
objc[30474]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
Buildfile: /Users/dev/TestAgent/project/build.xml

build-e:

init:
    [mkdir] Created dir: /Users/dev/TestAgent/project/bin

build:

BUILD FAILED
/Users/dev/TestAgent/project/build.xml:47: The following error occurred while executing this line:
/Users/dev/TestAgent/project/build.xml:32: Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency.

Total time: 2 seconds
abnormal termination, exit code: 1

Когда я не использую ecj-4.3.1.jar в моем агентском проекте, сборка работает хорошо, я перехватываю вызов execute() метод, но я не могу использовать другие классы из ecj jar.

1 ответ

Решение

Ошибка show stoppper: "Класс org.eclipse.jdt.core.JDTCompilerAdapter не может быть загружен из-за недопустимой зависимости".

Первый намек на ошибку можно найти, прочитав эту ссылку http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-ant_javac_adapter.htm

Второй намек может заключаться в том, что отсутствует один из jar-файлов, необходимых для запуска JDTCompilerAdapter.

Чтобы заставить JDTCompilerAdapter работать, я скопировал JDTCompilerAdapter.jar и org.eclipse.jdt.core.jar в папку ant/lib.

Существуют различия, основанные на версии Eclipse и версии Java, которые описаны в ссылке, упомянутой выше.

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