2016-04-14 6 views
4

Я пытаюсь скомпилировать некоторые Java-классы в String с помощью java. Я использовал javax.tools.JavaCompiler для компиляции классов в строках.Скомпилировать классы круговой зависимости, используя javax.tools.JavaCompiler

Я создал экземпляры SimpleJavaFileObject подкласса, которые я создал из SimpleJavaFileObject.

import javax.tools.SimpleJavaFileObject; 
import java.net.URI; 

public class JavaSourceFromString extends SimpleJavaFileObject { 
    final String code; 

    public JavaSourceFromString(String name, String code) { 
     super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE); 
     this.code = code; 
    } 

    @Override 
     public CharSequence getCharContent(boolean ignoreEncodingErrors) { 
     return code; 
    } 
} 

и я сделал экземпляры этого класса, добавил его к ArrayList, а затем Получил

ToolProvider.SystemJavaCompiler();

и добавлены варианты компиляции. а затем скомпилирован

Iterable<? extends JavaFileObject> fileObjects = jsfsList; 

JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
if (jc == null) throw new Exception("Compiler unavailable"); 

List<String> options = new ArrayList<>(); 
options.add("-d"); 
options.add(Config.getProperty("DESTINATION_PATH")); 
options.add("-classpath"); 

URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
StringBuilder sb = new StringBuilder(); 
for (URL url : urlClassLoader.getURLs()) { 
    sb.append(url.getFile()).append(File.pathSeparator); 
} 
sb.append(PiranhaConfig.getProperty("DESTINATION_PATH")); 
options.add(sb.toString()); 

StringWriter output = new StringWriter(); 
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
if (success) { 
    LOG.info("Class [" + compiledClasses + "] has been successfully compiled"); 
} else { 
    throw new Exception("Compilation failed :" + output); 
} 

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

как добиться того же результата, что и Javac, используя этот компилятор? Кто-то, пожалуйста, укажите мне в правильном направлении :) Спасибо.

+0

также отметить, что эти три тестовые классы форма 3 различных пакетов :) –

+0

Круговые взаимозависимостей между пакетами не такая хорошая идея, в первую очередь ... –

+0

Хотя я считаю, что вопрос достаточно интересный, я проголосовал за его закрытие: «Вопросы, требующие помощи по отладке (« почему не этот код работает? ») Должны включать в себя желаемое поведение, конкретную проблему или ошибку и самый короткий код, необходимый чтобы воспроизвести его в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См.: [Как создать минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve). " Можете ли вы обновить свой пример, чтобы а) мы могли его скомпилировать, б) он воспроизводит проблему, в) он содержит определенные ошибки, которые вы обнаружили. –

ответ

0

Я нашел решение для проблемы,

в процессе компиляции Я создал ArrayList для хранения экземпляров SimpleJavaFileObject (классов для компиляции), вместо этого у меня есть объявление вывести LinkedList.

со списком ссылок он работает отлично :)

0

Следующий код работает успешно для меня (почти так же, как код OP, всего заменяет неопределенные символы с разумными альтернативами):

import java.io.File; 
import java.io.StringWriter; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 

import javax.tools.JavaCompiler; 
import javax.tools.JavaFileObject; 
import javax.tools.ToolProvider; 

class CircularDeps { 
    public static void main(String[] args) throws Exception { 
    Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(
     new JavaSourceFromString(
      "A", 
      "package packageA; public class A { packageB.B b; }"), 
     new JavaSourceFromString(
      "B", 
      "package packageB; public class B { packageC.C c; }"), 
     new JavaSourceFromString(
      "C", 
      "package packageC; public class C { packageA.A a; }") 
     ); 

    JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
    if (jc == null) throw new Exception("Compiler unavailable"); 

    List<String> options = new ArrayList<>(); 
    options.add("-d"); 
    options.add(args[0]); 
    options.add("-classpath"); 

    URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
    StringBuilder sb = new StringBuilder(); 
    for (URL url : urlClassLoader.getURLs()) { 
      sb.append(url.getFile()).append(File.pathSeparator); 
    } 
    sb.append("output"); 
    options.add(sb.toString()); 

    StringWriter output = new StringWriter(); 
    boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
    if (success) { 
      System.out.println("Classes has been successfully compiled"); 
    } else { 
      throw new Exception("Compilation failed :" + output); 
    } 
    } 
} 

Выход:

Classes has been successfully compiled