2010-09-09 46 views
6

Tôi có thư viện JNI tương tác với một nhóm thư viện của bên thứ ba và có thể có nhiều phiên bản của thư viện của bên thứ ba trên hệ thống. Đối với mỗi phiên bản của thư viện của bên thứ ba, tôi phải biên dịch lại mã JNI vì các lý do so sánh. Ngay bây giờ tôi đối phó với điều này bằng cách tải một DLL với một tên cụ thể, và nếu phiên bản thay đổi tôi thay đổi tên của giao diện JNI DLLs để một trong những chính xác cho phiên bản có tên đúng để có được nạp.Có thể tải các phiên bản khác nhau của cùng một DLL trong Java không?

Tôi muốn có thể tự động tải tệp dll, dựa trên phiên bản người dùng muốn sử dụng. Điều gì sẽ xảy ra nếu tôi gọi System.loadLibrary hai lần trên các tệp DLL có tên khác nhau nhưng có cùng chữ ký phương thức?

System.loadLibrary("JNIv1"); 
// Same code compiled against a different third party version 
System.loadLibrary("JNIv2"); 

Tôi chỉ cần sử dụng một trong các phiên bản tại một thời điểm, vì vậy sẽ ổn nếu phiên bản cũ không còn truy cập được nữa.

Có thể tải hai phiên bản khác nhau của một DLL có cùng chữ ký phương thức mà không cần khởi động lại chương trình không?

Trả lời

3

Có thể và trên thực tế, nó hoàn toàn được hỗ trợ và hoạt động rất tốt.

Tôi đã phải làm điều này trong môi trường sản xuất và trên một mặt trời JVM nó là đá rắn.

Về cơ bản, nếu bạn tải thư viện từ trình nạp lớp khác, thì nó sẽ tải một bản sao thư viện khác. Nó đơn giản như vậy.

Tôi sẽ không khuyên bạn nên làm điều này trừ khi bạn thực sự phải ... nhưng nó hoạt động. Thay vào đó, tùy thuộc vào yêu cầu cụ thể của bạn, bạn chỉ có thể làm cho nó ra khỏi quá trình, và có một giao thức đơn giản (sử dụng jetty/xstream/httpclient, hoặc netty) giữa máy khách và các máy chủ khác nhau, mỗi máy chủ trong đó có một phiên bản dll khác nhau được tải.

Về cơ bản này bao gồm việc bạn viết một classloader

public class MyClassLoader extends URLClassLoader { 

    protected String findLibrary(String libName) { 
     if (libName.equals("mylib.dll")) { 
       return "full/path/to/library"; 
     } 
     else { 
       super.findLibrary(libName); 
     } 
    } 
} 

Sau đó, bạn sắp xếp để tải thực hiện các lớp học của bạn bằng cách sử dụng classloader có liên quan ...

public interface Implementation { 

} 

public class ImplementationLookerUpper { 

    Classloader v1 = new MyClassloader(version1); 
    Classloader v2 = new MyClassloader(version2); 


    public Implementation implementationUsingVersion(Version someversion) { 

      Classloader classloader = pickCorrectClassLoaderForVersion(someVersion); 

      return (Implementation) classloader.loadClass(RealImplementation.class.getName()).newInstance(); 

    } 
} 

Đó là loại điều .... .

0

Tôi không biết chi tiết về cách tải DLL trong cửa sổ hoạt động, nhưng cảm giác ruột của tôi cho tôi biết chắc chắn sẽ không an toàn để có các thư viện chồng chéo được tải cùng một lúc. Nhưng có lẽ nếu bạn lần đầu tiên dỡ hàng đầu tiên, nó có thể được.

Theo tôi thấy, không có cách nào để rõ ràng dỡ thư viện. Nếu bạn nhìn vào java.lang.Classloader.NativeLibrary bạn sẽ thấy rằng một thư viện được unloaded khi trình nạp lớp gây ra nó được nạp được thu gom rác (trong phương thức finalize() của nó). Vì vậy, nếu bạn tải nó trong một trình nạp lớp riêng biệt, và sau đó đợi cho nó được thu gom rác (với một số lệnh gọi ác đến System.gc() để làm điều đó xảy ra nhanh hơn) trước khi tải mới, điều đó có thể hữu ích.

1

Điều này không an toàn và khá lộn xộn khi triển khai. Có thể có các trình nạp lớp khác nhau cho các phiên bản khác nhau của dll. Bạn sẽ phải đảm bảo bộ nạp lớp được thu thập rác để đảm bảo rằng dll đã được tải xuống. (Xem Java JNI - DLL Unloading)

Trước đây, chúng tôi đã giải quyết vấn đề này bằng cách viết một quy trình hòa giải java nhẹ xử lý yêu cầu của người dùng và tạo một tiến trình java con mới với phiên bản dll được yêu cầu. Khi người dùng yêu cầu một phiên bản khác, người hòa giải sẽ tắt con hiện tại và sinh ra một phiên bản mới với một đường dẫn thư viện khác. Cách tiếp cận này hoạt động tốt. Nhược điểm duy nhất là thời gian thực hiện để khởi động các JVM mới, nhưng điều này sẽ chỉ đáng chú ý nếu bạn có nhiều yêu cầu chuyển đổi phiên bản đến rất thường xuyên.

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