2010-03-15 16 views
8

Tôi muốn đóng gói một đoạn mã hoàn toàn phải chạy trên Java 1.5. Có một phần của mã nơi chương trình có thể được "nâng cao" nếu VM là một máy ảo 1.6.Java: cách dễ nhất để đóng gói cả mã Java 1.5 và 1.6

Về cơ bản nó là phương pháp này:

private long[] findDeadlockedThreads() { 
    // JDK 1.5 only supports the findMonitorDeadlockedThreads() 
    // method, so you need to comment out the following three lines 
    if (mbean.isSynchronizerUsageSupported()) 
     return mbean.findDeadlockedThreads(); 
    else 
     return mbean.findMonitorDeadlockedThreads(); 
    } 

Điều gì sẽ là cách dễ nhất để có điều này biên dịch trên 1.5 và chưa làm phương pháp 1.6 gọi khi trên 1,6?

Trong quá khứ tôi đã làm một cái gì đó tương tự bằng cách biên dịch một lớp 1.6 duy nhất mà tôi sẽ đóng gói với ứng dụng của mình và nhanh chóng sử dụng ClassLoader khi trên 1.6 (vì 1,6 JVM hoàn toàn hòa trộn 0x32 và 0x31 lớp), nhưng Tôi nghĩ rằng đó là một chút overkill (và một chút đau đớn vì trong quá trình xây dựng, bạn phải xây dựng cả 0x31 và 0x32. Lớp tập tin).

Tôi nên làm cách nào nếu tôi muốn biên dịch phương thức trên trên 1,5? Có thể sử dụng phản chiếu nhưng sau đó như thế nào (tôi không quen thuộc ở tất cả với sự phản ánh)

Lưu ý: nếu bạn tò mò, các phương pháp trên xuất phát từ bài viết này: http://www.javaspecialists.eu/archive/Issue130.html

(nhưng tôi không muốn "bình luận ba dòng" như trong bài viết, tôi muốn điều này biên dịch và chạy trên cả 1.5 và 1.6)

Trả lời

3

Bạn không thể biên dịch nó trên 1.5, nhưng bạn có thể biên dịch trên 1.6 với tùy chọn mục tiêu được đặt thành 1.5 (sẽ tạo ra mã byte cho 1.5) và trong mã sử dụng sự phản chiếu để tìm hiểu xem phương thức có sẵn hay không.

Mã này sẽ tra cứu phương thức: mbean.getClass(). GetMethod ("findDeadlockedThreads", new Class [0]); Vấn đề là, nó ném một NoSuchMethodException nếu phương pháp không có mặt thay vì chỉ trả về null hoặc một cái gì đó tương tự. Điều đó có nghĩa là, bạn cần mã như sau:

try 
{ 
    mbean.getClass().getMethod("findDeadlockedThreads", new Class<?>[0]); 
    return mbean.findDeadlockedThreads(); 
} 
catch(NoSuchMethodException ex) 
{ 
    return mbean.findMonitorDeadlockedThreads(); 
} 

Điều đó không tốt lắm vì nó sử dụng Ngoại lệ để đưa ra quyết định. Điều đó có lẽ không phải là rất nhanh. Một cách khác là sử dụng getMethods thay thế và lặp qua danh sách trả về nếu phương thức của bạn có sẵn. Đó cũng không phải là rất nhanh.

EDIT: Christopher Oezbek đề xuất trong các chú thích để kiểm tra sự tồn tại của phương thức chỉ một lần và lưu kết quả để tránh chi phí cho khối try-catch. Đúng vậy và một giải pháp tốt. Matt b cảnh báo, rằng tùy chọn đích của Java-Compiler không kiểm tra, nếu các lớp và các phương thức được sử dụng có sẵn trong Java 1.5. Đúng vậy (và nếu không nó sẽ không hoạt động, vì bạn muốn biên dịch theo phương pháp 1.6) và điều đó có nghĩa là chương trình cần được kiểm tra cẩn thận theo một máy ảo 1,5-VM để tránh vấn đề này. Cảm ơn ý kiến ​​của bạn cả hai bạn.

+0

@Mnementh: ok nhưng sau đó điều gì sẽ giao diện đang suy nghĩ như ? – SyntaxT3rr0r

+0

Tôi đã chỉnh sửa câu trả lời của mình để bao gồm mã phản chiếu. – Mnementh

+0

@Mnementh: +1 tuyệt vời ... Tôi sẽ cố gắng thiết lập vào chiều nay :) – SyntaxT3rr0r

2

Biên dịch cho 1.5.

Trong phản ánh sử dụng mã của bạn. Bạn có thể lấy đối tượng Method từ giao diện Class; nó có một phương thức gọi để lấy ví dụ mbean của bạn như một tham số. Một cái gì đó như thế này:

Class c = mbean.getClass(); // cũng có thể làm YourClass.class để nhận được điều này

Phương thức m = c.getMethod ("findMonitorDeadLockedThreads"); // hoặc bất kỳ phương pháp khác (tham số để phương pháp này được chỉ định với lớp ... Tham số thứ hai để GetMethod)

m.invoke (MBean) // gọi phương pháp với ví dụ của bạn

Tất nhiên bạn don không phải làm điều này mọi lúc; thiết lập các tham chiếu phương thức trong một hàm tạo và sau đó chỉ cần gọi một hàm thích hợp theo yêu cầu.

+0

@danpaq: đó là một trường hợp đơn giản vì không có tham số nào để chuyển cho phương thức. Vì vậy, từ Mnementh và câu trả lời của bạn tôi mang nó phản ánh là con đường để đi ... Vì vậy, tôi sẽ cố gắng những gì bạn đề nghị ở đây. – SyntaxT3rr0r

+0

@WizardOfOdds: nếu bạn cho rằng đề xuất này có giá trị, vui lòng upvote nó. –

1

Maven cho phép bạn thực hiện việc này khá dễ dàng với hồ sơ. Ý tưởng đằng sau hồ sơ là bạn muốn xây dựng mọi thứ hai phiên bản khác nhau của một cái gì đó dựa trên một số tiêu chí. Trong ví dụ cụ thể này, bạn có thể xác định jdk15 và cấu hình jdk16, chỉ định phiên bản JDK nào cần biên dịch và cho biết bao gồm một bản sao của lớp trong tiểu sử jdk15 và bản sao còn lại trong jdk16.

Để bắt đầu, xem:

http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html

này mô tả làm thế nào để làm phiên bản JDK khác nhau một phần của vấn đề.

Để xử lý phần thứ hai của vấn đề, sử dụng một định nghĩa khác nhau của lớp tùy theo phiên bản JDK, thấy điều này:

Maven - Include Different Files at Build Time

+0

Xin lỗi, hy vọng sẽ giúp ... Tôi không có chút thời gian nào để hiển thị cho bạn toàn bộ kịch bản xây dựng maven. –

+0

Chỉ cần chắc chắn rằng tôi hiểu những gì bạn nói chính xác: Tôi cần đóng gói và gửi một * .jar * duy nhất hoạt động trên cả 1.5 và 1.6 sử dụng 1.6 tính năng khi trên 1.6, tôi có thể làm điều này với các cấu hình Mave không? – SyntaxT3rr0r

+0

@WizardOfOdds: Vâng, đó là những gì tôi đã cố gắng để mô tả trước đây. Tôi đã sửa đổi phản hồi của mình để có các liên kết mô tả cách thực hiện điều này tốt hơn tôi có thể mô tả ở đây. –