Является ли интерфейс Java Native (JNI) затронутым проблемами совместимости с С++ ABI?
Я разрабатываю Java-приложение. Я хотел бы использовать Java Native Interface (JNI) для вызова функций в библиотеке С++. У меня есть доступ к коду для библиотеки С++, и я могу его перестроить, но мне может понадобиться. (Например, я могу статически связать время выполнения С++.)
Я могу потребовать, чтобы мои пользователи имели JRE 6 или больше, но я не могу требовать от них какой-либо конкретной среды выполнения С++.
Сотрудник указал мне на эту статью в блоге: http://www.trilithium.com/johan/2005/06/static-libstdc/, который советует не использовать динамически загруженный код на С++.
Другой сотрудник указал мне на этот отчет об ошибке: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590, в котором подробно описывается, как эти проблемы были адресованы обратно в Java 1.4.2.
Суть проблемы, как я понимаю, в том, что бинарный интерфейс libstdС++ часто изменяется. Если приложение С++ загружает общую библиотеку С++, которая была построена с другим компилятором, две несовместимые библиотеки libstdС++ будут загружены в память одновременно.
В отчете об ошибке объясняется решение для Java 1.4.2: "Мы статически связываем среду выполнения С++ в JDK и включенный компоновщик script, чтобы скрыть символы из libstdС++ и других внутренних символов. В результате эти символы становятся невидимыми для JNI код, а когда какой-то собственный код нужно вызвать в С++ runtime, вызов будет разрешен с помощью соответствующего libstdС++. Таким образом, есть еще два libstdС++, поэтому они загружаются одновременно, но они должны быть доброкачественными."
У меня есть несколько вопросов об этом.
Во-первых, продолжает ли OpenJDK использовать этот подход?
[ EDIT: Я задал этот вопрос в списке рассылки OpenJDK build-dev. Ответ: да, HotSpot все еще статически связывает libstdС++, но, по-видимому, "большинство дистрибутивов Linux исправляет это". Другой разработчик отмечает, что для этого даже не требуется патч: "Настройка STATIC_CXX = false должно быть достаточно (по умолчанию оно равно true). "]
Во-вторых, даже в этом случае, действительно ли полезно иметь два несовместимых libstdС++, загруженных одновременно?
В-третьих, поддерживает ли этот подход (чтобы скрыть символы в JDK) все проблемы совместимости?
В статье в блоге, приведенной выше, предупреждается, что "код, составленный для разных ABI, просто не совместим с бинарными". И позже, что "поддержка времени выполнения языка обычно полагается на некоторые совместно используемые данные, например, для доступа к какой-либо блокировке или глобальной структуре данных (подобно тому, как программы на C требуют совместного использования errno).
Это звучит так, будто проблема не может быть решена.
Опять же, возможно, несовместимость ABI больше не проблема. Статья в блоге старше шести лет. Один ответ для другого вопроса о stackoverflow (совместимость GCC ABI) утверждает, что "Начиная с gcc-3.4.0, ABI совместим с переходом". Успешно ли это?
Буду признателен за любые рекомендации по этим вопросам. (И эй, спасибо, что прочитал все это!)
редактирует
Мой вопрос становился довольно длинным, поэтому я не дал всей специфики. Чтобы отправить комментарии Уилла:
- Мне нужно только вызвать внешние функции "С". (Например, я использую javah для создания файла заголовка C.)
- Мне не нужно взаимодействовать со средой выполнения С++ в JVM. (Мне просто нужно отправить строки в библиотеку С++.)