Java 在Linux上的FPC/Lazarus中使用JNI
我发现JNI有一个很好的实现: 它的版本为2.85,相关文本已于2016年3月编写,但它是为Windows编写的 但是我跳过/删除所有与Windows相关的东西(Lazarus没有删除的东西)没有问题,但我的工作仍然失败 我是这样做的:Java 在Linux上的FPC/Lazarus中使用JNI,java,linux,java-native-interface,freepascal,Java,Linux,Java Native Interface,Freepascal,我发现JNI有一个很好的实现: 它的版本为2.85,相关文本已于2016年3月编写,但它是为Windows编写的 但是我跳过/删除所有与Windows相关的东西(Lazarus没有删除的东西)没有问题,但我的工作仍然失败 我是这样做的: procedure TJavaRuntime.Initialize; begin if libHandle <> 0 then exit; // already initialized. FRuntimeLib := '/u
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;
(顺便说一句,cdecl处于活动状态,stdcall在Lazarus编辑器中显示为灰色)
我尝试调用一个函数,就像函数TJavaRuntime.GetVM中的一样
像这里
if CreateVM(@pvm, @penv, args) <>0 then
raise EJavaRuntimeCreation.Create('Could not create JVM');
我确信该库中存在具有该名称的函数:
~ > 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);
或者GetProcedAddress(…)有一些问题。(顺便说一下,我也试过GetProcedureAddress)
我还尝试了其他jvm库,所以这不是问题所在
谁知道这里出了什么问题
提前感谢需要考虑的一些事情:
- 使用单位cmem,使pascal和C内存统一
- 也许从最简单的功能开始,比如版本检查
- JNI库在Linux和Windows上使用相同的调用约定吗?可能您的头文件仅限于Windows,并且包含stdcall
- 我看到了很多@。如果您的库和调用代码来自不同的源,请非常小心。由于使用CONST或VAR参数,有些库可能会使用间接方法,请仔细检查它们是否匹配
@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