2009-10-23 37 views
59

Tôi đã mua thư viện Java của bên thứ ba bao gồm tệp JAR và hai tệp DLL. Tôi đã viết chương trình Java của riêng tôi gọi tệp JAR của bên thứ ba. Bây giờ câu hỏi của tôi là làm thế nào tôi có thể đóng gói tất cả mã của tôi vào một tệp JAR duy nhất bao gồm tất cả mã của tôi và JAR và DLL của bên thứ ba?Làm thế nào để tạo một tệp JAR bao gồm các tệp DLL?

Tôi biết SWT là trường hợp như vậy. Các swt.jar bao gồm các tập tin dll, nhưng tôi không biết làm thế nào để làm điều này và làm thế nào để làm cho nó hoạt động đúng.

Trả lời

68

Chỉ cần gói nó ở bất cứ đâu trong bình. Một điều bạn phải ghi nhớ mặc dù - trước khi bạn có thể sử dụng các tệp DLL bạn cần phải trích xuất các tệp này từ JAR và kết xuất chúng trên đĩa cứng ở một nơi khác, nếu không bạn sẽ không thể tải các hình ảnh này

. Tôi đã làm dự án JNI cho khách hàng, nơi tôi sẽ sử dụng lọ như vậy được đóng gói trong chiến tranh. Tuy nhiên - trước khi chạy bất kỳ phương thức gốc nào, tôi sẽ lấy DLL làm tài nguyên và ghi nó vào đĩa vào thư mục tạm thời. Sau đó, tôi sẽ chạy mã khởi tạo thường xuyên nơi DLL của tôi được đặt ở cùng một vị trí mà tôi vừa ghi DLL vào

Ồ, và chỉ trong trường hợp: không có gì đặc biệt về bao bì dll hoặc bất kỳ tệp nào khác vào trong thùng. Nó giống như đóng gói công cụ vào zip

Dưới đây là một số mã tôi chỉ đào ra

public class Foo { 
private static final String LIB_BIN = "/lib-bin/"; 
private final static Log logger = LogFactory.getLog(ACWrapper.class); 
private final static String ACWRAPPER = "acwrapper"; 
private final static String AAMAPI = "aamapi51"; 
private final static String LIBEAU = "libeay32"; 

static { 
    logger.info("Loading DLL"); 
    try { 
     System.loadLibrary(ACWRAPPER); 
     logger.info("DLL is loaded from memory"); 
    } catch (UnsatisfiedLinkError e) { 
     loadFromJar(); 
    } 
} 

/** 
* When packaged into JAR extracts DLLs, places these into 
*/ 
private static void loadFromJar() { 
    // we need to put both DLLs to temp dir 
    String path = "AC_" + new Date().getTime(); 
    loadLib(path, ACWRAPPER); 
    loadLib(path, AAMAPI); 
    loadLib(path, LIBEAU); 
} 

/** 
* Puts library to temp dir and loads to memory 
*/ 
private static void loadLib(String path, String name) { 
    name = name + ".dll"; 
    try { 
     // have to use a stream 
     InputStream in = ACWrapper.class.getResourceAsStream(LIB_BIN + name); 
     // always write to different location 
     File fileOut = new File(System.getProperty("java.io.tmpdir") + "/" + path + LIB_BIN + name); 
     logger.info("Writing dll to: " + fileOut.getAbsolutePath()); 
     OutputStream out = FileUtils.openOutputStream(fileOut); 
     IOUtils.copy(in, out); 
     in.close(); 
     out.close(); 
     System.load(fileOut.toString()); 
    } catch (Exception e) { 
     throw new ACCoreException("Failed to load required DLL", e); 
    } 
} 
    // blah-blah - more stuff 
} 
+7

Một lời cảnh cáo về cách tiếp cận này - hãy chắc chắn bạn dọn dẹp các tệp tạm thời. Nếu bạn tái sử dụng cùng một đường dẫn mỗi lần, hãy xem xét điều gì sẽ xảy ra nếu nhiều ứng dụng sử dụng JAR của bạn (một ứng dụng sẽ thất bại nếu một ứng dụng khác đã có khóa trên tệp tạm thời). Chỉ cần cẩn thận - đôi khi sẽ dễ dàng triển khai các tệp JAR và DLL một cách riêng biệt. –

+0

Mã có thể được thay đổi để ghi đè lên tập tin đã cài đặt trước đó. Trong trường hợp của tôi - đây là một ứng dụng web sẽ không được tái chế thường xuyên, nếu bạn chỉ sao chép mã "nguyên trạng", bạn sẽ nhận được bản sao của các tệp DLL mỗi khi bạn thực hiện nó – Bostone

+7

Một điều cần lưu ý: Tôi đã sử dụng JNI DLLs phụ thuộc vào các DLL khác. Tôi bao gồm tất cả các DLL bên trong một cái lọ và sử dụng đoạn mã trên để giải nén. Nhưng tôi đã nhận được ngoại lệ java.lang.UnsatisfiedLinkError nói "Không thể tìm thấy thư viện phụ thuộc". Vấn đề là bạn phải gọi System.load() trên các DLL để các DLL phụ thuộc được nạp trước tiên. –

6

Sử dụng http://www.jdotsoft.com/JarClassLoader.php có thể nạp DLL và lọ từ một JAR với làm tổ không giới hạn. Ví dụ, DLL có thể là JAR trong một JAR gốc khác. Tất cả các tệp DLL và các tệp JAR được tải giống như chúng ở trong đường dẫn lớp hoặc đường dẫn thư viện.

+23

Lưu ý cho người khác: Giấy phép là GPLv3, trong đó đáng kể giới hạn khả năng áp dụng. –

+4

Cũng lưu ý: Trình nạp lớp này bỏ tất cả các lọ lồng nhau vào một thư mục tạm thời. Vì vậy, nó hoạt động như câu trả lời đầu tiên. Các lib tự nhiên được giải nén chỉ khi cần thiết. – drzymala

+1

Giấy phép thương mại có sẵn. – drzymala

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