Подключить dll к java
Шаги для запуска кода из JNI
Шаг 1. Создадим новый проект ex: JNI_aymaletdinov_roman.
Шаг 2. Создадим класс, у которого будут native-методы, и назовём его AwesomeLib.
System.loadLibrary("nativeLib"); — это статический метод, который загружает native-библиотеку из файловой системы в память и делает её экспортированные функции доступными для нашего Java-кода. То есть мы загружаем файл на С/С++, который будет выполнять сложные вычисления. Однако nativeLib мы ещё не создали, сделаем это позже.
Шаг 3. Следующим шагом нам необходимо объявить метод, помеченный ключевым словом native. Он не имеет реализации в Java, напишем её на C++.
Шаг 4. Вызовем из Main нашу библиотеку, которая что-то делает в native-коде .
Шаг 5. На Java мы всё сделали! Теперь начинается что-то непривычное: нужно обязательно установить MinGW-w64, иначе не на чем будет компилировать нативный код. При установке выберите x86-64 и пропишите bin переменные среды path.
Шаг 6. Затем необходимо написать реализацию нашего нативного метода на C++. В этом языке объявление и реализация обычно хранятся в файлах .h и .cpp соответственно. Открываем консоль; переходим в папку, в которой будут лежать native-файлы; генерируем заголовок для натива командой javac -h . absolutePath/MyClass.java.
После выполнения команды будет создано два файла: .h и .class .
Декомпилированный .class мало интересен, а вот .h — что-то не из нашего JVM-мира. На самом деле всё очевидно: наш метод сгенерировался таким, каким он будет в С++. При этом имя функции генерируется автоматически с использованием полного имени пакета, класса и метода. Кроме того, мы получаем два параметра, передаваемых нашей функции:
указатель на текущий JNIEnv;
Java-объект (AwesomeLib), к которому привязан метод.
Шаг 7. Следующий шаг — создание .cpp . То есть мы сами создаём файл с расширением .cpp и копируем из .h контракт метода. Я назвал файл тем же именем, что и Java-класс: AwesomeLib.cpp .
Шаг 8. Затем наш нативный код надо скомпилировать. Когда мы выполним в консоли команду g++ -c -I"C:\Program Files\Java\jdk-12.0.1\include" -I"C:\Program Files\Java\jdk-12.0.1\include\win32" AwesomeLib.o.cpp -o AwesomeLib.o , появится ещё один файл: .o .
Смотрим на дерево проекта и видим новый файл:
Шаг 9. Осталось совсем немного. Теперь нужно сгенерировать .dll с названием нативной библиотеки, которое мы указали в статике в Java. В консоли выполняем команду: g++ -shared -o nativeLib.dll AwesomeLib.o -Wl,--add-stdcall-alias .
Смотрим, в IDE появился ещё один сгенерированный файл.
Шаг 10. Всё! Хочется запустить нашу программу с нативным кодом, но IDEA сейчас этого сделать не сможет. Она ничего не знает про С++, следовательно, для запуска воспользуемся консолью:
java -cp . -Djava.library.path="[Абсолютный путь до папки, где лежит dll]" Main.java
Обратите внимание, что я перед запуском выполнил команду cd .. для того, чтобы быть в той же папке, где лежит запускаемый мною файл Main .
2. Обзор
Смотреть сегодняJavaВо время многопоточного программирования я обнаружил, что в классе Thread есть несколько нативных методов. Я никогда раньше не видел этот метод, поэтому мне было любопытно, изучил некоторую информацию и разобрал ее для запоминания.
Как запустить проект из IDEA, а не через консоль?
Так как IDEA по умолчанию не знает ни о каких .dll , она не сможет запустить наш проект по нажатию на треугольник “Run”. Чтобы запустить проект, нужно прописать VM options в меню “Edit configurations”.
У нас появится поле VM options, и мы добавляем Djava.library.path full-width ">
Вот теперь точно всё! Можно запускать проект из IDEA и радоваться жизни.
3.3. Использовать javah -jni имя класса java для генерации заголовочного файла с расширением h
Генерируется после выполнения вышеуказанной командыD:\JNI\HelloWorld.hФайл со следующим содержимым:
Здесь мы можем понять это: Этот h-файл эквивалентен нашему интерфейсу в Java. Здесь мы объявляем метод Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); / C ++ программа должна использовать здесь то же имя метода
Содержание
Шаги для запуска кода из JNI;
Run from JetBrains IDEA.
More from my site
- February 23, 2011
- By michal.wrobel , JNA, Programming, WindowsjavaJNAnative codeprogramming
- 65 Comments
How to capture content of eclipse Console window (web tomcat application)?
[…] of Memory and Pointer JNA objects. Example covering such case is provided in my another article: How to call/invoke external DLL library method/function from Java code? JNA, Java, Programmingjava, JNA, native code ← How to call/invoke external DLL library […]
Thank you soo much. took me a WHOLE day to find this post. Lots of examples of using JNA but none that shows exactly how it will be done in Real Life. you Polish guys are amazing! Dzienki! Will call u for beer when I come to poland next time!
hahaha, thank you for appreciating my content. I’ll keep your word about the beer, but linking me will be also good for now in favour 🙂
Did u see that I posted this article on dzone? Check here
You should have more hits today….lol
didn’t check my stats today. thank you very much! 😉
nice news about javaFX redist btw, thought there’s no hope about it
This is the best one page example of using JNA I have found so far. Got me started in about 5 minutes, regretfully, I got stuck in next 5 minutes 🙁 🙁
Here are immediate 2 issues:
(1) Does JNA handle mangled names? What I have is the DLL and the interface definition (ie. header files). The problem is that the function defined as
int* func(int) is mangled to int* _func@4(int) and Java does not like the ‘@’ in the name of the method.
(2) Callbacks. The native lib uses them all over the place. In C++ it is easy. DLL provides the interface to define callbacks, so all the app has to do is to create them and pass the pointer to the API. When the event which has the associated callback occurs, the C++ app gets the information. Can something the same be done between the app written in Java and the DLL?
nice article.. and easily explained too..
thankx man , u just saved my day… 🙂
I am new to Java and I find using the compact style documentation like those two a bit difficult, hence my search for sample code.
I looked at some callback samples and I do not see how I can bind my own callback method (written in Java) with the DLL. All I have in the DLL is the API to specify the callback by feeding in the pointer to the callback function. Does this mean that the callback must be a C function?
Was link about solving problems with Mangled names in JNA helpful for you?
I am new to accessing DLLs from Java using JNA. I need to access a methods from a class within the DLL and can not do this by just calling the library as I can seem to work out how to access a class I.e. the DLL is called CDrawControl.dll, but the class within the DLL I need to access is DrawCtl. So I need to get and instance of the DrawCtl class.
So all in all, how to I reach this method in the DLL?
It is probably something very simple I am missing.Thanks for your help in advance.
Nice job, simple strait example for JNA utilization, thanks for your effor, easing ours 😉
I am trying to demo run your samle program, I am through most of the hurdles (configuring library path, various java.lang.UnsatisfiedLinkError), Now struck at error “Unable to load library ‘simpleDLL’: The specified module could not be found.” please guide me through this abt how to resolve this.
Regards, Mithun PG
Hi Even I am also getting the same error “module could not be found” if you found the solution please let me know.
Greats, but I have is error Exception in thread “main” java.lang.UnsatisfiedLinkError: Unable to load library ‘simpleDLL’ and the library is the current folder.
Not sure what I’m doing wrong. Have an even simpler example. Can’t find the methods at runtime. Is there any problem using Netbeans / mingw compiler?
QnAudio.cpp, compiled to a dll which is found by the java program:
using namespace std;
int QnAudio::getData(int i) return data[i];
>
void QnAudio::setData(int i, int input) data[i] = input;
>
>;
Guts of the java program:
public class NewFrame extends java.awt.Frame
public interface QnAudio extends Library QnAudio INSTANCE = (QnAudio) Native.loadLibrary(
“C:/Documents and Settings/Al Gerheim/My Documents/NetBeansProjects/QnAudio/dist/Debug/MinGW_TDM-Windows/libQnAudio”,
// “libQnAudio”,
QnAudio.class);
int getData(int i);
void setData(int i, int input);
>
public static void main(String args[])
QnAudio qn_Audio = QnAudio.INSTANCE;
qn_Audio.setData(0, 1); // error at this statement, function not found.
qn_Audio.setData(1, 5);
qn_Audio.setData(2, 10);
int i = qn_Audio.getData(0);
i = qn_Audio.getData(1);
i = qn_Audio.getData(2);
i = 1000;
HI i am getting the following exception when invoking the external DLL file.
Exception in thread “main” java.lang.UnsatisfiedLinkError: Unable to load library ‘C:/Users/kumargud/Desktop/JNA/simpleDLL/’: The specified module could not be found.
Hi,
i have a c dll method in which the function signature is: int func(HANDLE handle, char *Info);
The parameter [out]Info is an output parameter. Could you let me know how to call this function. I tried using Callback in jna but not able to get the proper value of info.
I m using jna to call this function.
Hello! Did you try to run this with 64-bit DLL? Weird, because I can’t transmit parameter from java code to C method (in dll), but I can get the return value in java code from dll methods.
Strange. No I haven’t tried 64-bit DLL’s only 32-bit. Is your JVM 32 or 64 bit?
Для прикладного программирования средств Java в подавляющем большинстве случаев хватает. Однако иногда возникает необходимость подключить к программе ряд системных вызовов. Либо обеспечить доступ к библиотекам, написанным на других языках программирования. Для таких целей в Java используются методы, объявленные с модификатором native – "родной". Это слово означает, что при выполнении метода производится вызов "родного" для конкретной платформы двоичного кода, а не платформо-независимого байт-кода как во всех других случаях. Заголовок "родного" метода описывается в классе Java , а его реализация осуществляется на каком-либо из языков программирования, позволяющих создавать динамически подключаемые библиотеки ( DLL – Dynamic Link Library под Windows , Shared Objects под UNIX -образными операционными системами).
Правило для объявления и реализации таких методов носит название JNI – Java Native Interface .
Объявление "родного" метода в Java имеет вид
Модификаторы native ВозвращаемыйТип имяМетода(список параметров);
Тело "родного" метода не задается – оно является внешним и загружается в память компьютера с помощью загрузки той библиотеки, из которой этот метод должен вызываться:
При этом имя библиотеки задается без пути и без расширения. Например, если под Windows библиотека имеет имя myLib.dll , или под UNIX или Linux имеет имя myLib.so, надо указывать System.loadLibrary("myLib") ;
В случае, если файла не найдено, возбуждается непроверяемая исключительная ситуация UnsatisfiedLinkError .
Если требуется указать имя библиотеки с путем, применяется вызов
System . load ("ИмяБиблиотекиСПутем");
Который во всем остальном абсолютно аналогичен вызову loadLibrary .
После того, как библиотека загружена, с точки зрения использования в программе вызов "родного" метода ничем не отличается от вызова любого другого метода.
Для создания библиотеки с методами, предназначенными для работы в качестве "родных", обычно используется язык С++. В JDK существует утилита javah.exe, предназначенная для создания заголовков C++ из скомпилированных классов Java . Покажем, как ей пользоваться, на примере класса ClassWithNativeMethod . Зададим его в пакете нашего приложения:
Для того, чтобы воспользоваться утилитой javah, скомпилируем проект и перейдем в папку build\classes. В ней будут располагаться папка с пакетом нашего приложения java_example_pkg и папка META-INF. В режиме командной строки выполним команду
- задавать имя класса необходимо с полной квалификацией, то есть с указанием перед ним имени пакета. В результате в папке появится файл java_example_pkg_ClassWithNativeMethod.h со следующим содержимым:
Функция Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod(JNIEnv *, jobject) , написанная на C++, должна обеспечивать реализацию метода myNativeMethod() в классе Java . Имя функции C++ состоит из: префикса Java , разделителя "_", модифицированного имени пакета (знаки подчеркивания "_" заменяются на "_1"), разделителя "_", имени класса, разделителя "_", имени "родного" метода. Первый параметр JNIEnv * в функции C++ обеспечивает доступ "родного" кода к параметрам и объектам, передающимся из функции C++ в Java . В частности, для доступа к стеку. Второй параметр , jobject , – ссылка на экземпляр класса, в котором задан "родной" метод, для методов объекта, и jclass – ссылка на сам класс – для методов класса. В языке C++ нет ссылок, но в Java все переменные объектного типа являются ссылками. Соответственно, второй параметр отождествляется с этой переменной.
Если в "родном" методе имеются параметры, то список параметров функции C++ расширяется. Например, если мы зададим метод
то список параметров функции C++ станет
А тип функции станет jint вместо void .
В реализации метода требуется объявить переменные. Например, если мы будем вычислять квадрат переданного в метод значения и возвращать в качестве результата значение параметра, возведенное в квадрат (пример чисто учебный), код реализации функции на C++ будет выглядеть так:
Отметим, что при работе со строками и массивами для получения и передачи параметров требуется использовать переменную env . Например, получение длины целого массива, переданного в переменную jintArray intArr , будет выглядеть так:
jsize length=(*env)->GetArrayLength(env, intArr);
Выделение памяти под переданный массив :
jint *intArrRef=(*env)->GetIntArrayElements(env, intArr,0);
Далее с массивом intArr можно работать как с обычным массивом C++. Высвобождение памяти из-под массива:
(*env)->ReleaseIntArrayElements(env, intArr, intArrRef ,0);
Имеются аналогичные функции для доступа к элементам массивов всех примитивных типов : GetBooleanArrayElements, GetByteArrayElements,…, GetDoubleArrayElements . Эти функции копируют содержимое массивов Java в новую область памяти, с которой и идет работа в C++. Для массивов объектов имеется не только функция GetObjectArrayElement , но и SetObjectArrayElement – для получения и изменения отдельных элементов таких массивов.
3.1. Напишите класс java с собственным методом объявления: HelloWorld.java
Подробное объяснение использования Java JNI для вызова локальной динамической библиотеки
Определение нативного метода:
Проще говоря, нативный метод - это интерфейс для Java для вызова не-Java-кода. Собственный метод - это метод Java: реализация этого метода реализована не на языке Java, таком как C. Эта функция не уникальна для Java. Многие другие языки программирования имеют этот механизм. Например, в C ++ вы можете использовать extern "C", чтобы сообщить компилятору C ++ о вызове функции C.
Как виртуальная машина запускает собственный метод:
Мы знаем, что когда класс используется в первый раз, байт-код этого класса будет загружен в память и будет перезагружен только один раз. При входе загруженного байт-кода поддерживается список всех дескрипторов методов класса. Эти дескрипторы методов содержат такую информацию, как: где хранится код метода, какие у него параметры и дескриптор метода (открытый Класс) и тд.
Если дескриптор метода имеет native, блок дескриптора будет иметь указатель на реализацию метода. Эти реализации находятся в некоторых файлах DLL, но они загружаются операционной системой в адресное пространство Java-программы. Когда класс с собственным методом загружен, связанная с ним DLL не загружается, поэтому указатель на реализацию метода не устанавливается. Эти библиотеки DLL загружаются до вызова собственного метода, что достигается путем вызова java.system.loadLibrary ().
3.2 Используйте команду javac для компиляции написанного класса java
Генерируется после выполнения вышеуказанной командыD:\JNI\HelloWorld.classфайл
2.2 Введение в JNI
Нативный метод реализован JNI в Java. JNI - это аббревиатура для собственного интерфейса Java. Начиная с Java 1.1 стандарт Java Native Interface (JNI) стал частью платформы Java, что позволяет коду Java взаимодействовать с кодом, написанным на других языках.JNI изначально был разработан для нативных скомпилированных языков, особенно C и C ++, но он не мешает вам использовать другие языки, если поддерживается соглашение о вызовах.Использование Java для взаимодействия с нативным скомпилированным кодом часто теряет переносимость платформы. Однако существуют ситуации, когда это приемлемо или даже необходимо, например использование некоторых старых библиотек для взаимодействия с оборудованием и операционной системой или для повышения производительности программы. Стандарт JNI по крайней мере гарантирует, что нативный код будет работать с любой реализацией виртуальной машины Java.
В настоящее время Java и DLL взаимодействуют с тремя основными технологиями: jni, jawin и jacob.Jni(Java Native Interface) - это технология, предоставляемая Sun для взаимодействия с нативными методами в системе (в Windows \LinuxВ системе реализована взаимная модуляция Java и нативный метод). В настоящее время это может быть реализовано только c / c ++. Последние два являются проектами с открытым исходным кодом на sourceforge, и они также являются библиотекой приложений в системе Windows, основанной на технологии jni. Jacob (Java-Com Bridge) предоставляет возможность Java-программам вызывать методы в COM-объекте Microsoft. В дополнение к объекту com, jawin (проект интеграции Java / Win32) также может использовать методы в динамической библиотеке ссылок win32-dll.С точки зрения функции: jni >> jawin> jacob, его примерная структура выглядит следующим образом:
С точки зрения простоты использования, верно и обратное: jacob> jawin >> jni.
JVM инкапсулирует различныеОперационная системаВ то же время фактических различий предоставляется технология JNI, так что разработчики могут вызывать библиотечные функции, реализуемые технологиями, связанными с операционной системой, через Java-программы (код), чтобы взаимодействовать с другими технологиями и системами, и использовать функции систем, реализованных другими технологиями. В то же время другие технологии и системы также могут использовать соответствующий собственный интерфейс, предоставляемый jni, для открытия функций, реализованных в системе Java-приложений.
В системах Windows, как правило, исполняемые приложения основаны на собственной структуре PE, а jvm on windows также реализуется на основе собственной структуры. Системы приложений Java построены на основе jvm.
Jni можно рассматривать как режим прокси для самого приложения. Разработчикам необходимо использовать c / c ++ для реализации агентской программы (jni-программы) для фактического управления целевой нативной функцией.В java-программах jvm косвенно вызывает целевую нативную функцию, загружая и вызывая эту jni-программу.
3.JNI пример
Ниже приведены все операции в каталоге:D:\JNI Под капотом это имеет преимущество в простоте управления. Другое требование состоит в том, что наш класс java не содержит имени пакета. В настоящее время я тестирую только те типы, которые не включают имя пакета.
2.3 JN шаги написания
- Напишите класс java с методом, объявленным как native, и сгенерируйте файл .java.
- Используйте команду javac, чтобы скомпилировать написанный класс java и сгенерировать файл .class
- Используйте javah -jni javaИмя классаСгенерировать заголовочный файл с расширением h, то есть сгенерировать .h файл
- Используйте C / C ++ (или другой язык программирования) для реализации локальных методов и создания реализаций файлов .h, то есть создавайте файлы .cpp для реализации методов в файлах .h
- Генерация файлов C / C ++ в динамически подключаемую библиотеку и создание файлов DLL
9 Answers 9
Edit: UnsatisfiedLinkError: Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native -- it seems like you are using a JNI function which does not exist.
One problem you have is: System.load("D:\mydll.dll"); should be System.load("D:\\mydll.dll"); or System.load("D:/mydll.dll");
I have had more success with System.load, but loadlibrary is better designed for multiplatform. It figures out the extension for you.
Check out how to properly set up the native dependencies here. Additionally, make sure you use the correct JVM: in my case, the DLL was not found because it was a 32 bit DLL, but I used the x64 JVM!
Using System.loadLibrary("mydll") works fine, you can also use that one. If you used javah and you think with your DLL everything is fine, there are two possibilies:
-
The JVM does not find your DLL: In this case, your java library path is not correct (which I doubt) and you should probably set it to . and place your DLL in the current working dir.
The JVM does not find a DLL your DLL depends on: If you have any dependent libraries in your DLL, they are NOT searched by the JVM, but by Windows itself. And Windows does not know the java.library.path , so it will look in the system PATH variable for those. If you have the possibility, you can set the system PATH variable to the location of your DLLs before starting the JVM and everything will be fine. Or you can load all your DLLs using the JVM like this
System.loadLibrary("dll_1");
System.loadLibrary("dll_2");
System.loadLibrary("dll_3");
Всем привет! Меня зовут Роман Аймалетдинов и я разрабатываю клиентское приложение Ситимобил. Решил написать небольшую серию из трех статей по JNI, так как технология используется редко, но иногда она бывает очень полезной. Несмотря на то, что я разрабатываю классические приложения под Android, иногда хочется посмотреть технологии рядом со своей специализацией.
3.5. Создать динамическую библиотеку ссылок из файла, написанного на C / C ++
волиD:\Program Files\Java\jdk1.6.0_26\include\jni.hиD:\Program Files\Java\jdk1.6.0_26\include\win32\jni_md.hЭти два файла копируются вD:\JNI\Справочник. Тот же каталог, что и HelloWorldImpl.cpp, структура каталога показана ниже:
Заключение
Краткий список шагов, чтобы было проще вспоминать тем, кто знает, читал и делал, но что-то подзабыл и нужна шпаргалка:
Установить MinGW-w64. При установке выбрать x86-64 и прописать bin переменные среды path.
Создать NativeLib.java с native-методами.
Перейти в консоли в папку (ex: src), в которую хотите сохранить сгенерированные файлы.
Выполнить javac -h . AwesomeLib.java .
Выполнить g++ -c -I"C:\\Program Files\\Java\\jdk-12.0.1\\include" -I"C:\\Program Files\\Java\\jdk-12.0.1\\include\\win32" AwesomeLib.cpp -o AwesomeLib.o .
Выполнить g++ -shared -o nativeLib.dll AwesomeLib.o -Wl,--add-stdcall-alias .
Запустить программу: java -cp . -Djava.library.path=”Путь до папки с .dll" Main (или через студию).
Если вы внесли изменения в .cpp , то заголовок пересоздавать не нужно, но если вы изменили контракт метода, то придётся начинать с этапа javac -h . . .
В следующей части я расскажу про более сложные методы в JNI, про передачу List и вызов Java из C++.
Java’s JVM allows you to do many smart things but sometimes you may be forced to directly use external library or writing code in pure java would be very time-consuming comparing it with something more low-leveled. I stumbled upon such a problem and had to use a .dll driver from a hardware provider. Of course I googled it and didn’t find much info, and what I’ve found mostly concerned about JNI (Java Native Interface). I would like to tell you about JNA which is fast and simple to use in aforementioned task.
So, how does it work? The only thing you have to do is to download and import JNA (Java Native Access) to your project and write a simple class.
Hereunder you can analyse a simple Java program which uses a sample .dll. You can download my java code and .dll library sources later.
Java code:
Mappings table
Not every native type maps directly to Java type, furthermore a class representing pointers had to be introduced. You can read a handy type mapping table below:
Downloads:
-
– ready to use Visual Studio 2010 project. You can alter it to continue experimenting with invoking DLL methods of library attached to the Netbeans project. – ready to use NetBeans 6 project using example code explained in this article with appropriate jars and DLL library attached – link to official JNA libraries download page
Useful links:
DLL library C++ functions source :
3.8 Класс получает результат
Запустите в cmd:
Детали показаны на следующем рисунке:
Использование Java для взаимодействия с нативным скомпилированным кодом часто теряет переносимость платформы. Однако в некоторых случаях это приемлемо или даже необходимо. Например, используйте некоторые старые библиотеки для взаимодействия с оборудованием и операционной системой или для повышения производительности программы. Стандарт JNI по крайней мере гарантирует, что нативный код может работать в любой среде виртуальной машины Java. Не сплетничайте, идите прямо к примеру.
Этот пример основан на платформе Windows, сначала генерируется целевая динамическая библиотека dll: Lib4JNI.dll
Метод add экспортируется из динамической библиотеки Lib4JNI. JNI используется в этом примере.
Следующее, что нужно сделать, это использовать промежуточный (или прокси) dll для вызова целевой динамической библиотеки (в данном примере целевой динамической библиотекой является Lib4JNI.dll). В Java целевая динамическая библиотека не может быть вызвана напрямую. Следовательно, существует необходимость в посреднике (или агенте). Локальный код Java сначала вызывает промежуточную (или агент) динамическую библиотеку, а затем промежуточная (или агент) динамическая библиотека вызывает целевую динамическую библиотеку.
Мы даем посреднику имя с именем Lib2Invoke. Процесс генерации этого промежуточного dll более сложен, ниже мы используем действие декомпозиции для подробного объяснения.
Первый шаг: необходимо создать вызывающий код нативной Java.
Сохраните приведенный выше код как TextJNI.java.
Шаг 2: скомпилируйте с javac. javac TestJNI.java
Третий шаг: используйте javah для создания заголовочного файла промежуточной (или прокси) динамической библиотеки. javah TestJNI После запуска сгенерируйте TestJNI.h Файл, пример файла, сгенерированного в этом примере, выглядит следующим образом:
Шаг 4. Создайте промежуточную (или агентскую) динамическую библиотеку
Почему он начал генерировать dll-посредник? Потому что нам нужен TestJNI.h, сгенерированный на предыдущем шаге, в качестве заголовочного файла промежуточной библиотеки dll. Пожалуйста, обратитесь к коду для деталей.
После компиляции генерируется необходимая промежуточная (или прокси) динамическая библиотека Lib2Invoke.dll 。
Шаг 5: Улучшение собственного кода вызова Java.
После завершения компиляции поместите созданный файл класса, а также Lib4JNI.dll и Lib2Invoke.dll в каталог.
Шаг шестой: выполнение java TestJNI
Результат будет выведен после успешного выполнения.
Другой альтернативой является JNative. С характером программиста говорите меньше и пишите больше:
Преимущество: нет промежуточных dll, нет промежуточного заголовочного файла .h
Недостатки: (Недостатки неточны, просто ради выравнивания.) Требуется поддержка внешнего пакета.
Давайте поговорим об использовании JNI на платформе Linux. Основные шаги такие же, как указано выше. Основной пример кода приведен ниже.
1. Вызывающая часть Java
2. Генерация динамической части библиотеки
3.Скомпилируйте и сгенерируйте динамическую библиотеку
Здесь есть два очень важных места, поэтому обратите внимание:
1. Для System.loadLibrary("NativeAgent");
В Linux, если имя файла вывода динамической библиотеки libNativeAgent.so 。
То есть, если System.loadLibrary("XXX") Затем при экспорте динамической библиотеки имя динамической библиотеки libXXX , В противном случае он сообщит об ошибке:
2.Linux обычно используется по умолчанию java.library.path в / usr / lib Далее. Вы также можете передать параметры виртуальной машины самостоятельно -Djava.library.path=/usr/lib Явно указано, или путем добавления переменных среды export LD_LIBRARY_PATH=~/JavaNativeTest:$LD_LIBRARY_PATH
but again getting the same problem, could someone can help?
I tested my classpath with this code System.getProperty("java.class.path") and placed the dll on that specific path. After that, I am getting error "Can't find dependent libraries". How can i check which libraries it is asking :S. I am using some thirdparty Dll.
Что такое JNI?
JNI — это интерфейс, позволяющий из Java вызывать нативные функции. Например, метод С++, который что-нибудь делает. Допустим, мы пишем большую программу на простом и любимом Java или Kotlin, и нужно реализовать задачу коммивояжера для нашего клиента. Или мы пишем генетический алгоритм, который ищет что-то в большом объёме данных, и так уж вышло, что у нас есть замечательная реализация на С++. Особенно часто я слышу про JNI в gamedev- и в automotive-проектах. Однажды я работал в таком, будучи ещё интерном, и, точно не помню, но в общих чертах на С++ было много низкоуровневого кода по обработке потока данных, получаемого со спутника. JNI позволяет вручную управлять памятью. Можно написать фрагмент кода на C/С++, и при необходимости дёргать нативный метод и получать из него результат вычисления.
И ещё по поводу производительности: мы все знаем, что С/С++ побыстрее будут, и тогда получается, что мы сможем оптимизировать наши алгоритмы на Java, переписав их на C++. (спойлер: не надо, скорее всего, будет работать медленнее). Некоторые авторы в интернете говорят про увеличение производительности, поэтому в своей третьей статье я приведу тесты JNI/NDK и мы сможем сверить производительность.
Также для Android есть инструмент NDK, который всё про то же — запуск нативного кода и увеличение производительности отдельных алгоритмов.
NDK — Native Development Kit (для Android).
JNI — Java Native Interface (общий интерфейс).
3.4 Реализация нативных методов с использованием C / C ++
Создайте HelloWorldImpl.cpp со следующим кодом:
3.7 Запустите cl / LD D: \ JNI \ HelloWorldImpl.cpp, чтобы получить файл HelloWorldImpl.dll
Я использую Visual Studio 2010. Чтобы использовать команду cl, необходимо открыть командную строку Visual Studio, как показано на следующем рисунке:
Затем введите следующую команду в командной строке
Детали показаны на следующем рисунке:
После выполнения вышеупомянутой команды мы можем видеть четыре файла, сгенерированные в C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC:
- HelloWorldImpl.dll
- HelloWorldImpl.exp
- HelloWorldImpl.lib
- HelloWorldImpl.obj
Нужно скопировать файл HelloWorldImpl.dll вD:\JNI\Справочник.
2.1.использование родного ключевого слова
Native используется при совместной разработке с C ++!Используйте ключевое слово native, чтобы указать, что этот метод является встроенной функцией, то есть этот метод реализован на языке C / C ++, скомпилирован в DLL и вызывается из Java., Реализация этих функций находится в DLL и не включена в исходный код JDK. Вы не должны видеть это. Они разные для разных платформ. Это также основной механизм Java.На самом деле, Java вызывает разные нативные методы на разных платформах для доступа к операционной системе. В целом:
- Native используется для сотрудничества между Java и другими языками (такими как C ++), то есть реализация функций после native не написана на Java.
- Поскольку ни один из них не является Java, не говоря уже о его исходном коде, нам просто нужно знать, что этот метод был реализован.
- Собственный означает сообщить операционной системе, что вы должны реализовать эту функцию для меня, потому что я хочу использовать ее. Таким образом, функции встроенного ключевого слова реализованы операционной системой, и Java может вызываться только.
- Java является кроссплатформенным языком. Поскольку он является кроссплатформенным языком, цена за него заключается в том, чтобы пожертвовать некоторым контролем над нижележащим уровнем. Для достижения контроля над нижележащим уровнем Java нужна помощь других языков. Это роль нативного языка.
Читайте также: