I found a good implementation of JNI: https://sites.google.com/site/aminer68/jni-wrapper-for-delphi-and-freepascal
It has version 2.85, and the according text has been written in March 2016, but it is written for Windows.
But I had no problems skipping/removing all the Windows related stuff (what Lazarus did not remove), but my work still fails
I did it like this:
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;
You see, I load the jvm-library as needed in Linux. libHandle becomes non-zero, so I think it loads it well (if I create a spelling-error in the library-name, libHandle remains zero.)
The finding of the procadresses seems to fail. @CreateVM: >
Some background on CreateVM:
CreateVM : TCreateVM;
TCreateVM = function (vm : PPJavaVM ; penv : PPJNIEnv ; p : Pointer) : jint; {$IFDEF WIN32} stdcall; {$ENDIF} {$IFDEF LINUX} cdecl; {$ENDIF}
(by the way, cdecl is active, stdcall is grayed out in the Lazarus editor)
I try to call one, like this in function TJavaRuntime.GetVM
Like here
if CreateVM(@pvm, @penv, args) <>0 then
raise EJavaRuntimeCreation.Create('Could not create JVM');
It does not go to the exception, but raises another Exception: Project jtest1 raised exception class 'External: SIGSEGV'. At address 7FFFE62582B4
I read somewhere that SIGSEGV is entering an memory location which is a fault of illegal memory access. That brings me back to the code where the address of CreateVM is retrieved in this way:
@CreateVM := getProcAddress(DLLHandle, 'JNI_CreateJavaVM');
I am sure that a function with that name exist in that library:
~ > 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
So the call with getProcAddress(.....) does not lead to an valid address. It can be the case that the LoadLibrary(PChar(FRuntimeLib)) function does not load the library well, allthough it has a valid handle. (I also tried SafeLoadLibrary(FRuntimeLib); Or the getProcAddress(.....) has some problems. (By the way, I also tried GetProcedureAddress).
I also tried other jvm-libraries, so that cannot be the problem.
Who knows what is going wrong here?
Thanks in advance
Some things to consider: