C++ и Java: совместное использование

ОГЛАВЛЕНИЕ

Язык JAVA во многом произошел от С/С++, у которых были позаимствованы синтаксис и базовая семантика. Однако связь между ними не ограничивается только этим. Используя JNI (JAVA NATIVE INTERFACE), можно вызывать С/С++-функции из JAVA-программы и, наоборот, из программы, написанной на С/С++, можно создавать JAVA-объекты и вызывать JAVA-методы. Несмотря на то, что использование JNI в большинстве случаев ведет к потере многоплатформенности JAVA-кода, данная возможность расширяет сферу применения самого языка JAVA на приложения, для которых это условие не является необходимым. В таких системах использование JNI позволяет сочетать современный объектно-ориентированный подход JAVA - главное преимущество этой технологии, с существующим (LEGACY) системно-зависимым (PLATFORM SPECIFIC) кодом на С/С++. Это является важным и необходимым условием перехода к использованию JAVA-технологии при разработке компонентов сервера. Существует несколько причин совместного использования С/С++ и JAVA: стандартные библиотеки JAVA-классов не всегда поддерживают некоторые системно-зависимые возможности; необходимость использования наработанного и отлаженного кода на других языках или желание максимально эффективно реализовать участок кода, критичного с точки зрения времени исполнения. Эти причины не существенны при разработке клиентских приложений, однако в случае серверных - они становятся доминирующими.

Для обеспечения интероперабельности программного кода в рамках С/С++ и JAVA JDK1.1 (JAVA DEVELOPERS KIT) предоставляет набор интерфейсов, объединенных в JNI (JAVA NATIVE INTERFACE). JNI позволяет JAVA-коду, исполняемому виртуальной JAVA-машиной (JVM - JAVA VIRTUAL MACHINE), взаимодействовать с приложениями и библиотеками, написанными на языках С/С++ или Ассемблера.

Основным преимуществом JNI перед предыдущей версией (JDK 1.0 NI - NATIVE INTERFACE) и другими сходными интерфейсами (NETSCAPE JAVA RINTIME INTERFACE или MICROSOFT'S RAW NATIVE INTERFACE AND COM/JAVA INTERFACE) является то, что JNI изначально разрабатывался для обеспечения двоичной совместимости (BINARY COMPATIBILITY), подразумевающей совместимость приложений, написанных с использованием JNI, для любых JVM на конкретной платформе. Другими словами, один и тот же скомпилированный С/С++-код должен одинаково корректно исполняться JVM NETSCAPE NAVIGATOR и MICROSOFT EXPLORER, SYMANTEC VISUAL CAFО и SUN JAVA WORKSHOP и т.д. для данной платформы (WIN32). Следует отметить, что ранние интерфейсы не удовлетворяли этому условию. Например, JDK 1.0 NI, входящий в JDK 1.0.2 и поддерживаемый в JDK 1.1 для обратной совместимости, использует С-структуры для доступа к членам JAVA-объекта, что определяет зависимость С/С++-кода от того, как JVM располагает объекты в памяти. В общем случае, при использовании JDK 1.0 NI требуется перекомпиляция соответствующего С/С++-кода для каждой JVM на данной платформе.

Несмотря на определенную универсальность интерфейса, обусловленную его двоичной совместимостью, JNI обладает широкой функциональностью, предоставляя разработчику все низкоуровневые механизмы JVM: создание JAVA-объектов, включая создание массивов и объектов типа STRING; вызов JAVA-методов; возбуждение и перехват исключительных ситуаций (EXCEPTION); загрузка JAVA-классов и динамический анализ типа (RUNTIME TYPE CHECKING). Отдельно в JNI входит INVOCATION API, позволяющий приложениям динамически загружать JVM. Динамическая загрузка JVM из С/С++-кода позволяет легко встраивать возможности JAVA в существующие системы без необходимости их статического связывания (LINKAGE) с кодом JVM.

Ниже будет рассмотрено, как создавать коды на С/С++ и JAVA для их совместного использования в рамках JNI и INVOCATION API. Все примеры разработаны и протестированы на платформе WINDOWS 95. Во всех случаях, когда это необходимо, даются пояснения для платформы UNIX.

JNI определяется библиотечными и заголовочными (HEADER) файлами для С/С++. Библиотечные файлы хранятся в подкаталоге LIB (DLL - DYNAMIC-LINK LIBRARY, для WIN32 - в подкаталоге BIN), а заголовочные файлы - в подкаталоге INCLUDE основного каталога JAVA.