Tôi đã tạo mô-đun C++ để xây dựng thành tệp thư viện được chia sẻ và sau đó gọi nó từ Java bằng JNI.Mã dll của tôi hoạt động từ tệp exe, nhưng không tải được từ Java loadLibrary
Tôi có 2 môi trường, Windows và Unix và tôi có chương trình thực thi C++ và chương trình Java mà tôi vừa biên dịch lại cho từng môi trường.
- Khi tôi biên dịch chương trình tester.exe của mình trong Unix và chạy nó bằng phương pháp từ thư viện của tôi (.so) nó hoạt động tốt.
- Khi tôi biên dịch chương trình Java của mình trong Unix và tải thư viện của tôi (.so) với loadLibrary của Java, nó hoạt động tốt.
Khi tôi biên dịch chương trình tester.exe của mình trong Windows và chạy chương trình bằng cách sử dụng phương pháp từ thư viện của tôi (.dll), nó hoạt động tốt. Giống như phiên bản unix .
Khi tôi biên dịch chương trình Java của mình trong Windows và tải thư viện của tôi (.dll) bằng thư viện tải của Java thì không thành công. Nó nói rằng Cố gắng truy cập địa chỉ không hợp lệ.
Tôi không thể hiểu tại sao nó sẽ không hoạt động với Thư viện tải Java khi chạy trong Windows, nhưng nó hoạt động ở mọi nơi khác bằng cùng một mã. Nếu tôi trì hoãn tải một DLL phụ thuộc mà thư viện của tôi sử dụng, thì thư viện của tôi tải trong Java nhưng không hoạt động. Tôi biết có mã cụ thể gây ra vấn đề với Java tải thư viện của tôi, nhưng tôi không thể tìm ra lý do tại sao C + + exe của tôi không có vấn đề với các phương pháp và thư viện tương tự.
Dll của tôi có 1 phương pháp được tiếp xúc gọi 4 phương pháp từ một số thư viện hiện có. Nếu tôi nhận xét 4 phương pháp đó, thì dll của tôi sẽ tải trong Java. Tôi biết nó là một cái gì đó để làm với các phương pháp này từ một thư viện dll của tôi liên kết đến. Có cái gì khác với cách Java thấy các thư viện phụ thuộc không? Tôi đã thử tải các thư viện phụ thuộc đầu tiên, nhưng một trong những tập tin dll tôi tải gây ra một lỗi đệ quy và tràn ngăn xếp.
Bất cứ ai biết một cách xung quanh một DLL gây ra tràn ngăn xếp từ lỗi đệ quy? Tôi cần các phương pháp trong đó, nhưng tôi không thể tải nó với java loadLibrary.
Dưới đây là thông tin chi tiết hơn về các tệp liên quan và thông báo lỗi thực tế. Tôi đã thêm một DllMain vào tập tin dll inital của tôi chỉ để xem những gì tải và khi nào. Nếu tôi biên dịch cùng một chương trình đó (my_plain_dll_to_call_JNI_DLL) thành một tệp exe, mọi thứ đều hoạt động tốt. Nếu tôi biên dịch nó và tải nó từ chương trình java của tôi điều này xảy ra.
- myJavaProgram, chỉ cần gọi System.loadLibrary() để tải tệp .dll cơ bản gọi phương thức trong dll khác của tôi có chứa mã JNI.
- my_plain_dll_to_call_JNI_DLL là một dll mà tôi đã tạo bằng cách liên kết nó với tệp thư viện dll của tôi chỉ để kiểm tra sự phụ thuộc. Nó chỉ gọi một phương thức từ dll khác đang gọi mã nguồn gốc mà tôi cần.
- my_JNI_DLL.ll là tệp dll được liên kết với lập trình C++ thư viện mà tôi cần truy cập từ JNI. Nó chứa các cuộc gọi trực tiếp đến các phương thức trong các thư viện mã nguồn hiện có.
tôi đã viết tên tập tin hiển thị văn bản bên trái của mỗi dòng để hiển thị những gì lớp thực hiện là trong.
c:\java myJavaProgram
myJavaProgram: Java Static Method Entry.
myJavaProgram: Java Calling System.loadLibrary(my_plain_dll_to_call_JNI_DLL)
my_JNI_DLL.dll: Entering DllMain
my_JNI_DLL.dll: DLL_PROCESS_ATTACH
my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_ATTACH
my_plain_dll_to_call_JNI_DLL: DLL_THREAD_ATTACH
my_plain_dll_to_call_JNI_DLL: DLL_THREAD_DETACH
my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH
myJavaProgram: my_plain_dll_to_call_JNI_DLL Loaded!
myJavaProgram: Java Static Method Exit.
myJavaProgram: Entering Main().
my_plain_dll_to_call_JNI_DLL: In call_my_JNI_DLL_method
my_JNI_DLL.dll: In my_JNI_DLL_method
my_JNI_DLL.dll: Entering my_JNI_DLL_CheckEnvironmentVariables()
my_JNI_DLL.dll: Exiting my_JNI_DLL_CheckEnvironmentVariables
my_JNI_DLL.dll: Calling StartExistingNativeCode.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (0xc0fb007e), pid=7500, tid=7552
#
# JRE version: 6.0_21-b06
# Java VM: Java HotSpot(TM) Client VM (17.0-b16 mixed mode, sharing windows-x86)
# Problematic frame:
# C [KERNELBASE.dll+0x9673]
#
# An error report file with more information is saved as:
# C:\hs_err_pid7500.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH
my_JNI_DLL.dll: Entering DllMain
my_JNI_DLL.dll DLL_PROCESS_DETACH
Cập nhật tôi đã thu hẹp xuống vấn đề để một thư viện quản lý bộ nhớ được liên kết từ một dll khác mà chương trình của tôi sử dụng. Các dll mà nó sử dụng là sh33w32.dll, nó được gọi là SmartHeap và là bởi một công ty tên là Microquil tôi nghĩ. Tôi có phiên bản 3.3, và khi Java LoadLibrary cố gắng tải dll đó, nó không thành công. Tôi không chắc chắn những gì tôi có thể làm để có java xử lý tải thư viện đó. Nó phải có một cái gì đó để làm với khu vực bộ nhớ mà Java có thể truy cập, so với những gì các cửa sổ cho phép một exe để truy cập. Các exe không có vấn đề với thư viện SmartHeap, nhưng Java sẽ không cho phép tôi sử dụng nó. Bất kỳ ý tưởng hoặc kinh nghiệm đối phó với điều này? Tôi đã cố gắng để loại bỏ các thư viện liên kết bằng cách biên dịch lại các thư viện khác, nhưng sau đó các cuộc gọi bình thường trong mã không bình thường làm việc.
Thông tin bổ sung Tìm thấy Chức năng đó là trong dll mà không tải trong java được gọi MemRegisterTask. Đó là từ một sản phẩm được gọi là SmartHeap bởi Microquill. Đây là tài liệu tôi tìm thấy về chức năng này. Tôi nghĩ rằng việc cấp phát bộ nhớ này là nguyên nhân khiến java không thể tải nó.
MemRegisterTask khởi tạo Thư viện SmartHeap. Trên hầu hết các nền tảng, bạn không cần phải gọi MemRegisterTask vì SmartHeap sẽ tự khởi chạy khi bạn thực hiện cuộc gọi đầu tiên.
SmartHeap duy trì số lượng tham chiếu đăng ký cho từng tác vụ hoặc quy trình. Mỗi lần bạn gọi MemRegisterTask, số tham chiếu này được tăng lên. Nếu cuộc gọi cuối cùng của bạn tới SmartHeap xảy ra trước khi ứng dụng của bạn sẵn sàng chấm dứt, bạn có thể gọi MemUnregisterTask để chấm dứt SmartHeap. MemUnregisterTask giảm số lượng tham chiếu đăng ký một lần - khi số đếm bằng 0, SmartHeap sẽ giải phóng mọi bộ nhớ được phân bổ SmartHeap và trạng thái gỡ lỗi được kết hợp với tác vụ hoặc quy trình hiện tại.
Có thể đăng một số mã sẽ giúp mọi người nhìn thấy nhiều hơn về điều này. Chỉ cần kiểm tra nhanh: bạn đang hiển thị đúng DLL của bạn tới java (ví dụ: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html#impl) – JScoobyCed
Tôi không chắc mình có thể đăng bài hay không mã, vì quy tắc công việc. Tôi đã làm việc thông qua mọi lỗi JNI khác mà tôi đã gặp phải, vì vậy tôi đang cố gắng hiểu các khái niệm để xem liệu tôi có thể thấy tại sao nó không thành công. Tôi đang vạch trần phương pháp 1 mà chương trình java của tôi sử dụng đúng cách. Vấn đề là dll thậm chí không tải trong Windows Java, Unix Java hoạt động tốt. – Logan
Có vẻ như từ thông báo ngoại lệ hoặc là các paramewters đến hàm C++ là không chính xác (marshalled thành một loại khác với dự kiến), hoặc liên kết không được thực hiện đúng cách. Có thể là thư viện C++ được biên dịch với các quy ước gọi khác nhau so với những gì JNI cung cấp/giả định. – Attila