2010-01-25 30 views
7

Vì vậy, gần đây tôi đã học về JavaCompiler API mới có sẵn trong JDK 1.6. Điều này làm cho nó rất đơn giản để biên dịch một String đến một .class tập tin trực tiếp từ mã chạy:JavaCompiler từ JDK 1.6: cách viết byte lớp trực tiếp vào mảng 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(); 

Bạn có thể lấy các nguồn để JavaSourceFromString từ Javadoc.

Thao tác này sẽ rất dễ dàng biên soạn sourceCode thành Foo.class trong thư mục làm việc hiện tại.

Câu hỏi của tôi là: là nó có thể biên dịch thẳng vào một mảng byte[], và tránh sự hỗn độn đối phó với File I/O hoàn toàn?

Trả lời

2

Có thể bạn có thể tạo javax.tools.JavaFileManager lớp triển khai của riêng mình, nơi bạn sẽ trả lại việc triển khai javax.tools.FileObject của riêng bạn, sau đó ghi nó ra bộ nhớ thay cho đĩa. Vì vậy, đối với lớp con của bạn của phương thức javax.tools.FileObjectWriter openWriter() throws IOException, bạn sẽ trả lại java.io.StringWriter. Tất cả các phương pháp nên được chuyển đổi thành các đối tác String của chúng.

2

Lý do không có API chuẩn để ghi bytecode vào mảng byte là việc biên dịch một tệp nguồn Java đơn lẻ có thể dẫn đến nhiều tệp bytecode. Ví dụ: bất kỳ tệp nguồn nào có các lớp lồng nhau/bên trong/ẩn danh sẽ dẫn đến nhiều tệp bytecode.

Nếu bạn cuộn JavaFileManager của riêng mình, bạn sẽ cần xử lý tình huống này.

2

Ứng dụng demo được vận chuyển với API JSR 199 có một ví dụ biên dịch từ chuỗi (trong đó thực sự đang sử dụng một số MemoryFileManager). Có thể có một cái nhìn vào nó here hoặc here (những mẫu này là một chút lỗi thời mặc dù, họ sẽ yêu cầu thay đổi nhỏ). Cũng có thể kiểm tra bài viết How to compile on the fly? trên Java.net.

PS: Tôi không xem xét tất cả chi tiết, nhưng tôi không nghĩ rằng nó xử lý các trường hợp được đề cập bởi Stephen C.