2012-01-04 25 views
11

Giao diện bản địa Java (JNI) có bị ảnh hưởng bởi các vấn đề tương thích với C++ ABI không?Giao diện bản địa Java (JNI) có bị ảnh hưởng bởi các vấn đề tương thích với C++ ABI không?

Tôi đang phát triển một ứng dụng Java. Tôi muốn sử dụng Java Native Interface (JNI) để gọi các hàm trong thư viện C++. Tôi có quyền truy cập vào mã cho thư viện C++, và tôi có thể xây dựng lại nó tuy nhiên tôi có thể cần. (Ví dụ, tôi có thể liên kết tĩnh thời gian chạy C++.)

Tôi có thể yêu cầu người dùng của mình có JRE 6 trở lên, nhưng tôi không thể yêu cầu họ có bất kỳ thời gian chạy C++ cụ thể nào.

Một đồng nghiệp đã chỉ cho tôi đến bài viết trên blog này: http://www.trilithium.com/johan/2005/06/static-libstdc/ mà khuyên không nên sử dụng tự động nạp C++.

Một đồng nghiệp khác đã chỉ cho tôi báo cáo lỗi này: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590 chi tiết cách các vấn đề này được giải quyết lại trong Java 1.4.2.

Các ý chính của vấn đề, như tôi hiểu nó, là giao diện nhị phân của libstdC++ thường thay đổi. Nếu một ứng dụng C++ tải một thư viện chia sẻ C++ được xây dựng với một trình biên dịch khác, hai thư viện libstdC++ không tương thích sẽ được nạp vào bộ nhớ cùng một lúc.

Báo cáo lỗi giải thích giải pháp cho Java 1.4.2: "Chúng tôi liên kết tĩnh thời gian chạy C++ trong JDK và bật tập lệnh liên kết để ẩn biểu tượng khỏi libstdC++ và các biểu tượng nội bộ khác. và khi một số mã nguồn gốc cần phải gọi vào thời gian chạy C++, cuộc gọi sẽ được giải quyết bằng libstdC++ thích hợp. Vì vậy, vẫn còn hai libstdC++. do đó được tải cùng một lúc, nhưng nó phải là lành tính. "

Tôi có một vài câu hỏi về điều này.

Thứ nhất, không OpenJDK tiếp tục áp dụng cách này?

[EDIT: Tôi đã đặt câu hỏi này trên danh sách gửi thư xây dựng của OpenJDK. Câu trả lời là có, HotSpot vẫn tĩnh liên kết libstdC++, nhưng dường như "hầu hết các bản phân phối Linux vá lỗi này". Một nhà phát triển nhấn mạnh rằng điều này thậm chí không cần một bản vá: "Thiết STATIC_CXX = false nên đủ (nó mặc định là true)."]

Thứ hai, ngay cả trong trường hợp này, là nó thực sự lành tính có hai không tương thích libstdC++ để nạp cùng một lúc?

Thứ ba, cách tiếp cận này (để ẩn các ký hiệu trong JDK) có giải quyết được tất cả các vấn đề tương thích không?

Các bài viết blog tham chiếu ở trên cảnh báo rằng "mã biên dịch chống lại Abis khác nhau chỉ đơn giản là không tương thích nhị phân." Và sau đó, "hỗ trợ thời gian chạy ngôn ngữ thường dựa vào một số dữ liệu được chia sẻ, ví dụ: để truy cập một số loại khóa hoặc cấu trúc dữ liệu toàn cầu (tương tự như cách các chương trình C cần chia sẻ errno)."

Điều này làm cho nó âm thanh như vấn đề không thể được giải quyết.

Sau đó, một lần nữa, có lẽ ABI không tương thích không phải là một vấn đề nữa. Bài viết trên blog đã hơn sáu tuổi. Một câu trả lời cho một câu hỏi stackoverflow khác (GCC ABI compatibility) khẳng định rằng "Vì gcc-3.4.0, ABI tương thích về phía trước." Điều đó đã thành công?

Tôi đánh giá cao mọi hướng dẫn về những vấn đề này. (Và này, cảm ơn vì đã đọc tất cả điều này!)

CÁC CHỈNH SỬA

Câu hỏi của tôi đã nhận được khá lâu, vì vậy tôi đã không đưa ra tất cả các chi tiết cụ thể. Để giải quyết các nhận xét của Will:

  1. Tôi chỉ cần gọi các hàm "C" bên ngoài. (Ví dụ, tôi sử dụng javah để tạo tệp tiêu đề C.)
  2. Tôi không cần tương tác với thời gian chạy C++ trong JVM. (Về cơ bản tôi chỉ cần gửi chuỗi đến thư viện C++.)

Trả lời

5

Tôi không biết. Nhưng điều đó không bao giờ ngăn tôi lại.

Đầu tiên, nó phụ thuộc vào những gì bạn muốn làm. Tiền đề đằng sau liên kết tĩnh của JDK là cải thiện tính di động của bản thân JDK thực tế. Vì họ không thể mong đợi người dùng biên dịch lại JDK trên hệ điều hành cụ thể của họ, họ cần một cơ chế để tạo ra nhị phân cuối cùng di động. Rõ ràng liên kết tĩnh cố định vấn đề này.

Tiếp theo, liên quan đến JNI, trước tiên bạn sẽ gọi hàm C chứ không phải C++, tôi không tin rằng JNI có bất kỳ loại ràng buộc C++ nào. Vì vậy, bất cứ điều gì C++ bạn sẽ muốn sử dụng sẽ cần phải được bao bọc trong một thường trình C để nói chuyện với Java.

Tiếp theo, C++ của bạn sẽ tự động liên kết với hệ điều hành khá giống như bình thường mà tôi đoán. Có vẻ như draconian khá mong đợi một thói quen JNI không hoạt động với một liên kết động .so, và một C++. Nên không khác nhau. Và, không có nghi ngờ C + + được phổ biến như nó được, có vẻ như draconian tương tự mà bạn sẽ không thể liên kết động chống lại một C++ .so. Vì vậy, bất cứ điều gì shenanigans cần phải diễn ra để tạo thuận lợi cho điều này, đó là một giả định hợp lý rằng họ (tm) đã thực hiện công việc để cho phép điều này xảy ra.

Điều đó nói rằng, chắc chắn sẽ không có kỳ vọng rằng bất kỳ C++ nào bạn đang sử dụng sẽ có bất kỳ tương tác nào với thời gian chạy C++ trong thời gian chạy Java. Lý tưởng nhất, họ chỉ đơn giản là hòa bình cùng tồn tại. Với điều đó, giả sử công trình này ở tất cả, C++ của bạn chắc chắn sẽ có vấn đề về tính di động của ABI, vì nó sẽ liên kết động và sẽ có lòng thương xót của thời gian chạy C++ đã cài đặt của hệ điều hành.

Vì vậy, cuối cùng, tôi chỉ cho nó một bản trích xuất và xem điều gì sẽ xảy ra.

+1

JNI chắc chắn có ràng buộc C++. Nhưng tôi nghi ngờ của nó một wrapper chỉ tiêu đề của C ràng buộc, do đó, nên được miễn dịch với các vấn đề ABI. –

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