2008-10-01 41 views
10

Tôi đang viết một số mã JNI trong C++ để được gọi từ một applet trên Windows XP. Tôi đã có thể chạy thành công applet và có thư viện JNI được nạp và gọi, thậm chí đi xa đến mức có chức năng gọi nó trong các DLL khác. Tôi đã làm việc này bằng cách thiết lập biến môi trường hệ thống PATH để bao gồm tất cả các tệp DLL của tôi đang có.UnsatisfiedLinkError: Quy trình được chỉ định không thể tìm thấy

Vì vậy, vấn đề là tôi thêm một cuộc gọi khác sử dụng DLL bên ngoài mới và đột nhiên khi tải thư viện, một UnsatisfiedLinkError được ném. Thông báo là: 'Không thể tìm thấy quy trình được chỉ định'. Điều này không có vẻ là một vấn đề với một DLL phụ thuộc bị thiếu, bởi vì tôi có thể loại bỏ một DLL phụ thuộc và nhận được một thông báo khác nhau về DLL phụ thuộc bị thiếu. Từ những gì tôi đã có thể tìm thấy trực tuyến, nó xuất hiện rằng thông báo này có nghĩa là một thực hiện chức năng Java bản địa là mất tích từ DLL, nhưng nó lẻ rằng nó hoạt động tốt mà không cần thêm chút mã này.

Có ai biết điều gì có thể gây ra điều này không? Những loại điều nào có thể cung cấp thông điệp 'Quy trình được chỉ định không thể tìm thấy' cho một UnsatisifedLinkError?

Trả lời

14

Tôi đã tìm ra sự cố. Đây là một doozy. Thông báo "Không thể tìm thấy thủ tục được chỉ định" cho UnsatisfiedLinkError chỉ ra rằng một hàm trong dll gốc hoặc trong một dll phụ thuộc không thể tìm thấy. Nguyên nhân có khả năng nhất của điều này trong tình huống JNI là hàm JNI gốc không được xuất một cách chính xác. Nhưng điều này dường như có thể xảy ra nếu một DLL phụ thuộc được nạp và DLL đó thiếu một hàm do cha mẹ yêu cầu.

Bằng ví dụ, chúng tôi có thư viện có tên input.dll. Thứ tự tìm kiếm DLL là luôn luôn tìm trong thư mục ứng dụng đầu tiên và các thư mục PATH cuối cùng. Trong quá khứ, chúng tôi luôn chạy các tập tin thực thi từ cùng thư mục với input.dll. Tuy nhiên, có một input.dll trong thư mục hệ thống cửa sổ (mà là ở giữa thứ tự tìm kiếm DLL). Vì vậy, khi chạy này từ một applet java, nếu tôi bao gồm các mã được mô tả ở trên trong applet, nguyên nhân gây input.dll để được nạp, nó tải input.dll từ thư mục hệ thống. Bởi vì mã của chúng tôi là mong đợi một số chức năng trong input.dll mà không có (vì nó là một DLL khác nhau) tải không thành công với một thông báo lỗi về thủ tục mất tích. Không phải vì các hàm JNI được xuất sai, nhưng vì DLL phụ thuộc sai đã được tải và nó không có các hàm được mong đợi trong nó.

+0

Tôi gặp sự cố này. libA kéo vào libBv2 và libC. Cả hai libBv2 và libC đã được tìm thấy. Vấn đề là libC đã phụ thuộc vào một phiên bản khác, libBv1. libBv1 và libBv2 không hoạt động cùng nhau. phụ thuộc tập đi cho thấy các thư viện nhưng tôi đã không mở rộng phụ thuộc của libC. Tôi đã sử dụng procmon (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) để xem các thư viện đang được tải và đó là khi tôi nhận thấy phiên bản libB thứ hai đang được tải. – codeDr

0

Thông thường, khi liên kết với các thư viện khác, bạn cần liên kết đến tệp .lib có liên quan. Có vẻ như bạn không tham chiếu tất cả các tệp lib bạn cần. Kiểm tra những gì không liên kết và đảm bảo bạn thêm lib vào danh sách cho trình liên kết.

2

Có khả năng DLL được tạo bằng C++ (ngược với C). trừ khi bạn đã chăm sóc để làm một extern về thủ tục, đây là một trong những lý do có thể.

Thử xuất tất cả các chức năng từ DLL. Nếu danh sách bao gồm chức năng của bạn thì bạn tốt.

+0

Tôi đã mở tệp DLL trong trình khám phá PE và kiểm tra kỹ xem các chức năng JNI có được xuất bằng liên kết C hay không. Tôi cũng kiểm tra lại, và chữ ký của các hàm JNI trông giống nhau trong trường hợp DLL không tải mà không có lỗi và trong trường hợp nó không thành công. – matt

0

Bạn đã tạo DLL bên ngoài mới bằng quy trình JNI chuẩn chưa? Tức là, bằng cách sử dụng javah và vv? Nếu vậy, thì tôi không chắc điều gì sai.

Nếu không, thì quy trình bạn đang cố gắng gọi chưa được xuất (như đã đề cập bởi anjanb). Tôi biết hai cách xuất các hàm: một danh sách xuất riêng biệt và đánh dấu các hàm cụ thể với __declspec (dllexport).

Can't access variable in C++ DLL from a C app có thêm một chút thông tin về chủ đề của các tệp DLL.

+0

Tôi đang sử dụng quy trình JNI chuẩn. Như tôi đã nói, tôi có nó hoạt động trong một số trường hợp. Nhưng khi tôi thêm mã phụ này, nó đột nhiên ngừng hoạt động với lỗi đã cho. Như đã được chỉ ra, lỗi cho biết hàm không được xuất, nhưng tôi cho rằng các hàm được xuất. – matt

0

Biên dịch mã C++ của bạn ở chế độ gỡ lỗi. Sau đó chèn DebugBreak(); tuyên bố nơi bạn muốn bắt đầu gỡ lỗi. Chạy mã java.Khi gặp DebugBreak(), bạn sẽ nhận được một popup với một nút Debug trên đó. Nhấn vào nó. Dev Studio sẽ mở bằng chương trình của bạn trong mã máy. Bước qua với trình gỡ rối hai lần và bạn sẽ có thể bước qua mã nguồn của bạn.

0

Nếu bạn đã thực hiện tất cả các vấn đề lập trình trong hướng dẫn sử dụng và ví dụ của JNI nhưng bạn vẫn gặp lỗi thủ tục thiếu, có thể sự cố có thể ở biến đường dẫn của bạn. Làm các bước dưới đây và chạy lại:

  1. Hãy chắc chắn về bạn đặt biến JAVA_HOME vào thư mục của bạn JDK (không JRE vì JRE doesnt chứa tiêu đề JNI) Ví dụ: Tại bảng điều khiển thiết lập biến môi trường xác định var: JAVA_HOME val: C: \ Program Files \ Java \ jdk1.7.0_11
  2. thêm % JAVA_HOME% \ bin đến đường dẫn của bạn biến

Sau khi thực hiện những bước, ứng dụng của bạn có thể tìm thấy tên thủ tục JNI và liên kết đến JNI . dll đúng cách. Vì vậy, tôi hy vọng bạn không nhận được lỗi thủ tục mất tích này một lần nữa.

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