문제

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 각 소스 파일에 대해 별도로.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top