Thao tác với DLL bằng Java
22/02/2012 - Xem: 3377
Môi trường triển khai
- JDK 1.6_0.16
- Eclipse
- JUnit
- VC++ Express 2010
Mục đích
File Calc.dll được tạo ra và bao gồm hai phương thức với đặc tả như sau
- int add (int a, int b)
- int substract (int a, int b)
Viết đoạn mã Java sử dụng sẵn hai phương thức đã được viết bằng VC++ và được dịch ra file dll.
Quy định chung
Một số tên gọi được giữ nguyên tiếng Anh thay vì viết tiếng Việt.
Thuật ngữ
Java = nền tảng Java & ngôn ngữ lập trình Java
C/C++ = ngôn ngữ lập trình C/C++
service(s) (trong tài liệu này) = các hàm viết bằng ngôn ngữ lập trình khác java
Intermediate platform = lớp trung gian giao tiếp giữa ứng dụng viết bằng Java & ứng dụng viết bằng các ngôn ngữ lập trình khác.
JNI (Java Native Interface) = lớp giao tiếp giúp JVM gọi các services được viết bằng ngôn ngữ lập trình khác.
JNA (Java Native Access) = truy cập vào các thư viện native mà không phải viết code JNI
Tổng quát
Bản thân ngôn ngữ Java không tự gọi được các hàm viết bằng các ngôn ngữ lập trình khác. Vì thế, trong Java Platform có cung cấp Java Native Interface (JNI) cho phép tích hợp chương trình viết bằng Java với những services được tạo ra trên nền tảng khác. JNI định nghĩa các chuẩn đặt tên và cách thức gọi hàm tích hợp trong JVM.
Kiến trúc
JNI architecture
Các bước gọi hàm trong file dll dịch từ C++
- viết code java, bao gồm tên hàm & các tham số.
- biên dịch file java = javac
- tạo file header (*.h) = javah -jni
- viết code C++ để thực thi, include file header tạo ra từ code java trên.
- build mã nguồn C++ ra file dll
- load file dll vào mã nguồn java và chạy.
Calling JNI
Trên là trường hợp lý tưởng khi có đủ cả mã nguồn & công cụ thực thi của các file dll. Tuy nhiên, trường hợp không thể có mã nguồn của dll mà chỉ có đặc tả kỹ thuật của các phương thức cần dùng thì công việc lại vất vả hơn chút. Đó là phải tự viết code C++ để đọc các
phương thức từ dll, tức là tự viết lớp intermediate platform ở trên để làm việc kết nối Java & dll (lập trình bằng C/C++)
Giải pháp khác
Có nhiều thư viện giải quyết việc giao tiếp giữa mã nguồn Java & dll (C/C++), JNA là một trong số đó với đặc điểm dễ dùng & miễn phí. Những thông tin cần thiết bao gồm
- download jna.jar
- import vào dự án (giả sử dùng eclipse)
- load dll lên và sử dụng, cần có đặc tả kỹ thuật của các phương thức (tên, tham số, kiểu dữ liệu nên chính xác)
Làm bằng JNI đơn thuần
1. Viết file Calc.java
public native int add(int a, int b);public static void main(String[] args) {Calculator cal = new Calculator();int sum = cal.add(1,2);}
2. Biên dịch file Calc.java
javac Calc.java
3. Tạo ra file header (*.h) để sử dụng trong mã nguồn C++
javah -jni Calc
File Calc.h thu được có nội dung như dưới
#include/* Header for class Calculator */#ifndef _Included_Calculator#define _Included_Calculator#ifdef __cplusplusextern “C” {#endif/** Class: Calculator* Method: add* Signature: (II)I*/JNIEXPORT jint JNICALL Java_Calculator_add(JNIEnv *, jobject, jint, jint);#ifdef __cplusplus} #endif#endif
Trong đó
- JNIEXPORT jint JNICALL là quy tắc viết giao tiếp của JNI
- jint là kiểu native của int
4. Viết mã nguồn C++
- #include file Calc.h header như trên
- viết mã nguồn chính
#include#include “Calc.h”JNIEXPORT jint JNICALLJava_Calc_add(JNIEnv *env, jobject obj, jint a, jint b){return a + b;}
5. Dịch mã nguồn C++ thành file dll. Trường hợp đã có sẵn file *.dll, từ bước (1) – (4) thì viết các phương thức theo như đặc tả kỹ thuật của file *.dll nhận được. Tại bước (4), viết các hàm C++ để gọi đến hàm C++ trong file *.dll đó.
6. Sử dụng file dll vừa dịch trong mã nguồn Java.
Cách này đòi hỏi người làm vừa phải làm với Java, vừa phải làm với C/C++. Nếu các lập trình viên Java ngại làm việc với C/C++ thì thư viện Java Native Access (JNA) là một trong số những lựa chọn tốt để sử dụng. Lợi ích của nó là có thể tránh cho lập trình viên can thiệp hoặc viết mới mã nguồn C/C++, tức là bỏ qua bước (3), (4) ở trên.
Sử dụng JNA
1. Vào website https://jna.dev.java.net/ và download thư viện cần thiết
- jna.jar
- platform.jar (không bắt buộc)
2. Import thư viện jna.jar và viết mã nguồn java
○ file Calc.javapackage Calculator;import com.sun.jna.*;public interface Calc extends Library {int add(int a, int b);}○ file Cal.javapackage Calculator;import com.sun.jna.*;public class Cal {static Calc init() {Calc c = (Calc) Native.loadLibrary(“Path/to/Calc”,Calc.class);return c;} public static void main (String [] args) {System.out.println(add(1, 2));} public static int add(int a, int b) {return init().add(a, b);} public static int substract(int a, int b) {return init().substract(a, b);}}
Có thể gộp 2 files trên thành 1, tuy nhiên, việc viết interface mô tả các phương thức gọi các hàm native làm cho code dễ quản lý hơn.
Vậy là chạy roài.
Hai lỗi thường gặp
- java.lang.UnsatisfiedLinkError: Error looking up function ‘’: The specified procedure could not be found. -> kiểm tra lại chính xác tên hàm, kiểu dữ liệu (native) & tham số.
- java.lang.UnsatisfiedLinkError: Unable to load library ‘C:\Users\nguyen.duc.hoang\Documents\Visual Studio 2010\Projects\Calc\Debug\’: The specified module could not be found -> kiểm tra lại tên file dll, đường dẫn đến file, phiên bản build & nền tảng lập trình của file đó.
Hạn chế của JNA
Tốc độ chậm hơn JNI native khoảng 10 lần (nghe nói thế), tuy nhiên vẫn có những cách để tăng thêm hiệu suất làm việc (chưa thử). Việc mapping giữa library & functions giữa JNA và native code cũng gặp vấn đề về
- tính chính xác
- các kiểu dữ liệu.
Những yêu cầu của file *.dll dùng được
- có mô tả chính xác tên hàm, giá trị trả về & tham số truyền vào.
- có mô tả chi tiết các kiểu dữ liệu, hằng số
- ngoài ra, file *.dll nên được viết (nếu = C/C++) đúng chuẩn xuất ra dll chứ không phải dll gắn trực tiếp & cố định vào một ứng dụng cụ thể (vì lý do ràng buộc giữ các thư viện - nếu có).
- có thể xem được tên hàm của file *.dll bằng các chương trình phân tích dll đơn giản.
Tham khảo thêm
- website chính của dự án JNA https://jna.dev.java.net/
- Sheng Liang The Java™ Native Interface (Programmer’s Guide and Specification)
(i-php.net)
Tin sưu tầm:
Các tin khác cùng chuyên mục
- Kỹ thuật lập trình HTML/CSS mới nhất 2020 - 04
- Funny web2.0
- Giải thử vài câu đề thi tốt nghiệp ptth môn toán
- MỘT NGÀY PHẢI KHÁC MỌI NGÀY
- Level 1 - Lập trình hướng đối tượng (P2)
- Level 1 - Lập trình hướng đối tượng (P1)
- PHP 5.3, Phần 3: Không gian tên
- PHP 5.3, Phần 2: Bao đóng và các hàm lambda
- PHP 5.3, Phần 1: Các thay đổi về giao diện đối tượng
- Tăng tốc độ xử lý CSDL MySQL
Liên kết
Tin được quan tâm nhất
- Ant Group của Jack Ma hé lộ bước đi đầu tiên...
- Ô tô giao hàng tự lái sẽ bắt đầu hoạt...
- Clip cô giáo phạt học sinh tự ném vỡ...
- Tiền điện tử lớn thứ ba thế giới Ripple...
- Joe Biden kêu gọi hiện đại hóa hệ thống...
- Viettel khai trương nền tảng Hồ sơ sức khỏe...
- Các hãng di động nên ngừng cãi nhau về việc...
- Công nghệ AI của Alibaba và Tân Hoa Xã: Đối...
- Một năm đáng thất vọng của YouTube trên toàn...
- EVN lần đầu diễn tập an toàn thông tin mạng...
- Đây là chiếc iPhone được mua nhiều nhất...
- Bộ Tài chính ra quy chế mới về quản lý, sử...
- Cập nhật nhãn mới giúp người tiêu dùng...
- Kiếm tiền từ 5G: Thách thức lớn nhất của...
- "Hô biến" iPhone thành cục đá: Có thể bị...
- Phí trước bạ ô tô không gia hạn giảm, sẽ...
- Tại sao Apple chế tạo ô tô?
- Viettel cung cấp dịch vụ 5G tại thành phố...
- Đội KingTigerPrawn của Hàn Quốc giành giải...
- Thứ trưởng Phan Tâm: “Triển khai hạ tầng 5G...
- Nhiều mẫu iPhone chính hãng đang khan hàng tại...
- Mỹ quy định drone cần có ID, trang bị đèn ban...
- Trung Quốc điều tra Alibaba: Bài học cho Jack Ma...
- Chuyên gia dự báo 5 xu hướng tấn công mạng...
- Apple MagSafe vẫn còn rất nửa vời
- Các tỉnh cuối cùng đã ngừng phát sóng...
- 55/63 tỉnh thành sử dụng Zalo trong cải cách...
- Headline: CR7: “Mong muốn của tôi là luôn...
- Samsung dự kiến xuất xưởng dưới 300 triệu...
- Vì sao Trung Quốc ‘sờ gáy’ Alibaba?
- Những smartphone được người Việt mua nhiều...
- Vì sao mua hàng ở sàn TMĐT Mỹ không cần...
- Đằng sau bức ảnh động viên Đà Nẵng chiến...
- VNPT cung cấp MyTV Box 2020 - Tính năng nâng cấp...
- Clip hành động ghê tởm của shipper trước khi...
- Các đội thi chung kết WhiteHat Grand Prix 6 phát...