如何使用依赖运行时编译.java?

时间:2017-02-12 02:43:12

标签: java compilation dependencies runtime javacompiler

我有很多.java个文件需要导入另一个.java文件......

这样的事情:

import package.c;

public class A {

  // do whatever that needs package.c
}

但我只有package.c.java

当我尝试编译使用Java编译器或我知道的任何其他内容时,我总是遇到这些错误

  

错误:包< -package->不存在

或类似的东西:

  

错误:找不到符号

我无法编译A.java,因为无法编译的需要C.class导致需要另一个,有人知道我应该怎么做?

.java不需要依赖项时,一切正常,在这些情况下Java编译器运行良好。

也许GetStarted链接可以解决我的问题,但我找不到办法来做到这一点。

[编辑]这是我的编译器代码:

    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 个答案:

答案 0 :(得分:0)

javaDoc有点有用:https://docs.oracle.com/javase/7/docs/api/javax/tools/JavaCompiler.html

主要是这个:

JavaCompiler.CompilationTask getTask(Writer out,                                    JavaFileManager文件管理器,                                    DiagnosticListener diagnosticListener,                                    可重复选项,                                    可以上课,                                    Iterable compilationUnits)

参数:

  • out - 编译器的附加输出的Writer;如果为null
  • ,请使用System.err
  • fileManager - 文件管理器;如果null使用编译器的标准文件管理器
  • diagnosticListener - 诊断侦听器;如果null使用编译器的默认方法来报告诊断
  • classes - 要由注释处理处理的类的名称,null表示没有类名
  • options - 编译器选项,null表示没有选项
  • compilationUnits - 要编译的编译单元,null表示没有编译单元

所以......

我打开了一个带有以下内容的项目

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在他的c中反复使用了ObjectB,所以我们知道A依赖于B, 确定我尝试在cmd中使用javac编译ObjectA并出现错误

我在cmd中遇到的错误: img1

项目的结构: img2

还有一件事,我将classesDir设置为文件路径&#34;。&#34;所以编译好的java文件的.class文件将存储在项目的bin文件夹中。

当.java文件位于两个不同的包中时,

工作也可以找到: img3

我做的唯一改变是在classesDir值为 - &gt; &#34; ... \ compileTest \ bin&#34;