-->
   
-->

Главная

ТАРИФЫ ХОСТИНГА
АРЕНДА СЕРВЕРОВ
КЛИЕНТАМ
ТЕХ. ПОДДЕРЖКА
РЕССЕЛЕРАМ
ПРОГРАММЫ И УСЛУГИ
ИНФОРМАЦИЯ
О КОМПАНИИ

  

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

 

Опубликовано:
23.09.04

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.

Использование JNI

Взаимодействие кодов JAVA и С/С++ может осуществляться двумя способами: С/С++-код получает управление непосредственно из JAVA-программы путем вызова собственного (NATIVE) метода; С/С++-код динамически загружает JVM с помощью INVOCATION API. Во втором случае, по сути, реализуется специализированная JVM, так как разработчик С/С++-кода сам решает, в какой последовательности выполнять JAVA-код (когда и какие JAVA-объекты создавать, какие методы вызывать и т. д.).

Рассмотрим первую из указанных возможностей.

Для того чтобы передать управление С/С++-коду из JAVA-программы, необходимо создать собственный JAVA-метод, сгенерировать с помощью утилиты JAVAH заголовочный файл для С/С++-функций, разработать сами функции, в которые будет передаваться управление, и оттранслировать их, поместив в библиотечный файл. После создания библиотеки ее можно загружать из JAVA-программы для последующего вызова собственных методов.

Создание собственного JAVA-метода

Собственный метод создается путем добавления к его описанию спецификатора NATIVE, при этом он не должен иметь реализации (так же как и методы в описании интерфейса). Спецификатор NATIVE сообщает компилятору, что реализация данного метода будет представлена в виде откомпилированного С/С++-кода, помещенного в библиотечный файл. Когда JVM встречает обращение к собственному методу, происходит вызов соответствующей С/С++-функции. Помимо описания собственнного метода, JAVA-код должен динамически загрузить библиотеку, содержащую С/С++-функцию с реализацией данного метода. Для этого в классе JAVA.LANG.SYSTEM существует метод PUBLIC STATIC VOID LOADLIBRARY (STRING LIBNAME), загружающий указанную библиотеку. Следующий пример демонстрирует описание собственного метода.

CLASS SYSTEMSPECIFIC {
    STATIC {
        SYSTEM.LOADLIBRARY("SYSSPEC");
    }
    NATIVE VOID DOSPECIFIC();
}

В приведенном примере метод DOSPECIFIC() является собственным, и его С/С++-реализация находится в библиотеке SYSSPEC. Метод LOADLIBRARY() вызывается в статическом инициализаторе, что обеспечивает единственный вызов этого метода после загрузки класса SYSTEMSPECIFIC загрузчиком классов (CLASS LOADER). В принципе, LOADLIBRARY() можно вызывать более одного раза (например, в конструкторе), однако загрузка библиотеки будет происходить только при первом обращении к LOADLIBRARY(), поскольку при последующих вызовах этого метода определяется, что библиотека уже загружена и будет просто возвращаться управление.

Метод LOADLIBRARY() преобразует свой параметр в соответствии с тем, как именуются библиотечные файлы на конкретной платформе. В данном примере SYSSPEC преобразуется в SYSSPEC.DLL и LIBSYSSPEC.SO для WIN32 и UNIX соответственно. Метод LOADLIBRARY() использует стандартный алгоритм поиска библиотеки для данной платформы. Для WIN32 DLL должна находиться либо в текущем каталоге процесса, либо в каталоге, содержащем EXE-файл, то есть исполняемый модуль JVM, находящийся в подкаталоге BIN основного каталога JAVA, либо в системном каталоге WIN32, либо каталоге WINDOWS или в каталогах, указанных в переменной окружения PATH. Для UNIX библиотечный файл должен находиться либо в текущем каталоге процесса, либо в подкаталоге LIB основного каталога JAVA, либо в каталогах, перечисленных в переменной окружения LD_LIBRARY_PATH. Если указанную библиотеку найти не удается, метод LOADLIBRARY() генерирует исключительную ситуацию JAVA.LANG.UNSATISFIEDLINKERROR. Однако данная ситуация возникает не только в этом случае. Когда интерпретатор встречает вызов собственного метода, он ищет его (точнее его полную сигнатуру) в списке методов загруженных библиотек. Если метод не найден, то генерируется указанная исключительная ситуация.

Для более надежной работы с собственными методами можно использовать, к примеру, следующий код:

PUBLIC CLASS APP {
    PUBLIC STATIC VOID MAIN(STRING ARGS) {
        SYSTEMSPECIFIC SS = NEW SYSTEMSPECIFIC();
        TRY {
            SS.DOSPECIFIC();
        }    
        CATCH (UNSATISFIEDLINKERROR E) {
            SYSTEM.OUT.PRINTLN("метод не найден (" + E + ")");
        }
    }
}
CLASS SYSTEMSPECIFIC {
    STATIC {
        TRY {
SYSTEM.LOADLIBRARY("SYSSPEC");
        }
        CATCH (UNSATISFIEDLINKERROR E) {
            SYSTEM.OUT.PRINTLN("библиотека не найдена (" + E
             + ")");
        }
    }
    NATIVE VOID DOSPECIFIC();
}

>

Компиляция программ, содержащих собственные методы, ничем не отличается от компиляции обычных программ. Например, если записать предыдущий пример в файл с именем APP.JAVA, то для его компиляции необходимо выполнить следующую команду:

C:\ JAVAC APP.JAVA

Создание заголовочного файла

Создание С/С++-кода необходимо начинать с создания заголовочного файла. Его можно написать вручную или воспользоваться утилитой JAVAH. Второй путь предпочтительней, так как допускает меньшее количество ошибок. При обращении к утилите JAVAH указывается имя класса и параметр -JNI. Без него JAVAH будет генерировать файл в формате JDK 1.0 NI. Имя класса представляет собой полное квалифицированное имя класса. Например:

JAVAH -JNI JAVA.LANG.RUNTIME

Перед использованием утилиты JAVAH соответствующий JAVA-класс должен быть скомпилирован в CLASS-файл. Утилита JAVAH анализирует CLASS-файл и строит заголовочный файл, в котором перечислены объявления С/С++-функций, представляющих реализации соответствующих собственных методов. В качестве имен создаваемых заголовочных файлов используются полные квалифицированные имена классов, которые описаны в указанном файле и содержат собственные методы. Например, если выполнить следующие команды:

JAVAC APP.JAVA
JAVAH -JNI SYSTEMSPECIFIC

то JAVAH сгенерирует следующий файл SYSTEMSPECIFIC.H:

/* DO NOT EDIT THIS FILE - IT IS MACHINE GENERATED */
#INCLUDE <JNI.H>
/* HEADER FOR CLASS SYSTEMSPECIFIC */
#IFNDEF _INCLUDED_SYSTEMSPECIFIC
#DEFINE _INCLUDED_SYSTEMSPECIFIC
#IFDEF _ _CPLUSPLUS
EXTERN "C" {
#ENDIF
/*
 * CLASS:   SYSTEMSPECIFIC
 * METHOD:  DOSPECIFIC
 * SIGNATURE: ()V
 */
JNIEXPORT VOID JNICALL JAVA_SYSTEMSPECIFIC_DOSPECIFIC(JNIENV *, 
JOBJECT);
#IFDEF _ _CPLUSPLUS
}
#ENDIF
#ENDIF

Как указывалось выше, данный файл можно создать вручную или с помощью утилиты JAVAH. В последнем случае не рекомендуется вносить в него какие-либо изменения, так как при последующем применении JAVAH к данному классу все внесенные изменения будут потеряны.

Директива препроцессора #INCLUDE <JNI.H> включает файл JNI.H (из подкаталога INLCUDE основного каталога JAVA), в котором находятся все необходимые объявления типов и функций для реализации собственного метода.

Макросы JNIEXPORT и JNICALL необходимы только для платформы WIN32, где они раскрываются соответственно в __DECLSPEC(DLLEXPORT) и __STDCALL и позволяют более эффективно строить DLL. Платформа UNIX использует для этих целей обычные С-соглашения, поэтому указанные макросы раскрываются в пустые строки.

Как видно из примера, имя С/С++-функции значительно отличается от имени собственного JAVA-метода. Важным понятием при построении имени С/С++-функции и использовании JNI-функций является сигнатура метода (SIGNATURE или METHOD ARGUMENTS SIGNATURE).

Сигнатура метода

Сигнатура метода - это сокращенная форма записи параметров метода и типов возвращаемого значения. Следует подчеркнуть, что в сигнатуру не входят ни имя метода, ни имена параметров. JNI формирует сигнатуры в соответствии с правилами, представленными в табл. 1.

Таблица 1

Знак сигнатуры JAVA-тип

Z BOOLEAN
B BYTE
C CHAR
S SHORT
Internet INT
J LONG
F FLOAT
V VOID
D DOUBLE
L полное квалифицированное имя класса полное квалифицированное имя класса
[ тип тип[]
(типы аргументов) возвращаемый тип полная сигнатура метода

Проиллюстрируем эти правила на примерах:

  • метод LONG M1(INT N, STRING S, INT[] ARR);
  • сигнатура (ILJAVA/LANG/STRING;[I)J;
  • метод VOID M2(FLOAT N, BYTE[][] ARR, RUNTIME R);
  • сигнатура (F[[BLJAVA/LANG/RUNTIME;)V.

    Полная информация о правилах образования сигнатуры метода представлена в файле SIGNATURE.H.

    Правила формирования имени С/С++-функции

    Имя С/С++-функции формируется путем последовательного соединения следующих компонентов:

  • префикс JAVA_;
  • полное квалифицированное имя класса;
  • символ подчеркивания ("_");
  • имя метода;
  • для перегружаемых (OVERLOADED) методов - два символа подчеркивания ("_ _") с последующей сигнатурой метода.

    Использование имен с сигнатурой на конце необходимо только в случае перегрузки двух или более собственных методов (перегрузка с обычным методом не важна, так как обычные методы не будут находиться в создаваемой библиотеке, что, однако, не допускает наличия собственного и обычного метода с одинаковыми именами и сигнатурами).

    Для соответствия лексиграфическим правилам С/С++ и использования UNICODE-кодировки, применяются дополнительные правила преобразования, представленные в табл. 2.

    Таблица 2

    Исходный символ Результирующая последовательность

    "_" _1
    ";" _2
    "[" _3
    символ UNICODE с кодом ХХХХ _0ХХХХ

    Ниже приведен пример JAVA-класса с собственными методами:

    PACKAGE TESTPACKAGE;
    ABSTRACT CLASS TEST {
        PUBLIC NATIVE VOID M1(STRING[] SA, OBJECT O, INT[][] IA2);
        PUBLIC NATIVE FLOAT[] M1(DOUBLE D, TEST T);
        PUBLIC NATIVE TEST M3(INT I);
    }
    

    и соответствующие им имена С/С++-функций:

    JNIEXPORT VOID JNICALL JAVA_TESTPACKAGE_TEST_M1___3LJAVA
    _LANG_STRING_2LJAVA_LANG_OBJECT_2_3_3I
    (JNIENV *, JOBJECT, JOBJECTARRAY, JOBJECT, JOBJECTARRAY);
    JNIEXPORT JFLOATARRAY JNICALL JAVA_TESTPACKAGE_TEST_M1__LJAVA
    _LANG_DOUBLE_2LTESTPACKAGE_TEST_2
    (JNIENV *, JOBJECT, JOBJECT, JOBJECT);
    JNIEXPORT JOBJECT JNICALL JAVA_TESTPACKAGE_TEST_M3
    (JNIENV *, JOBJECT, JINT);
    

    Рассмотрим типы параметров, которые получает на входе С/С++-функция при ее вызове.

    Типы и структуры данных JNI

    JNI использует целый набор типов для своих функций и для формальных параметров С/С++-функций, представляющих реализацию собственных методов. Все эти типы описаны в файле JNI.H, который включается в любой заголовочный файл для JNI. Файл JNI.H использует стандартную технику препроцессирования с макросом _CPLUSPLUS. Тем самым, в зависимости от того, какой (С++ или С) код компилируется, будут создаваться две немного отличающиеся версии описания типов. Каждая из них требует определенного синтаксиса доступа.

    Файл JNI_MD.H содержит системно-зависимые описания JINT, JLONG и JBYTE. В этом же файле определены макросы JNIEXPORT и JNICALL. Тип VOID используется без переопределения.

    Следует отметить, что для представления строковых объектов JNI использует сокращенный вариант формата UTF-8.

    Первым аргументом С/С++-функции, представляющей реализацию собственного метода, является указатель на структуру JNIENV. Смысл этого указателя определяет важную идею, лежащую в основе реализации JNI. Если отвлечься от конкретного языка, то указатель на JNIENV, или интерфейсный указатель (JNI INTERFACE POINTER), является указателем на массив указателей, каждый из которых указывает на прикладную функцию JNI. Только через этот указатель С/С++-функция может получить доступ к функциям и ресурсам JNI. В случае С++ (макрос _CPLUSPLUS определен) тип JNIENV является структурой, а в случае С - указателем на структуру. В силу этого, для доступа к функциям JNI в С и С++ применяется различный синтаксис:

    // C
    JNIEXPORT VOID JNICALL JAVA_SYSTEMSPECIFIC_DOSPECIFIC
    (JNIENV* ENV, JOBJECT THIS) {
        JINT VERSION = (*ENV)->GETVERSION(ENV);
        Е
    }
    // C++
    JNIEXPORT VOID JNICALL JAVA_SYSTEMSPECIFIC_DOSPECIFIC
    (JNIENV* ENV, JOBJECT THIS) {
        JINT VERSION = ENV->GETVERSION();
        Е
    }
    

    Главным преимуществом такой организации функций JNI является легкость модификации и дальнейшего расширения интерфейса.

    Указатель на JNIENV действителен только в текущем потоке (THREAD). JVM гарантирует передачу одного и того же интерфейсного указателя всем методам, вызываемым из данного потока. Тем самым запрещено передавать интерфейсный указатель другому потоку. Если методы вызываются из разных потоков, то в этом случае каждый метод получает различные интерфейсные указатели.

    Если С/С++-функция представляет реализацию нестатического собственного метода, то вторым параметром функции является объект типа JOBJECT. Данный параметр является ссылкой на JAVA-объект, для которого был вызван соответствующий собственный метод. Если функция представляет статический собственный метод, то вторым параметром является объект типа JCLASS, определяющий JAVA-класс, для которого вызван собственный метод класса (CLASS METHOD).

    Последующие параметры С/С++-функции соответствуют параметрам собственного метода (если собственный метод их не содержит, то реализующая его С/С++-функция имеет только два описанных выше параметра).

    JNI функции

    JNI определяет 210 прикладных функций. Доступ к ним из С/С++-функции можно получить через интерфейсный указатель JNIENV*, который передается каждой С/С++-функции, представлющей реализацию собственного метода. Все функции разделены на 14 групп:

    • информация о версии JNI;
    • операции с классами;
    • исключения (EXCEPTIONS);
    • обработка глобальных и локальных ссылок;
    • операции с объектами;
    • доступ к данным объекта;
    • вызов методов объекта (INSTANCE METHOD);
    • доступ к статическим данным объекта;
    • вызов методов класса (CLASS METHOD);
    • операции со строковыми объектами;
    • операции с массивами;
    • регистрация собственных методов;
    • операции с мониторами (MONITOR OPERATIONS);
    • интерфейс с JVM.

    Использование JNI функций необходимо только в том случае, если С/С++-функция осуществляет какое-либо взаимодействие с JVM: вызов JAVA-методов, доступ к данным, создание JAVA-объектов и т.д.

    Ниже приведен пример JAVA-программы, которая выводит на печать количество свободной памяти на диске С для платформы WIN32. Для этого используется собственный метод и соответствующая реализационная С/С++-функция, вызывающая при своей работе функцию WIN32 API.

    // Файл APP.JAVA
    PUBLIC CLASS APP {
        PUBLIC STATIC VOID MAIN(STRING ARGS[]) {
            SYSTEMSPECIFIC SS = NEW SYSTEMSPECIFIC();
            TRY {
                LONG BYTES = SS.GETCDRIVEFREESPACE();
                IF (BYTES != -1) {
                    LONG KB = BYTES / 1024;    
                    SYSTEM.OUT.PRINTLN("на диске C:\\ свободно " 
                    + KB + " KB");
                }
                ELSE {
                    SYSTEM.OUT.PRINTLN("произошла ошибка в 
                    С/С++-функции");
                }
            }    
            CATCH (UNSATISFIEDLINKERROR E) {
                SYSTEM.OUT.PRINTLN("метод не найден (" + E + ")");
            }
        }
    }
    CLASS SYSTEMSPECIFIC {
        STATIC {
            TRY {
                SYSTEM.LOADLIBRARY("SYSSPEC");
            }
            CATCH (UNSATISFIEDLINKERROR E) {
                SYSTEM.OUT.PRINTLN("библиотека не найдена (" + E + ")");
            }
        }
        NATIVE LONG GETCDRIVEFREESPACE();
    }
    // Файл SYSTEMSPECIFIC.CPP
    #INCLUDE "SYSTEMSPECIFIC.H"
    #INCLUDE <WINDOWS.H>
    JNIEXPORT JLONG JNICALL JAVA_SYSTEMSPECIFIC_GETCDRIVEFREESPACE 
    (JNIENV *, JOBJECT) {
        DWORD SCTRPERCLSTR, BYTESPERSCTR, FREECLSTR, CLSTR;
        BOOL RES = GETDISKFREESPACE("C:\\", &SCTRPERCLSTR, 
        &BYTESPERSCTR, &FREECLSTR, &CLSTR);
        RETURN RES == TRUE ? SCTRPERCLSTR * BYTESPERSCTR * 
        FREECLSTR : -1;
    }
    

    Для успешной компиляции кода JAVA и С/С++ на платформе WIN32 необходимо правильно установить переменные окружения PATH, LIB, INCLUDE и CLASSPATH (многие из этих значений можно задать как параметры соответствующих компиляторов).

    Если записать исходные тексты предыдущего примера в файлы APP.JAVA и SYSTEMSPECIFIC.CPP соответственно, то для их компиляции необходимо выполнить следующие команды (предполагается, что исходные файлы находятся в каталоге C:\TEST\NATIVE):

    C:\TEST\NATIVE> JAVAC APP.JAVA
    C:\TEST\NATIVE> JAVAH -JNI SYSTEMSPECIFIC
    C:\TEST\NATIVE> CL -W3 SYSTEMSPECIFIC.CPP -FESYSSPEC.DLL
     -TP -LD -MD -LINK JAVAI.LIB
    

    Для запуска программы необходимо выполнить:

    C:\TEST\NATIVE> JAVA APP
    на диске С:\ свободно 324567 KB
    C:\TEST\NATIVE>
    

    Для трансляции С/С++-файлов можно использовать любой компилятор, допускающий создание 32-битных DLL.

    Использование INVOCATION API

    Использование INVOCATION API позволяет встраивать JVM в приложения без необходимости их статического связывания с кодом самой JVM. Напомним, что в этом случае управление изначально находится в С/С++-программе. INVOCATION API состоит из небольшого набора функций, позволяющих создавать и уничтожать JVM в текущем процессе, присоединять и отсоединять текущий поток от JVM (интерфейсный указатель существует только в рамках данного потока).

    В общем случае, для встраивания JVM в программу ее необходимо создать и проинициализировать, присоединить, если это необходимо, к какому-либо потоку, а по окончании работы с JVM удалить ее из памяти процесса. После того как JVM создана и получен интерфейсный указатель, можно использовать любые JNI-функции.

    Рассмотрим пример С++-кода, который создает JVM в процессе своей работы и вызывает статический метод JAVA-класса. Ниже приведены исходные тексты JAVA-класса и C++-кода:

    // Файл INVOCATIONAP.JAVAI
    PUBLIC CLASS INVOCATIONAPI {
        STATIC VOID TEST() {
            SYSTEM.OUT.PRINTLN("HELLO FROM JAVA CODE");
        }
    }
    // Файл INVOCATIONAPI.CPP
    #INCLUDE <JNI.H>
    VOID MAIN() {
        JAVAVM* JVM;
        JNIENV* ENV;
        // инициализация
        JDK1_1INITARGS VMARGS;
        JNI_GETDEFAULTJAVAVMINITARGS(&VMARGS);
        VMARGS.CLASSPATH = "C:/JDK1.1/LIB/CLASSES.ZIP;C:/TEST/NATIVE";
        // создание JVM
        JNI_CREATEJAVAVM(&JVM, &ENV, &VMARGS);
        // получение ссылки на класс INVOCATIONAPI
        JCLASS CLS = ENV->FINDCLASS("INVOCATIONAPI");
        // вызов статического метода TEST
        JMETHODID MID = ENV->GETSTATICMETHODID(CLS, "TEST", "()V");
        ENV->CALLSTATICVOIDMETHOD(CLS, MID);
        // удаление JVM
        JVM->DESTROYJAVAVM();
    

    Для компиляции приведенной программы на платформе WIN32 необходимо выполнить следующие команды (предполагается, что переменные окружения PATH, LIB, INCLUDE и CLASSPATH установлены верно и исходные файлы находятся в каталоге C:\TEST\NATIVE):

    C:\TEST\NATIVE\ JAVAC INVOCATIONAPI.JAVA
    C:\TEST\NATIVE\ CL -W3 -NOLOGO INVOCATIONAPI.CPP -FEINVOCATIONAPI
     -TP -MD -LINK
                -NOLOGO JAVAI.LIB
    

    А для запуска программы:

    C:\TEST\NATIVE\ INVOCATIONAPI
    HELLO FROM JAVA CODE
    C:\TEST\NATIVE\
    

    На первый взгляд, наличие JNI и полная публикация его спецификаций может привлечь разработчиков к написанию непереносимого JAVA-кода, что, в свою очередь, может значительно снизить эффективность применения технологии JAVA. Однако на самом деле JNI способствует обратному процессу.

    Практически для любого приложения можно совершенно точно определить необходимость в многоплатформенном исполнении. Для систем, которые не нуждаются в многоплатформенности, JNI предоставляет инфраструктуру, с помощью которой JAVA-приложение может взаимодействовать с операционной системой и аппаратурой, в среде которых оно исполняется. Таким образом, JNI является естественным дополнением JAVA-технологии. Он позволяет использовать ее как для создания переносимых (клиентских) приложений, так и для создания высокопроизводительных (серверных) систем, использующих всю специфику конкретной платформы и аппаратуры, сохраняя в то же время главное достоинство JAVA - современный объектно-ориентированный подход.

Автор: Никита Иванов
Информация взята с сайта Мир Internet

 


Версия для печати

Назад

Проверить домен

ru  com net

Новости компании

02.04.10
Технические работы на сервере!

В пятницу 3-го апреля 2009 г. возможен кратковременный перерыв в работе сервера с 17 до 18 часов в связи с проводимыми техническими работами. ...


08.09.08
ВНИМАНИЕ!!! Пользователям сервера PRO-HOSTING!

В связи с технической необходимостью, мы вынуждены перевезти оборудование из датацентра СТЕК в новый, более современный и удобный датацентр на Остаповском проезде. Переезд оборудования будет осуществл...


15.04.08
Новая рекламная акция нашей компании.

Вас не устраивает Ваш хостинг провайдер, но деньги оплачены и жалко их терять. Мы готовы предоставить Вам альтернативу. Выбрав нас, Вы получаете возможность перехода от своего старого хостинг провайд...


01.02.08
Специальная акция "Автоматизируй свой сайт"

Скидка 30% на покупку системы управления сайтом SSPRO. Установка системы управления производится бесплатно. Подробнее о системе управления сайтом смотрите на странице: Система управления сайтом ...


20.12.07
С новым 2008-м годом

Поздравляем всех клиентов и посетителей сайта с новым 2008 годом, желаем успехов в новом году, здоровья и счастья. Коллектив ООО " ССПРО ХОСТИНГ"  ...


06.02.07
Профилактические работы на сервере

Уведомляем Вас о том, что 06/02/2007 на сервере ONLINEHOST.RU администраторами датацентра "STACK" запланировано отключение электропитания, связанное с профилактическими работами на монтажной стойке. Н...



Ваш проект:


Коммерческий
Коммерческий
Коммерческий


2002-2009 (с) ООО "ССПРО Хостинг"
+7 495 77-88-33-9  Карта сайта,
Разработка сайта Cве-Арт | Cms Sspro