Как скомпилировать.java с зависимостями во время выполнения?

У меня много .java файлы, которые нужно импортировать другой .java файл...

Что-то вроде этого:

import package.c;

public class A {

  // do whatever that needs package.c
}

Но у меня есть только package.c.java,

Когда я пытаюсь скомпилировать Используя Java Compiler или что-либо еще, что я знаю, я всегда получаю эти ошибки

ошибка: пакет <-package-> не существует

Или что-то вроде:

ошибка: не могу найти символ

Я не могу скомпилировать A.java потому что нужно C.class это не может быть скомпилировано, потому что нужен другой, кто-то знает, что мне делать?

Все нормально когда .java не нужны зависимости, в этих случаях Java Compiler работает хорошо.

Возможно, ссылка GetStarted могла бы решить мою проблему, но я не могу найти способ сделать это.

[EDIT] Это мой код компилятора:

    File sourceDir = new File(source);
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, Locale.getDefault(), null);
    List<JavaFileObject> javaObjects = scanRecursivelyForJavaObjects(sourceDir, fileManager);
    System.out.println(javaObjects.size());
    if (javaObjects.size() == 0) {
        throw new CompilationError("There are no source files to compile in " + sourceDir.getAbsolutePath());
    }
    String[] compileOptions = new String[]{"-d", sourceDir.getAbsolutePath()};
    Iterable<String> compilationOptions = Arrays.asList(compileOptions);

    CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostics, compilationOptions, null, javaObjects);

    if (!compilerTask.call()) {            
        for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
            System.err.format("Error on line %d in %s", diagnostic.getLineNumber(), diagnostic);
        }
        throw new CompilationError("Could not compile project");
    }

где я даю путь и нахожу там все файлы.java, добавляя их в список и пытаясь скомпилировать все одновременно.

1 ответ

javaDoc был немного полезен: https://docs.oracle.com/javase/7/docs/api/javax/tools/JavaCompiler.html

в основном это:

JavaCompiler.CompilationTask getTask (Записывающее устройство, JavaFileManager fileManager, DiagnosticListener DiagnosticListener, Итерируемые параметры, Итерируемые классы, Итерируемые объекты компиляции)

Параметры:

  • out - Writer для дополнительного вывода из компилятора; используйте System.err, если ноль
  • fileManager - файловый менеджер; если ноль, используйте стандартный файловый менеджер компилятора
  • DiagnosticalListener - диагностический слушатель; если ноль, используйте метод компилятора по умолчанию для сообщения о диагностике
  • классы - имена классов, которые будут обработаны обработкой аннотации, нуль означает отсутствие имен классов
  • options - параметры компилятора, null означает отсутствие параметров
  • compilationUnits - единицы компиляции для компиляции, ноль означает отсутствие единиц компиляции

так.....

Я открыл проект со следующим

package compileTest1;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


public class MyCompiler {

private File classesDir;
private File sourceDir;

public void loadClassesFromCompiledDirectory() throws Exception {
    new URLClassLoader(new URL[]{classesDir.toURI().toURL()});
}

public void compile() throws Exception {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, Locale.getDefault(), null);
    List<JavaFileObject> javaObjects = scanRecursivelyForJavaObjects(sourceDir, fileManager);

    if (javaObjects.size() == 0) {
        throw new Exception("There are no source files to compile in " + sourceDir.getAbsolutePath());
    }
    String[] compileOptions = new String[]{"-d", classesDir.getAbsolutePath()} ;
    Iterable<String> compilationOptions = Arrays.asList(compileOptions);

    CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostics, compilationOptions, null, javaObjects) ;

    if (!compilerTask.call()) {
        for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
            System.err.format("Error on line %d in %s", diagnostic.getLineNumber(), diagnostic);
        }
        throw new Exception("Could not compile project");
    }
}

private List<JavaFileObject> scanRecursivelyForJavaObjects(File dir, StandardJavaFileManager fileManager) {
    List<JavaFileObject> javaObjects = new LinkedList<JavaFileObject>();
    File[] files = dir.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            javaObjects.addAll(scanRecursivelyForJavaObjects(file, fileManager));
        }
        else if (file.isFile() && file.getName().toLowerCase().endsWith(".java")) {
            javaObjects.add(readJavaObject(file, fileManager));
        }
    }
    return javaObjects;
}


private JavaFileObject readJavaObject(File file, StandardJavaFileManager fileManager) {
    Iterable<? extends JavaFileObject> javaFileObjects = fileManager.getJavaFileObjects(file);
    Iterator<? extends JavaFileObject> it = javaFileObjects.iterator();
    if (it.hasNext()) {
        return it.next();
    }
    throw new RuntimeException("Could not load " + file.getAbsolutePath() + " java file object");
}

public File getClassesDir() {
    return classesDir;
}

public void setClassesDir(File classesDir) {
    this.classesDir = classesDir;
}

public File getSourceDir() {
    return sourceDir;
}

public void setSourceDir(File sourceDir) {
    this.sourceDir = sourceDir;
}
}

взял из https://github.com/ishubin/blogix/blob/master/src/main/java/net/mindengine/blogix/compiler/BlogixCompiler.java

Основным методом является:

public static void main(String[] args) {
    MyCompiler compiler = new MyCompiler();
    compiler.setClassesDir(new File(".")); 
    compiler.setSourceDir(new File("C:\\Users\\...\\workspace\\compileTest\\src\\objectA"));
    try {
        compiler.compile();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

ObjectA получил ObjectB в своем c'tor, поэтому мы знаем, что A зависит от B,чтобы быть уверенным, что я попытался выполнить ObjectA с помощью javac в cmd и получил ошибки

ошибки, которые я получил в cmd: img1

Структура проекта: img2

еще одна вещь, я установил classesDir в файл с путем "." поэтому файл.class скомпилированных java-файлов будет храниться в папке bin проекта.

Работа просто найти также, когда файлы.java находятся в двух разных пакетах: img3

единственное изменение, которое я сделал, было в значении classesDir -> "... \compileTest\bin"

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