2011-10-05 57 views
27

Tôi biết rằng các tính năng thời gian chạy của Java 7 không có sẵn với Java 6 nhưng kể từ không có mã byte mới nào được thêm mã byte mới invokedynamic chỉ phù hợp với các ngôn ngữ không phải Java , Tôi đã tự hỏi sẽ khó khăn như thế nào khi chuyển đổi mã nguồn Java 7 (tuyên bố mới switch, toán tử kim cương) thành thuần Java 6 (nghĩa là có thể bắt đầu chuyển đổi nguồn sang Java 7 mà không mất khả năng tương thích Java 6).Biên dịch Java 7 sang Java 6

Mọi con trỏ?

+3

Tôi tò mò muốn biết động cơ. Chỉ là một mối quan tâm học tập? –

+0

Một bytecode mới đã được thêm vào trong Java 7: 'invokedynamic' (trình biên dịch Java sẽ không tạo ra nó khi bạn biên dịch mã nguồn Java). – Jesper

+0

Tôi nghĩ rằng hỗ trợ động cơ gọi là có nghĩa là thêm mã byte mới? – SteveD

Trả lời

6

Đánh dấu một đầu ra tập tin .class bằng Java 7 javac với phiên bản 1.6.0 (tức là 0x32)

 
printf "\x00\x00\x00\x32" |dd of=Example.class seek=4 bs=1 count=4 conv=notrunc 

(theo http://en.wikipedia.org/wiki/Java_class_file#General_layout)

Nếu bạn đặt đó (sử dụng $ 1 cho tên tập tin) vào j6patch bạn có thể làm tất cả các file lớp với:

 
find . -name \*.class |xargs -I {} ./j6patch {} 

tôi đã sử dụng này trên một (~ 4,8 MB jar) cơ sở mã lớn và thậm chí sử dụng RetroTranslator trên java 6 jar để các tính năng ngôn ngữ Java 7 có thể được sử dụng trên một ứng dụng chạy trong Java 5. Ngoài ra trình biên dịch Java 7 (javac) thực hiện rất nhiều tối ưu hóa bổ sung (ví dụ: phân tích thoát) cải thiện đáng kể hiệu suất.

Sử dụng RetroTranslator với -verify -target 1.5 và JRE 1,6 thời gian chạy chum cho phép xác minh rằng không có tính năng thời gian chạy Java 7 nào được sử dụng.

+0

Bạn đã thử điều đó chưa? Làm thế nào nó đã làm việc trong thực tế? –

+0

Có, trên một codebase lớn (~ 4.8 MB jar) và thậm chí sử dụng RetroTranslator trên java 6 jar để các tính năng ngôn ngữ Java 7 có thể được sử dụng trên một ứng dụng chạy trong Java 5. Ngoài ra trình biên dịch Java 7 (javac) cũng có rất nhiều opimizations bổ sung (ví dụ như phân tích thoát) cải thiện đáng kể hiệu suất. – karmakaze

+2

Ngoài ra, bạn có thể sử dụng RetroTranslator với các bình thời gian chạy -verify -target 1.5 và JRE 1.6 để xác minh rằng không có thời gian chạy Java 7 nào được sử dụng. – karmakaze

11

Theo như tôi biết, hiện tại không có giải pháp cho vấn đề này. Đặt cược tốt nhất sẽ là mở rộng retrotranslator để xử lý các cấu trúc Java 1.7. Các nhà điều hành kim cương nên rất dễ dàng, vì nó không đòi hỏi phải sửa đổi bytecode cả.

Tuyên bố "không có mã byte mới đã được thêm" không chính xác: Có mã byte gọi động mới và quan trọng hơn là có một số trường hợp mã byte được tạo sẽ không hợp lệ cho 1,6 JRE, do đó trình quay lại sẽ phải khắc phục điều đó.

+0

Bạn có thể đưa ra một ví dụ nơi mã byte được tạo ra không hợp lệ với máy ảo Java 6 không? 'invokedynamic' không được sử dụng bởi Java, nó chỉ dành cho các ngôn ngữ động như Groovy hoặc Jython (và cả hai đều có thể sống mà không có nó). –

+2

Bạn sẽ phải đi qua Phụ lục 3 của đặc tả Java SE 7 (http://download.oracle.com/otndocs/jcp/java_se-7-final-eval-spec/index.html), nó chứa một tệp PDF với sự khác biệt liên quan đến Java SE 6. Ở một cái nhìn lướt qua, dường như tất cả các thay đổi phá vỡ (ví dụ như các kiểu pool không đổi mới) có liên quan đến sự hỗ trợ động lực. –

+0

Vấn đề là số phiên bản mã byte được chứa trong tệp lớp, do đó, một JVM 1.6 sẽ không tải tệp 1,7 lớp. –

3

Bạn đúng là hướng dẫn gọi động không được Java sử dụng, tuy nhiên có một số thay đổi liên quan khác có thể được sử dụng trong Java. Invoked dynamic dựa vào một 'Cơ chế liên kết động - Phương pháp xử lý phương thức' mà có một số thay đổi đối với hướng dẫn invokevirtual. Bạn có thể tìm thêm chi tiết trong this article trong phần 'Cơ chế liên kết động mới: Phương thức xử lý'.

Xử lý phương pháp cũng cung cấp giải pháp thay thế nhanh hơn, và do đó rất hữu ích trong Java. Việc chuyển đổi mã bằng cách sử dụng các phương thức xử lý đối với Java 6 sẽ không thể thực hiện được vì tính năng này dựa trên máy ảo Java 7.

+0

Đọc của bài báo được tham chiếu dường như chỉ ra rằng 'Cơ chế liên kết động' mới được hỗ trợ không phải bất kỳ bytecode mới nào mà là hỗ trợ thời gian chạy java.dyn (java.lang.invoke.MethodHandle). Tất nhiên mã byte phải được kiểm tra để xem điều này không được tham chiếu cho khả năng tương thích Java 6. – karmakaze

2

Có thể là một số công việc nhưng hãy thử cách này:

Thêm trình biên dịch Java của Eclipse vào đường dẫn lớp của bạn. Trong plugin org.eclipse.jdt.core (tìm kiếm org.eclipse.jdt.core_*.jar trong thư mục plugins).

JAR này chứa trình biên dịch và trình phân tích cú pháp. Bạn có thể tự gọi trình phân tích cú pháp và sau đó use the ASTVisitor để di chuyển cây phân tích cú pháp.

Sau đó, bạn có thể sửa đổi cây và tạo mã nguồn mới từ điều này mà bạn có thể biên dịch như bình thường.

Thậm chí có thể có khả năng "tiền xử lý" cây AST trước khi trình biên dịch tạo mã byte; điều này sẽ giúp bạn tiết kiệm "ghi nguồn trở lại đĩa và biên dịch chúng từ đó" bước.

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