6

Tôi có chương trình java Client.class sử dụng thư viện chia sẻ cpp libclient.so qua JNI. libclient.so được xây dựng dưới dạng chia sẻ và sử dụng thư viện chia sẻ cpp libhttp.so.System.loadLibrary không hoạt động. UnsatisfiedLinkError cho lib thứ hai trong chuỗi

libclient.so và libhttp.so được đặt trong thư mục /home/client/lib64
Client.class được đặt trong /home/client/bin

Khách hàng có thể tải thư viện với

  1. System.load và LD_LIBRARY_PATH biến môi trường
  2. System.loadLibrary và -Djava.library.path

Cách đầu tiên hoạt động tốt.

export LD_LIBRARY_PATH = /home/client/lib64

java -classpath ./bin Khách hàng

Cách Secon thất bại.

java -classpath ./bin -Djava.library.path=./../lib64 Client

java.lang.UnsatisfiedLinkError: /home/client/lib64/libclient.so: libhttp.so: cannot open shared object file: No such file or directory 

Khi tôi đặt libhttp.so vào/usr/lib64 cách thứ hai hoạt động tốt.

Tại sao libclient.so đang tìm libhttp.so trong/usr/lib64 nếu tôi sử dụng System.loadLibrary? Làm cách nào để khắc phục sự cố mà không cần phải đối mặt với libhttp.so trong/usr/lib64?

đang tải của tôi:

//Try load from -Djava.library.path   
    boolean found = false; 
    String lib = "client"; 
    try { 
     System.loadLibrary(lib); 
     found = true; 
    } catch (UnsatisfiedLinkError e) { 
     e.printStackTrace(); 
    } 
    //Try load from LD_LIBRARY_PATH 
    if (!found) { 
     lib = "libclient.so"; 
     String ld_lib_path = System.getenv("LD_LIBRARY_PATH"); 
     String[] paths = ld_lib_path.split(":"); 
     for(int i=0; i<paths.length; i++) { 
      String p = paths[i]; 
      File x = new File(p, lib); 
      if (x.exists()) { 
      System.load(x.getAbsolutePath()); 
      found = true; 
      break; 
      } 
     } 
    } 

thông tin bổ sung.

Nếu tôi kiểm tra libclient.so với ldd thì tôi thấy: libhttp.so => ​​không tìm thấy Nếu tôi đặt LD_LIBRARY_PATH =/home/client/lib64 xuất thì tôi thấy: libhttp.so => ​​/ home/client/lib64/libhttp.so

Trả lời

10

Lý do cho điều này là libclient.so được tải từ JVM của bạn, trông giống như java.library.path. Tuy nhiên, khi libclient.so cố tải libhttp.do đó, nó không biết gì về Java và chỉ sử dụng cách tải Linux thông thường (liên kết động ld.so), trông giống như LD_LIBRARY_PATH và một số thư mục phổ biến như /usr/lib64.

Tôi có thể sẽ sử dụng LD_LIBRARY_PATH được đặt từ tập lệnh bắt đầu của ứng dụng Java của bạn. Nếu bạn không muốn sử dụng một kịch bản bắt đầu, bạn có thể trong lý thuyết thiết lập LD_LIBRARY_PATH từ bên trong quá trình đó. Tuy nhiên, Java không cho phép thực hiện điều này (chỉ có System.getenv(), không phải System.setenv()), vì vậy bạn cần viết một thư viện C nhỏ được gọi từ Java và gọi putenv() thiết lập LD_LIBRARY_PATH.

Nếu bạn tự xây dựng libclient.so, bạn có thể sử dụng cờ liên kết -rpath để chỉ định đường dẫn nơi liên kết động sẽ tìm các thư viện yêu cầu tiếp theo. Hãy cẩn thận nếu bạn chỉ định một đường dẫn tương đối ở đây, nó sẽ được hiểu là tương đối so với thư mục làm việc hiện tại của ứng dụng đang chạy, không liên quan đến vị trí của libclient.so. Để đạt được điều này, bạn cần sử dụng $ORIGIN làm đối số cho -rpath và hãy cẩn thận rằng trình bao của bạn không mở rộng.

Vì vậy, nếu bạn muốn có libclient.solibhttp.so trong cùng thư mục, bạn cần phải sử dụng

-rpath '$ORIGIN' 

như là đối số để mối liên kết khi xây dựng libclient.so. Nếu bạn không gọi mối liên kết trực tiếp nhưng chúng ta hãy biên dịch của bạn gọi nó, bạn cần phải thêm dòng sau vào dòng lệnh của trình biên dịch của bạn:

-Wl,-rpath,'$ORIGIN' 

biết thêm thông tin về vấn đề này có thể được tìm thấy trong man page for ld.so.

1

Tôi không có câu trả lời hay cho câu hỏi này.

Nhưng tôi đã tìm thấy một số cách tốt.

  1. Đặt libhttp.so vào vị trí dùng chung cho thư viện, ví dụ/usr/lib64.
  2. Đặt đường dẫn đến libhttp.so vào LD_LIBRARY_PATH.
  3. Xây dựng libclient.so bằng libhttp.so bên trong.
  4. Sử dụng -rpath trong khi xây dựng libclient.so.
0

Đối tra cứu chính xác các thư viện (từ java.library.path) cho hệ điều hành khác nhau của phải có tên gọi khác nhau:

  • Linux: libhttp.so
  • Windows: http.dll

Hơn bạn có thể gọi từ Java:

System.loadLibrary("http"); 
Các vấn đề liên quan