Использование javax.tools.ToolProvider из пользовательского загрузчика классов? - PullRequest
6 голосов
/ 23 февраля 2010

Кажется невозможным использовать javax.tools.ToolProvider из пользовательского загрузчика классов, как того требует Ant или Webstart: http://bugs.sun.com/view_bug.do?bug_id=6548428

javax.tools.ToolProvider.getSystemJavaCompiler() загружает javax.tools.JavaCompiler в URLClassLoader, чьим родителем является системный загрузчик классов. Похоже, что API не позволяет пользователям указывать родительский загрузчик классов.

Как можно использовать javax.tools.JavaCompiler из пользовательского загрузчика классов?

Например:

  • Муравьиные грузы MyParserTask
  • MyParserTask анализирует исходный код Java
  • MyParserTask загружается AntClassLoader, который делегирует системному загрузчику классов
  • javax.tools.JavaCompiler загружается URLClassLoader делегатами в системный загрузчик классов

Позже MyParserTask вызывает:

javax.tools.CompilationTask task = compiler.getTask(...);
com.sun.source.util.JavacTask javacTask = (com.sun.source.util.JavacTask) task;
javacTask.parse().next().accept(visitor, unused); // parsing happens here
  • Видя, как эти два класса находятся в отдельных загрузчиках классов, MyParserTask не может взаимодействовать с JavacTask без ошибок ClassCastException.

Есть идеи?

Ответы [ 4 ]

2 голосов
/ 16 января 2013

У меня была точно такая же проблема. Я использую пользовательскую задачу ant для сканирования AST для определенных видов вызовов методов. Мое решение, которое может не подходить для вас, заключалось в том, чтобы создать экземпляр самого компилятора вместо использования ToolProvider.

я заменил

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

с

JavaCompiler compiler = (JavaCompiler)Class.forName("com.sun.tools.javac.api.JavacTool").newInstance();

Это, конечно, не будущее и не безопасно во всех средах, но это вариант в зависимости от ваших потребностей. Если у кого-то есть лучший способ использовать ToolProvider в пользовательских задачах Ant, пожалуйста, поделитесь.

0 голосов
/ 08 февраля 2013

У меня были похожие проблемы, я должен был загрузить tools.jar Когда я обнаружил, что подкласс не загружается.подробности в этой ссылке https://stackoverflow.com/questions/14619179/webappclassloader-loadclass-cannot-find-class-at-runtime Как я уже говорил, это может быть не очень хорошим решением, так как мы пытаемся возиться с загрузкой классов через программу.нашел здесь несколько полезных заметок http://easternlights -wisdomtree.blogspot.in / 2013/02 / classloading-blues-part1.html

0 голосов
/ 23 февраля 2010

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

Это обычно является результатом нарушения преимущественной отсрочки загрузки класса для родителя ClassLoader. Проще говоря, любой загрузчик классов должен сначала попросить своего родителя загрузить класс, прежде чем он попытается загрузить его сам. В противном случае возникают всевозможные «интересные» проблемы.

В вашем конкретном примере, поскольку A вызывал B, загрузчику классов B не удалось делегировать его родителю, поскольку, если A может видеть целевой класс, загрузчику классов B не нужно его загружать, учитывая, что A вызывал B и, следовательно, загрузчик класса А или его предок загрузили B.

0 голосов
/ 23 февраля 2010

Эта проблема часто возникает с OSGi. Некоторые люди придумали «загрузчики классов моста», см., Например, эту статью (которая, вероятно, соединяет только интерфейсы, а не подклассы, поэтому, возможно, вы не можете использовать его напрямую).

Если существует только несколько методов, которые вы хотите вызвать для «чужого» объекта, вы также можете избежать размышлений:

 javax.tools.CompilationTask task;
 task.getClass().getMethod("someMethodInTheSubclassThatICannotSee").invoke("a");

Основываясь на идее отражения, может быть, язык сценариев тоже полезен (Groovy, Beanshell, JavaScript).

...