동적 컴파일을 위한 출력 경로 지정
-
19-09-2019 - |
문제
Java 6의 동적 컴파일이 완벽하게 작동합니다.그런데 출력 경로를 변경하고 싶습니다.나는 수많은 일을 시도했지만 아무 소용이 없었습니다.어쨌든 작업 코드는 다음과 같습니다.
String[] filesToCompile = { "testFiles/Something.java" };
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(filesToCompile);
CompilationTask task = compiler.getTask(null, fileManager, null,null, null, compilationUnits);
System.out.println("Good? " + task.call());
그러나 출력은 내가 원하는 것이 아닌 소스 디렉터리로 이동합니다.
나는 그 대답이 다음에 있을 것이라고 생각한다. compiler.getTask
그러나 API는 일부 매개변수가 무엇을 의미하는지에 대해 그다지 명시적이지 않습니다.아니면 아마도 fileManager와 관련된 것일 수도 있습니다.난 노력 했어
fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null);
하지만 다시 말하지만, 추측하는 것은 아마도 좋은 생각이 아닐 것입니다.
감사해요!
편집하다: 나는 다음과 같은 옵션도 사용해 보았습니다. (더 간단한 방법이 있다면 죄송합니다.)
final List<String> optionsList = new ArrayList<String>();
optionsList.add("-d what");
Iterable<String> options = new Iterable<String>() {
public Iterator<String> iterator() {
return optionsList.iterator();
}
};
그런 다음 getTask에 옵션을 전달했지만 오류 메시지는 "잘못된 플래그"입니다.
해결책
첫 번째 게시물의 코드는 작동하지만 다음 오류가 발생합니다.
java.lang.IllegalArgumentException: invalid flag: -d folder
지나가는 것입니다 "-d folder"
파서가 하나의 옵션을 구문 분석한다고 생각하게 만듭니다. 옵션을 분리해야합니다 "-d", "folder"
.
작업 예제는 다음과 같습니다.
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sjfm = javaCompiler.getStandardFileManager(null, null, null);
String[] options = new String[] { "-d", "output" };
File[] javaFiles = new File[] { new File("src/gima/apps/flip/TestClass.java") };
CompilationTask compilationTask = javaCompiler.getTask(null, null, null,
Arrays.asList(options),
null,
sjfm.getJavaFileObjects(javaFiles)
);
compilationTask.call();
다른 팁
오늘도 같은 문제에 직면했습니다.
대답 (정규 getTask
`run ) 대신 메소드를 사용하면 FileManager에서 출력 디렉토리를 지정하는 것입니다.
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir));
그리고 그게 다야!!:)
문서가 약간 오해의 소지가 있습니다. 즉, 샘플이 매우 유용할 수 있다는 의미입니다.그러나 결국 그것은 나를 그곳으로 데려갔습니다.
편집하다
실행 중인 샘플은 다음과 같습니다.
// write the test class
File sourceFile = new File("First.java");
FileWriter writer = new FileWriter(sourceFile);
writer.write(
"package load.test;\n" +
"public class First{}"
);
writer.close();
// Get the java compiler for this platform
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
null,
null,
null);
//-- H E R E --//
// Specify where to put the genereted .class files
fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
Arrays.asList(new File("/tmp")));
// Compile the file
compiler
.getTask(null,
fileManager,
null,
null,
null,
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile)))
.call();
fileManager.close();
// delete the file
sourceFile.deleteOnExit();
Java 6 Dynamic Compiler 도구에 대한 경험이 0입니다. 그러나 아무도 대답하지 않았습니다 :)
컴파일 작업이 a FileManager
물체. 표준을 사용하면 소스 디렉토리 트리에서 클래스가 생성됩니다. 당신이 할 수있는 일은 자신의 filemanager 서브 클래스를 재정의하는 것입니다. getFileForOutput
방법. getFileForOutput에 대한 API 설명은 이것이 출력 (= 클래스) 파일이 어디로 가는지에 영향을 미칠 것임을 나타냅니다.
업데이트
파일 관리자를 연결하는 방법
ForwardingjavafileManager, ForwardingFileObject 및 ForwardingJavaFileObject 서브 클래싱은 생성자를 호출하지 않고 컴파일러에서 메소드를 호출하여 생성되므로 표준 파일 관리자의 동작을 재정의하는 데 사용할 수 없습니다. 대신 전달 (또는 위임)을 사용해야합니다. 이 클래스를 사용하면 대부분의 호출이 주어진 파일 관리자 또는 파일 객체로 쉽게 전달하면서 동작을 사용자 정의 할 수 있습니다. 예를 들어, 모든 통화를 javafilemanager.flush () 로그인하는 방법을 고려하십시오.
final Logger logger = ...;
Iterable<? extends JavaFileObject> compilationUnits = ...;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
public void flush() {
logger.entering(StandardJavaFileManager.class.getName(), "flush");
super.flush();
logger.exiting(StandardJavaFileManager.class.getName(), "flush");
}
};
compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
업데이트 2
나는 동적 컴파일을 읽고이를 위해 내 앱을 만들었습니다. 이 코드는 너무 많은 의식이 포함되어 있지만 (예 : 단순화 될 수 있음) 작동합니다!
package yar;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class DynamicCompiler {
JavaCompiler compiler;
public DynamicCompiler() {
this.compiler = ToolProvider.getSystemJavaCompiler();
if (this.compiler == null) {
throw new NullPointerException("Cannot provide system compiler.");
}
}
public void compile() {
this.compiler.run(null, System.out, System.err,
"-d", "testFiles2",
"testFiles/Hello1.java", "testFiles/Hello2.java");
}
/**
* @param args
*/
public static void main(String[] args) {
try {
DynamicCompiler dc = new DynamicCompiler();
dc.compile();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
이 코드를 동적으로 생성 된 Java 파일 목록과 함께 작동하는 방법을 잘 모르겠습니다. 아마 그냥 할거야 compiler.run
각 소스 파일에 대해 별도로.