gpt4 book ai didi

java - 在 Linux 上的 FPC/Lazarus 中使用 JNI

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:43:16 27 4
gpt4 key购买 nike

我找到了一个很好的 JNI 实现: https://sites.google.com/site/aminer68/jni-wrapper-for-delphi-and-freepascal

它有 2.85 版本,相应的文本已于 2016 年 3 月编写,但它是为 Windows 编写的。

但是我跳过/删除所有与 Windows 相关的东西(Lazarus 没有删除的东西)没有问题,但我的工作仍然失败

我是这样做的:

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;

你看,我在 Linux 中根据需要加载 jvm 库。 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 处于 Activity 状态,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 库,所以这不是问题。

谁知道这里出了什么问题?

提前致谢

最佳答案

一些需要考虑的事情:

  • 使用单位cmem,使pascal和C内存统一
  • 也许从最简单的功能开始,比如版本检查?
  • JNI 库在 Linux 和 Windows 上使用相同的调用约定吗?也许您的 header 仅适用于 Windows,并且包含 stdcall
  • 我看到很多@。如果您的库和调用代码来自不同的来源,请务必小心。由于使用 CONST 或 VAR 参数,有些人可能会吃掉间接寻址,仔细检查它们是否匹配。

关于java - 在 Linux 上的 FPC/Lazarus 中使用 JNI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40383495/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com