2010-01-25 2 views
7

그래서 최근에 JDK 1.6에서 새로운 JavaCompiler API을 사용할 수 있음을 알게되었습니다. 이것은 매우 간단한 실행 코드에서 직접 String.class A와 파일을 컴파일 할 수 있습니다 :JDK 1.6의 JavaCompiler : byte [] 배열에 직접 클래스 바이트를 쓰는 방법?

String className = "Foo"; 
String sourceCode = "..."; 

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

List<JavaSourceFromString> unitsToCompile = new ArrayList<JavaSourceFromString>() 
    {{ 
     add(new JavaSourceFromString(className, sourceCode)); 
    }}; 

StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 
compiler.getTask(null, fileManager, null, null, null, unitsToCompile).call(); 
fileManager.close();  

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
FileInputStream fis = new FileInputStream(className + ".class"); 
IOUtils.copyStream(fis, bos); 

return bos.toByteArray(); 

당신은 Javadoc에서 JavaSourceFromString에 소스를 잡을 수 있습니다.

이것은 현재 작업 디렉토리에서 sourceCode에서 Foo.class까지 매우 편리하게 컴파일합니다.

내 질문은이다 : 그것은이 가능합니다 byte[] 배열로 바로 컴파일하고 모두 I/O File 처리의 어지러움을 방지하기 위해?

답변

2

아마도 javax.tools.FileObject의 고유 한 구현을 반환하는 클래스를 구현하는 javax.tools.JavaFileManager 클래스를 만들면 디스크에 대신 메모리에 쓸 수 있습니다. 따라서 javax.tools.FileObjectWriter openWriter() throws IOException 메서드의 하위 클래스는 java.io.StringWriter을 반환합니다. 모든 방법을 String 사본으로 변환해야합니다.

2

바이트 배열에 바이트 코드를 쓰는 표준 API가없는 이유는 단일 Java 소스 파일을 컴파일하면 여러 개의 바이트 코드 파일이 생성 될 수 있기 때문입니다. 예를 들어 중첩/내부/익명 클래스가있는 모든 소스 파일은 다중 바이트 코드 파일이됩니다.

자신 만의 JavaFileManager를 굴리는 경우이 상황을 처리해야합니다.

2

JSR 199 API와 함께 제공되는 데모 응용 프로그램에는 실제로 메모리가 컴파일되는 문자열 (MemoryFileManager)이 있습니다. 아마도 here 또는 here (이 샘플은 조금 오래된 것입니다. 약간의 변경이 필요할 것입니다.) 또한 Java.net에서 How to compile on the fly? 문서를 확인하십시오.

추신 : 나는 모든 세부 사항을 살펴 보지 않았지만 Stephen C에 언급 된 사례를 처리하지는 않는다고 생각합니다.

관련 문제