2009-04-08 6 views
11

Tôi đang viết một chương trình máy chủ được sử dụng để chạy thử nghiệm đơn vị của một API (hiển thị nhiều thông tin và cung cấp truy cập web để kiểm soát /giám sát toàn bộ điều) ...Tôi có thể tự động tải và tải lại (các phiên bản khác của cùng một) JAR không?

API này là được biết đến với máy chủ trong thời gian biên dịch và được cung cấp như một JAR.

Để có thể so sánh giữa các kết quả thử nghiệm đơn vị của phiên bản khác nhau của API (không khởi động lại máy chủ), Tôi muốn để có thể dỡ bỏ các phiên bản 'hiện tại' của API, và tải lại một cái mới hơn (hoặc cái cũ hơn).

Tôi không muốn sử dụng URLClassLoader và gọi mỗi phương pháp duy nhất bởi tên
(sử dụng getDeclaredMethod("someMethod")),
vì máy chủ yếu phụ thuộc vào các API và nó sẽ là phức tạp để 'bọc' mỗi gọi phương thức theo cách bẩn thỉu.

Tôi đã suy nghĩ: Vì tất cả các giao diện của tất cả phiên bản của JAR là cùng, không thể tôi nó bằng cách nào đó tải lại một phiên bản khác của JAR (mà không có bằng-name-invokation?).

Lưu ý: Tôi đang sử dụng Java SE (6) và Java EE mới nhất (5).

Nếu bạn nghĩ, những gì tôi đang cố gắng đạt được là không thể, vui lòng đề xuất 'giải pháp' hoặc một khái niệm khác.

+0

Xem thêm: http://stackoverflow.com/questions/148681/unloading-classes-in-java – sleske

Trả lời

7

Tôi nghĩ rằng nếu bạn nạp một lớp sử dụng

Class.forName(clsname, init, classloader); 

(Javadoc đây), bạn sẽ có được một thể hiện của lớp được cung cấp bởi classloader nhất định. Mọi thứ được nạp vì lớp đó cũng sẽ được tải thông qua cùng một trình nạp lớp.

Miễn là bạn rất cẩn thận với các đối tượng được khởi tạo từ điểm này (để cho phép GC), bạn sẽ có thể tải lại các phiên bản khác nhau. Tôi đã làm điều này một lần trước đây với Java 1.3, nó đã mất rất nhiều gỡ lỗi, nhưng cuối cùng tôi đã có một "bootstrap" ứng dụng mà nạp một lớp học Runnable theo tên và đã có thể "khởi động lại mềm" bằng cách instantiating một bộ nạp lớp mới chống lại một URL khác và đi lại.

-2

Có thể là không. Trình nạp lớp Java không thực sự hỗ trợ tải thời gian chạy; thậm chí các trình nạp lớp có sẵn là các hacks sử dụng một đối tượng proxy.

1

OSGi là một khuôn khổ cho phép bạn thực hiện. JSR 277 the Java Module System cũng được thiết kế để thực hiện điều đó (tôi nghĩ). Tôi đã không theo sau cuộc tranh luận OSGi -vs- JSR 277, vì vậy tôi không biết f họ đang cố gắng marge chúng ở tất cả.

Bạn có thể tự cuộn bằng trình tải lớp, nhưng sẽ ít "vui nhộn" hơn.

0

Có. Tôi đã nhìn thấy nó được thực hiện tại một hội nghị NFJS.Đó là cách những thứ như các thùng chứa web hỗ trợ triển khai các ứng dụng và liên quan đến việc tận dụng phạm vi của các trình nạp lớp. Để thực hiện nó, bạn cần phải tạo một trình nạp lớp mới và sử dụng nó để tải thư viện được đề cập .. sau đó ném bộ nạp đi (hoặc không) và tạo trình nạp khác khi bạn muốn tải lại. Bạn cũng có thể phải ghi đè hành vi của trình nạp lớp (tôi nhớ một số thứ về trình nạp lớp nhận các lớp thông qua cha mẹ đầu tiên theo mặc định.) Ngoài ra, tôi nhớ một cảnh báo rằng các đối tượng được tạo bởi các trình nạp lớp khác nhau là không tương thích (không phải của cùng loại) với nhau ngay cả khi tệp .class giống hệt nhau.

Chủ yếu là deep magic cho tôi. ;-)

4

Bạn có thể sửa đổi chương trình classpath theo cách lập trình để phản ánh các thay đổi JAR của mình. Dưới đây là làm thế nào tôi sẽ làm điều đó:

URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 
     Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); 
     m.setAccessible(true); 
     m.invoke(urlClassLoader, jarFile.toURI().toURL()); 
     String cp = System.getProperty("java.class.path"); 
     if (cp != null) { 
      cp += File.pathSeparatorChar + jarFile.getCanonicalPath(); 
     } else { 
      cp = jarFile.toURI().getPath(); 
     } 
     System.setProperty("java.class.path", cp); 

nơi jarFile là phiên bản của jar bạn muốn sử dụng/ghi đè lên.

3

Bạn có thể sử dụng gói mã nguồn mở: JclLoader giúp tải các phiên bản khác nhau của cùng một lọ. Đây cũng là một nhu cầu trong một trong các hệ thống của chúng tôi để làm thử nghiệm.

Link: http://sourceforge.net/projects/jcloader/

+0

tôi sử dụng nó. Nó hoạt động, một lưu ý - nếu bạn muốn tải lại lớp, bạn nên làm điều đó với trường hợp JarClassLoader khác nhau, nếu bạn thử nó với cùng một lỗi classloader sẽ được ném, chỉ cần tạo một cái khác. – odiszapc

+0

Tôi đã thử nhiều giải pháp ... Tôi có thể xác nhận, đây là giải pháp đơn giản nhất mà tôi có thể tìm thấy để tải lớp động. Điều này thực sự nên là câu trả lời được chấp nhận. – taylorcressy