2012-05-26 26 views
10

Tôi muốn biên dịch mã nguồn mà không cần phụ thuộc vào máy.
Ví dụ: File A.java:
JavaCompiler với ClassLoader tùy chỉnh và FileManager

import some.pkg.B; 
public class A extends B {...} 

tôi không có nguồn B hiện tại, tôi muốn treo hoặc JavaFileManager hoặc một ClassLoader tùy chỉnh để có được những biểu tượng trong câu hỏi (gói 'một số. gói 'và lớp B) và sau đó sử dụng dịch vụ tôi có để truy xuất chuỗi nguồn.

Mã biên soạn: (inputFiles có A.java)

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
CustomClassLoader classLoader = new CustomClassLoader(); 
StandardJavaFileManager standardfileManager = compiler.getStandardFileManager(this, null, null); 
JavaFileManager fileManager = new CustomFileManager(standardfileManager, output, classLoader); 
CompilationTask task = compiler.getTask(null, fileManager, this, null, null, inputFiles); 
boolean result = task.call(); 

Hooks trên JavaFileManager (getFileForInput ..) và trên classloader của tôi (findClass, loadClass ..) không kích hoạt khi biên soạn và tôi nhận thông báo lỗi:

A.java:#: package some.pkg does not exist 
A.java:#: cannot find symbol 
symbol: class B 

EDIT

Sau khi chơi đùa với các API, đi qua JavaCompiler (phiên bản cũ) s ource và đọc Compilation Overview Tôi vẫn không thể tìm thấy một móc API tôi có thể sử dụng để cung cấp cho tôi Biểu tượng từ các cây cú pháp. Dường như API cần lấy tất cả các tài nguyên dựa trên tên gói như được gợi ý bởi kschneid.
Một cách giải quyết khác mà tôi nghĩ đến là chạy JavaCompiler và phân tích các thông báo lỗi cho các ký hiệu bị thiếu. Bằng cách đó tôi sẽ biết những biểu tượng nào là cần thiết, lấy chúng và biên dịch lại.
Bất kỳ cách giải quyết/giải pháp nào khác?

+0

gì JDK phiên bản/biên dịch và nền tảng mà bạn đang sử dụng? – matts

+0

JavaCompiler (javac), JDK 1.6.30 x64 trên Windows. –

+0

Tôi không hoàn toàn chắc chắn. Nhưng, tôi cảm thấy như thể những gì bạn đang cố gắng làm là tải lớp động. Bạn không thể sử dụng 'Class.forname()' để nạp lớp vào thời gian chạy. Hãy sửa tôi nếu tôi hiểu lầm. – Ankit

Trả lời

4

(tôi giả sử rằng bạn đang không thực sự sử dụng một tên gói "gói" từ đó sẽ chỉ là bất hợp pháp ...)

tùy chỉnh của bạn JavaFileManager nên được nhận phương pháp list nó gọi. Hy vọng rằng ký hiệu này có ý nghĩa, nhưng sự kết hợp của args để phương pháp đó sẽ giống như sau:

[PLATFORM_CLASS_PATH, some, [CLASS], false] 
[CLASS_PATH, some, [SOURCE, CLASS], false] 
[PLATFORM_CLASS_PATH, some.pkg, [CLASS], false] 
[CLASS_PATH, some.pkg, [SOURCE, CLASS], false] 

Tôi không chắc chắn khó khăn như thế nào nó sẽ được cho môi trường cụ thể của bạn để tạo ra các Iterable<JavaFileObject> trường hợp thích hợp, nhưng tôi nghĩ đó là những gì sẽ được yêu cầu ...

+0

Cảm ơn cho các gói lưu ý, tôi đã sửa đổi các câu hỏi. –

+0

Tôi đã bỏ lỡ chức năng này, cuộc gọi tốt.Tuy nhiên, đó là một đường dẫn tốt tuy nhiên tôi không muốn xây dựng JavaFileObject cho tất cả các lớp trong gói, chỉ những cái được sử dụng trong việc biên dịch thực sự của tệp Java mà tôi đang cố gắng biên dịch. Có cách nào để có được tên lớp thực tế và không chỉ các gói? –

+0

Đây là một triển khai tuyệt vời cho việc này. http://atamur.blogspot.kr/2009/10/using-built-in-javacompiler-with-custom.html – zeodtr

1

Tôi đã tìm thấy rằng một cách tốt đẹp để móc trong các lớp học tại thời gian biên dịch là với Groovy AST Transformation. Bạn có thể có một cái nhìn vào những gì có thể được thực hiện here

Đó không phải là java đồng bằng cũ mặc dù, nhưng nó có thể là một công cụ hữu ích để biết

Các vấn đề liên quan