Сегодня мы рассмотрим такую тему, как использовать Java методы при помощи JNI.
На самом деле все очень просто. Давайте сразу начнем с примера:
Допустим у нас есть некое Java приложение на котором есть простая кнопка и при нажатии на эту кнопку будет исполняться некий код.
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
File MyFile = new File("D:\\Sample\\text.txt");
MyFile.delete();
}
Как мы видим в событии клика на кнопку будет исполняться просто код для удаления файла.
На Java все выглядит ясно и просто, но как же это будет выглядеть на Delphi с использованием JNI. На самом деле все проще чем кажется.
Для этого нам нужно разобрать заглянуть и в класс File, который находится по адресу java.io.File. Из этого класса нам нужно:
— Получиться сам класс
— Получить функцию delete, а именно Имя и Дескриптор.
— Заполнить аргумент для данной функции
— Использовать ее.
И так приступим.
Самой удобной утилитой для разборки класса на чечки на мой взгляд является DirtyJOE. КИдаем туда класс File и в методах ищем нашу функцию. Находим ее Имя и Дескриптор. Переходим в Delphi и создаем там такую функцию.
function JVM_DeleteFile(JNIEnv: PJNIenv; FilePath: String): Boolean;
Обратим внимание в DirtyJOE что функция delete возвращает назад Boolean.
Тут все просто: Название функции и объявляем переменные.
Давайте объявим переменные для работы нашего кода:
var
FileClass: JClass;
Delete, Init: JMethodID;
FileObj: JObject;
Args: array[0..0] of JValue;
Это все то что далее мы будем искать и использовать.
Теперь давайте заполним Аргументы
Args[0].l:= WideToJString(jnienv, PwideChar(WideString(FilePath)));
Обратите внимание что JString мы передаем как JObject (По сути JString это и есть JObject)
Ну а далее мы будем получать класс и метод delete:
FileClass:= jnienv^.FindClass(jnienv, 'java/io/File');
Delete:= jnienv^.GetMethodID(jnienv, FileClass, 'delete', '()Z');
А теперь не мало важный этап. Обратите внимание что в Java коде мы создаем новый объект new File и в Delphi нам требуется сделать тоже самое:
Init:= jnienv^.GetMethodID(jnienv, FileClass, '<init>', '(Ljava/lang/String;)V');
FileObj:= jnienv^.NewObjectA(jnienv, FileClass, Init, @Args);
И нам по сути осталось только использовать сам метод delete:
jnienv^.CallBooleanMethod(jnienv, FileObj, Delete)
Но, так как вначе всего мы обратили внимание что функция delete возвращает Boolean, то давайте же сделаем проверку на возврат True и False:
if jnienv^.CallBooleanMethod(jnienv, FileObj, Delete) = 1 then
Result:= True
else
Result:= False;
Ну и давайте посмотрим на эту функцию в готовом виде:
function JVM_DeleteFile(JNIEnv: PJNIenv; FilePath: String): Boolean;
var
FileClass: JClass;
Delete, Init: JMethodID;
FileObj: JObject;
Args: array[0..0] of JValue;
begin
Args[0].l:= WideToJString(jnienv, PwideChar(WideString(FilePath)));
FileClass:= jnienv^.FindClass(jnienv, 'java/io/File');
Delete:= jnienv^.GetMethodID(jnienv, FileClass, 'delete', '()Z');
Init:= jnienv^.GetMethodID(jnienv, FileClass, '<init>', '(Ljava/lang/String;)V');
FileObj:= jnienv^.NewObjectA(jnienv, FileClass, Init, @Args);
if jnienv^.CallBooleanMethod(jnienv, FileObj, Delete) = 1 then
Result:= True
else
Result:= False;
end;
Заключение.
На самом деле все проще чем кажется. С помощью JNI можно использовать любой Java метод. В этом примере, если вы внимательно смотрели то увидели что я использовал запись Аргументов типа JValue и как нужно их использовать. Это очень важный момент.
andyshark1974
Я что-то не понял — через тернии к звездам? Если это пример использования JNI, то можно было подобрать вариант который не вызывает интуитивного отторжения?
sshikov
Менее бесполезный (в смысле, в Дельфи же можно удалять файлы без JNI, правда)?
Mr_Dan Автор
Это демонстрация того, что в запущенном Java приложении при помощи JNI можно использовать любой Java метод.
sshikov
Чтобы использовать из Дельфи методы через JNI, нужно сначала запустить JVM — а это дорого. Для такого применения, как удалить файл — чрезмерно дорого. Поэтому этот пример — дурь.
Mr_Dan Автор
Никто еще не запрещал DLL. Легко и просто засунуть все это в DLL, там сделать подключение к JVM (Пример подключения я уже описал) и делай что хочешь в «УЖЕ ЗАПУЩЕННОЙ СТОРОННЕЙ JVM»
sshikov
Заметьте — я не говорил, что вообще идея вызывать Java-методы из Дельфи плохая. Идея нормальная (хотя на практике чаще все-таки нужно именно DLL из Java, а не наоборот). Да и пример именно для Дельфи видимо встречается не часто.
Я лишь говорю, что пример вызова удаления файла через JNI бессмысленный, потому что это все умеет и дельфи. Ну а про запущенную стороннюю JVM — вы же это сразу не написали, поэтому и уточнил, что дорого. И про это стоило бы явно писать.
andyshark1974
Типа того. Вот код из проги
DeleteFile(<Имя файла>);…
Блин. Я просто понимаю что вызов нужного метода может понадобиться, но Delphi это немного другой язык, чтобы в нем так изголяться… Я лично подвис…
Любой пример должен быть понятным и вменяемым. А когда ты знаешь что та же самая операция делается очень просто (ну или очень-очень-очень просто), то смысл от такого примера нивелируется правоприменением других функций.