2016-11-02 3 views
1

Я нашел хорошую реализацию JNI: https://sites.google.com/site/aminer68/jni-wrapper-for-delphi-and-freepascalИспользование JNI в FPC/Lazarus на Linux

имеет версию 2.85, и в соответствии текст был написан в марте 2016 года, но она написана для Windows.

Но у меня никаких проблем не пропуская/удаление всех связанных с Windows, материал (что Лазарь не удалить), но моя работа все еще не

Я сделал это так:

procedure TJavaRuntime.Initialize; 
begin 
    if libHandle <> 0 then 
     exit; // already initialized. 
    FRuntimeLib := '/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so'; 
    libHandle := LoadLibrary(PChar(FRuntimeLib)); 

    if libHandle = 0 then 
     raise EJavaRuntimeCreation.Create('Could not load library ' + FRuntimeLib); 
    @CreateVM := getProcAddress(libHandle, 'JNI_CreateJavaVM'); 
    @GetDefaultArgs := getProcAddress(libHandle, 'JNI_GetDefaultJavaVMInitArgs'); 
    @GetCreatedVMs := getProcAddress(libHandle, 'JNI_GetCreatedJavaVMs'); 
    if (@CreateVM = Nil) or (@GetDefaultArgs = Nil) or (@GetCreatedVMs = Nil) then 
    raise EJavaRuntimeCreation.Create('Library ' + FRuntimeLib + ' is not valid.'); 
    vmargs2.version := $00010008; 
    GetDefaultArgs(@vmargs2); 
end; 

Вы видите, Я загружаю jvm-библиотеку по мере необходимости в Linux. libHandle становится ненулевым, поэтому я думаю, что он загружает его хорошо (если я создаю орфографическую ошибку в имени библиотеки, libHandle остается равным нулю.)

Обнаружение procadresses кажется неудачным. @CreateVM:>

Некоторые фон на CreateVM:

CreateVM : TCreateVM; 
TCreateVM = function (vm : PPJavaVM ; penv : PPJNIEnv ; p : Pointer) : jint; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF} 

(кстати, Cdecl активен, STDCALL неактивна в редакторе Lazarus)

Я пытаюсь вызвать один, как это функция TJavaRuntime.GetVM

Как здесь

if CreateVM(@pvm, @penv, args) <>0 then 
    raise EJavaRuntimeCreation.Create('Could not create JVM'); 

Он не переходит к исключению, но вызывает другое исключение: Проект jtest1 повышен класс исключений «Внешний: SIGSEGV». По адресу 7FFFE62582B4

Я где-то читал, что SIGSEGV входит в ячейку памяти, которая является причиной незаконного доступа к памяти. Это возвращает меня к коду, где адрес CreateVM извлекается таким образом:

@CreateVM := getProcAddress(DLLHandle, 'JNI_CreateJavaVM'); 

я уверен, что функция с таким именем существует в этой библиотеке:

~ > nm -D /usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/libjvm.so 

---fragment 
000000000070e0f0 T jio_snprintf 
000000000070de80 T jio_vfprintf 
000000000070e0d0 T jio_vsnprintf 
00000000006d0880 T JNI_CreateJavaVM 
00000000006cd1d0 T JNI_GetCreatedJavaVMs 
00000000006cd210 T JNI_GetDefaultJavaVMInitArgs 
000000000070ee00 T JVM_Accept 
0000000000713990 T JVM_ActiveProcessorCount 
0000000000715a20 T JVM_AllocateNewArray 
0000000000727340 T JVM_AllocateNewObj 

Поэтому вызов с getProcAddress (.....) не приводит к действительному адресу. Может быть, что функция LoadLibrary (PChar (FRuntimeLib)) не загружает библиотеку хорошо, хотя у нее есть действительный дескриптор. (я также попытался SafeLoadLibrary (FRuntimeLib). Или GetProcAddress (.....) есть некоторые проблемы (Кстати, я также попытался GetProcedureAddress)

Я также пробовал другие Jvm-библиотеку, так что. .? не может быть проблема

Кто знает, что происходит здесь не так

заранее спасибо

ответ

1

Некоторые вещи, чтобы рассмотреть следующие вопросы:

  • использовать блок cmem, так что память pascal и C объединена
  • Возможно, начните с простейшей функции, например, проверки версии?
  • Использует ли библиотека JNI одно и то же соглашение о вызовах в Linux и Windows? Возможно, ваши заголовки только для Windows и содержат stdcall
  • Я вижу много @. Если ваши библиотеки и код вызова из разных источников, будьте очень осторожны. Некоторые из них могут использовать непрямые связи из-за использования параметров CONST или VAR, тщательно проверяя их соответствие.
+0

Спасибо, Марко, я нашел информацию о cmem: http://wiki.lazarus.freepascal.org/CMem Сейчас первый в моей LPR-файл. Не решает проблему. Действительно, многие stdcall's. Теперь {$ IFDEF WIN32} stdcall; {$ ENDIF} {$ IFDEF LINUX} cdecl; {$ ENDIF}, а cdecl - активны. Функции, которые я вызываю с помощью @, например CreateVM, необходимы для инициализации. Без них ничего не работает (как я хорошо понимаю). Я не знаю, правильно ли я их использую, я использую их в исходном коде. Я не понимаю ваше последнее замечание, для информации, моего кода и библиотеки находятся на одном компьютере. –

+0

Если исходный код заголовка и код, который вы используете для вызова заголовка, относятся не к одному и тому же источнику (но для другого заголовка или заголовка), то вы рискуете, что один транслятор заголовка перевел указательный параметр с помощью VAR, а другой перевел его как pascal указатель. –

+0

Привет, Марко, нет заголовков, используемых в Pascal loadLibrary и getProcAddress, все, что мы делаем, - это имена, которые публикуются библиотекой. Сама библиотека должна быть загружена, ручка стала ненулевой. Я проверил его, преднамеренно искажая путь, затем ручка становится нулевой. Итак, когда библиотека загружена хорошо, что я думаю, тогда проблема должна быть в вызове getProcAddress. Я также попытался загрузить другой libjvm.so, который имел тот же результат. Я думаю, что это проблема FPC/Lazarus, но я не уверен в этом. Я также разместил их в своих списках рассылки. –

Смежные вопросы