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
}
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. –
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
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. –