2using System.Buffers.Binary;
5using System.Runtime.InteropServices;
14#if FIRST_PASS == false && IMPORTER == false && EXPORTER == false
21 internal unsafe
class LibJvm
24 static PropertiesAccessor propertiesAccessor;
26 static PropertiesAccessor PropertiesAccessor =>
JVM.
Internal.BaseAccessors.Get(
ref propertiesAccessor);
31 [StructLayout(LayoutKind.Sequential)]
32 unsafe
struct JVMInvokeInterface
35 public nint JNI_GetDefaultJavaVMInitArgs;
36 public nint JNI_GetCreatedJavaVMs;
37 public nint JNI_CreateJavaVM;
39 public nint JVM_ThrowException;
40 public nint JVM_GetThreadInterruptEvent;
41 public nint JVM_ActiveProcessorCount;
42 public nint JVM_IHashCode;
43 public nint JVM_ArrayCopy;
44 public nint JVM_InitProperties;
45 public nint JVM_RawMonitorCreate;
46 public nint JVM_RawMonitorDestroy;
47 public nint JVM_RawMonitorEnter;
48 public nint JVM_RawMonitorExit;
49 public nint JVM_CopySwapMemory;
54 delegate
int JNI_GetDefaultJavaVMInitArgsDelegate(
void* vm_args);
57 delegate
int JNI_GetCreatedJavaVMsDelegate(
JavaVM** vmBuf,
int bufLen,
int* nVMs);
60 delegate
int JNI_CreateJavaVMDelegate(
JavaVM** p_vm,
void** p_env,
void* vm_args);
63 delegate
void JVM_ThrowExceptionDelegate([MarshalAs(UnmanagedType.LPUTF8Str)]
string name, [MarshalAs(UnmanagedType.LPUTF8Str)]
string message);
66 delegate nint JVM_GetThreadInterruptEventDelegate();
69 delegate
int JVM_ActiveProcessorCountDelegate();
72 delegate
int JVM_IHashCodeDelegate(
JNIEnv* env, nint handle);
75 delegate
void JVM_ArrayCopyDelegate(
JNIEnv* env, nint ignored, nint src,
int src_pos, nint dst,
int dst_pos,
int length);
78 delegate nint JVM_InitPropertiesDelegate(
JNIEnv* env, nint props);
81 delegate nint JVM_RawMonitorCreateDelegate();
84 delegate
void JVM_RawMonitorDestroyDelegate(nint mon);
87 delegate
int JVM_RawMonitorEnterDelegate(nint mon);
90 delegate
void JVM_RawMonitorExitDelegate(nint mon);
93 delegate
void JVM_CopySwapMemoryDelegate(
JNIEnv* env, nint srcObj,
long srcOffset, nint dstObj,
long dstOffset,
long size,
long elemSize);
95 delegate
void JVM_InitDelegate(JVMInvokeInterface* iface);
97 delegate nint JVM_LoadLibraryDelegate([MarshalAs(UnmanagedType.LPUTF8Str)]
string name);
99 delegate
void JVM_UnloadLibraryDelegate(nint handle);
101 delegate nint JVM_FindLibraryEntryDelegate(nint handle, [MarshalAs(UnmanagedType.LPStr)]
string name);
106 public static readonly LibJvm Instance =
new();
108 readonly ikvm.@
internal.CallerID callerID = ikvm.@
internal.CallerID.create(typeof(LibJvm).TypeHandle);
109 readonly JVMInvokeInterface* jvmii;
111 readonly JVM_InitDelegate _JVM_Init;
112 readonly JVM_LoadLibraryDelegate _JVM_LoadLibrary;
113 readonly JVM_UnloadLibraryDelegate _JVM_UnloadLibrary;
114 readonly JVM_FindLibraryEntryDelegate _JVM_FindLibraryEntry;
116 readonly JNI_GetDefaultJavaVMInitArgsDelegate _JNI_GetDefaultJavaVMInitArgs;
117 readonly JNI_GetCreatedJavaVMsDelegate _JNI_GetCreatedJavaVMs;
118 readonly JNI_CreateJavaVMDelegate _JNI_CreateJavaVM;
119 readonly JVM_ThrowExceptionDelegate _JVM_ThrowException;
120 readonly JVM_GetThreadInterruptEventDelegate _JVM_GetThreadInterruptEvent;
121 readonly JVM_ActiveProcessorCountDelegate _JVM_ActiveProcessorCount;
122 readonly JVM_IHashCodeDelegate _JVM_IHashCode;
123 readonly JVM_ArrayCopyDelegate _JVM_ArrayCopy;
124 readonly JVM_InitPropertiesDelegate _JVM_InitProperties;
125 readonly JVM_RawMonitorCreateDelegate _JVM_RawMonitorCreate;
126 readonly JVM_RawMonitorDestroyDelegate _JVM_RawMonitorDestroy;
127 readonly JVM_RawMonitorEnterDelegate _JVM_RawMonitorEnter;
128 readonly JVM_RawMonitorExitDelegate _JVM_RawMonitorExit;
129 readonly JVM_CopySwapMemoryDelegate _JVM_CopySwapMemory;
141 _JVM_Init = Marshal.GetDelegateForFunctionPointer<JVM_InitDelegate>(Handle.GetExport(
"JVM_Init",
sizeof(nint)).Handle);
142 _JVM_LoadLibrary = Marshal.GetDelegateForFunctionPointer<JVM_LoadLibraryDelegate>(Handle.GetExport(
"JVM_LoadLibrary",
sizeof(nint)).Handle);
143 _JVM_UnloadLibrary = Marshal.GetDelegateForFunctionPointer<JVM_UnloadLibraryDelegate>(Handle.GetExport(
"JVM_UnloadLibrary",
sizeof(nint)).Handle);
144 _JVM_FindLibraryEntry = Marshal.GetDelegateForFunctionPointer<JVM_FindLibraryEntryDelegate>(Handle.GetExport(
"JVM_FindLibraryEntry",
sizeof(nint) +
sizeof(nint)).Handle);
147 jvmii = (JVMInvokeInterface*)Marshal.AllocHGlobal(
sizeof(JVMInvokeInterface));
149 jvmii->JNI_GetCreatedJavaVMs = Marshal.GetFunctionPointerForDelegate(_JNI_GetCreatedJavaVMs =
JNIVM.
GetCreatedJavaVMs);
150 jvmii->JNI_CreateJavaVM = Marshal.GetFunctionPointerForDelegate(_JNI_CreateJavaVM =
JNIVM.
CreateJavaVM);
151 jvmii->JVM_ThrowException = Marshal.GetFunctionPointerForDelegate(_JVM_ThrowException = JVM_ThrowException);
152 jvmii->JVM_GetThreadInterruptEvent = Marshal.GetFunctionPointerForDelegate(_JVM_GetThreadInterruptEvent = JVM_GetThreadInterruptEvent);
153 jvmii->JVM_ActiveProcessorCount = Marshal.GetFunctionPointerForDelegate(_JVM_ActiveProcessorCount = JVM_ActiveProcessorCount);
154 jvmii->JVM_IHashCode = Marshal.GetFunctionPointerForDelegate(_JVM_IHashCode = JVM_IHashCode);
155 jvmii->JVM_ArrayCopy = Marshal.GetFunctionPointerForDelegate(_JVM_ArrayCopy = JVM_ArrayCopy);
156 jvmii->JVM_InitProperties = Marshal.GetFunctionPointerForDelegate(_JVM_InitProperties = JVM_InitProperties);
157 jvmii->JVM_RawMonitorCreate = Marshal.GetFunctionPointerForDelegate(_JVM_RawMonitorCreate = JVM_RawMonitorCreate);
158 jvmii->JVM_RawMonitorDestroy = Marshal.GetFunctionPointerForDelegate(_JVM_RawMonitorDestroy = JVM_RawMonitorDestroy);
159 jvmii->JVM_RawMonitorEnter = Marshal.GetFunctionPointerForDelegate(_JVM_RawMonitorEnter = JVM_RawMonitorEnter);
160 jvmii->JVM_RawMonitorExit = Marshal.GetFunctionPointerForDelegate(_JVM_RawMonitorExit = JVM_RawMonitorExit);
161 jvmii->JVM_CopySwapMemory = Marshal.GetFunctionPointerForDelegate(_JVM_CopySwapMemory = JVM_CopySwapMemory);
168 public NativeLibraryHandle Handle {
get;
private set; }
176 void JVM_ThrowException(
string name,
string msg)
187 var exceptionClass =
RuntimeClassLoader.FromCallerID(callerID).TryLoadClassByName(name.Replace(
'/',
'.'));
188 if (exceptionClass ==
null)
195 var ctor = exceptionClass.GetMethod(
"<init>", msg ==
null ?
"()V" :
"(Ljava.lang.String;)V",
false);
203 exceptionClass.Finish();
205 var ctorMember = (
java.
lang.reflect.Constructor)ctor.ToMethodOrConstructor(
false);
206 var exception = (Exception)ctorMember.newInstance(msg ==
null ? Array.Empty<
object>() :
new object[] { msg }, callerID);
208 JVM.SetPendingException(exception);
212 JVM.Context.
Diagnostics.
GenericJniError($
"{nameof(LibJvm)}.{nameof(JVM_ThrowException)}: Exception occurred creating exception {name}: {e.Message}");
213 JVM.SetPendingException(e);
221 nint JVM_GetThreadInterruptEvent()
225 return global::java.lang.Thread.currentThread().interruptEvent.SafeWaitHandle.DangerousGetHandle();
227 catch (global::java.lang.Throwable t)
229 JVM.SetPendingException(t);
235 JVM.SetPendingException(
new global::java.lang.InternalError(e));
244 int JVM_ActiveProcessorCount()
246 return Environment.ProcessorCount;
255 int JVM_IHashCode(
JNIEnv* env, nint handle)
257 return handle == 0 ? 0 : RuntimeHelpers.GetHashCode(env->UnwrapRef(handle));
270 void JVM_ArrayCopy(
JNIEnv* env, nint ignored, nint src,
int src_pos, nint dst,
int dst_pos,
int length)
274 if (src == 0 || dst == 0)
275 throw new java.
lang.NullPointerException();
277 var s = env->UnwrapRef(src) as Array;
278 var d = env->UnwrapRef(dst) as Array;
279 if (s is
null || d is
null)
280 throw new java.
lang.ArrayStoreException();
282 if (src_pos < 0 || dst_pos < 0 || length < 0)
283 throw new java.
lang.ArrayIndexOutOfBoundsException();
285 if (((length + src_pos) > s.Length) || ((length + dst_pos) > d.Length))
286 throw new java.
lang.ArrayIndexOutOfBoundsException();
291 Array.Copy(s, src_pos, d, dst_pos, length);
295 JVM.SetPendingException(t);
297 catch (ArrayTypeMismatchException)
299 JVM.SetPendingException(
new java.
lang.ArrayStoreException());
303 JVM.SetPendingException(
new java.
lang.InternalError(e));
317 nint JVM_InitProperties(
JNIEnv* env, nint props)
321 var p = env->UnwrapRef(props);
323 if (kvp.Value is
string v)
324 PropertiesAccessor.InvokeSetProperty(p, kvp.Key, v);
330 JVM.SetPendingException(t);
335 JVM.SetPendingException(
new java.
lang.InternalError(e));
344 nint JVM_RawMonitorCreate()
348 return (IntPtr)GCHandle.Alloc(
new object(), GCHandleType.Normal);
352 JVM.SetPendingException(
new java.
lang.InternalError(e));
361 void JVM_RawMonitorDestroy(nint mon)
365 GCHandle.FromIntPtr(mon).Free();
369 JVM.SetPendingException(
new java.
lang.InternalError(e));
378 int JVM_RawMonitorEnter(nint mon)
382 Monitor.Enter(GCHandle.FromIntPtr(mon).Target);
386 JVM.SetPendingException(
new java.
lang.InternalError(e));
397 void JVM_RawMonitorExit(nint mon)
401 Monitor.Exit(GCHandle.FromIntPtr(mon).Target);
405 JVM.SetPendingException(
new java.
lang.InternalError(e));
419 unsafe
void JVM_CopySwapMemory(
JNIEnv* env, nint srcObj,
long srcOffset, nint dstObj,
long dstOffset,
long size,
long elemSize)
421 JVM_CopySwapMemory((Array)env->UnwrapRef(srcObj), srcOffset, (Array)env->UnwrapRef(dstObj), dstOffset, size, elemSize);
433 internal static unsafe
void JVM_CopySwapMemory(Array srcObj,
long srcOffset, Array dstObj,
long dstOffset,
long size,
long elemSize)
440 if (size % elemSize != 0)
441 throw new java.
lang.InternalError($
"size {size} must be multiple of element size {elemSize}");
443 static unsafe Span<T> AsSpan<T>(Array obj,
long off,
long size) where T : unmanaged
446 return new Span<T>(Unsafe.As<T[]>(obj)).Slice((
int)(off /
sizeof(T)), (
int)(size /
sizeof(T)));
448 return new Span<T>((
void*)(nint)off, (
int)(size /
sizeof(T)));
450 throw new java.
lang.InternalError($
"address must not be NULL");
456 ReverseEndianness(AsSpan<short>(srcObj, srcOffset, size), AsSpan<short>(dstObj, dstOffset, size));
459 ReverseEndianness(AsSpan<int>(srcObj, srcOffset, size), AsSpan<int>(dstObj, dstOffset, size));
462 ReverseEndianness(AsSpan<long>(srcObj, srcOffset, size), AsSpan<long>(dstObj, dstOffset, size));
465 throw new java.
lang.InternalError($
"incorrect element size: {elemSize}");
470 JVM.SetPendingException(e);
474 JVM.SetPendingException(
new java.
lang.InternalError(e));
483 static void ReverseEndianness(ReadOnlySpan<short> src, Span<short> dst)
486 BinaryPrimitives.ReverseEndianness(src, dst);
488 ref short srcRef =
ref MemoryMarshal.GetReference(src);
489 ref short dstRef =
ref MemoryMarshal.GetReference(dst);
490 if (Unsafe.AreSame(
ref srcRef,
ref dstRef) || !src.Overlaps(dst, out
int elementOffset) || elementOffset < 0)
491 for (
int i = 0; i < src.Length; i++)
492 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
494 for (
int i = src.Length - 1; i >= 0; i--)
495 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
504 static void ReverseEndianness(ReadOnlySpan<int> src, Span<int> dst)
507 BinaryPrimitives.ReverseEndianness(src, dst);
509 ref int srcRef =
ref MemoryMarshal.GetReference(src);
510 ref int dstRef =
ref MemoryMarshal.GetReference(dst);
511 if (Unsafe.AreSame(
ref srcRef,
ref dstRef) || !src.Overlaps(dst, out
int elementOffset) || elementOffset < 0)
512 for (
int i = 0; i < src.Length; i++)
513 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
515 for (
int i = src.Length - 1; i >= 0; i--)
516 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
525 static void ReverseEndianness(ReadOnlySpan<long> src, Span<long> dst)
528 BinaryPrimitives.ReverseEndianness(src, dst);
530 ref long srcRef =
ref MemoryMarshal.GetReference(src);
531 ref long dstRef =
ref MemoryMarshal.GetReference(dst);
532 if (Unsafe.AreSame(
ref srcRef,
ref dstRef) || !src.Overlaps(dst, out
int elementOffset) || elementOffset < 0)
533 for (
int i = 0; i < src.Length; i++)
534 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
536 for (
int i = src.Length - 1; i >= 0; i--)
537 dst[i] = BinaryPrimitives.ReverseEndianness(src[i]);
546 public nint JVM_LoadLibrary(
string name)
551 var h = _JVM_LoadLibrary(name);
557 JVM.ThrowPendingException();
565 public void JVM_UnloadLibrary(nint handle)
570 _JVM_UnloadLibrary(handle);
575 JVM.ThrowPendingException();
585 public nint JVM_FindLibraryEntry(nint handle,
string name)
590 var h = _JVM_FindLibraryEntry(handle, name);
596 JVM.ThrowPendingException();
606 Marshal.FreeHGlobal((IntPtr)jvmii);
System.Runtime.InteropServices.CallingConvention CallingConvention
Represents an internal error that occurred within IKVM.
static int GetCreatedJavaVMs(JavaVM **ppvmBuf, jsize bufLen, jsize *nVMs)
Implements the JNI_GetCreatedJavaVMs native function.
static int CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
Implements the JNI_CreateJavaVM native method.
static int GetDefaultJavaVMInitArgs(void *vm_args)
Implements the JNI_GetDefaultJavaVMInitArgs native function.
Property values loaded into the JVM from various sources.
Main state of the running JVM.
Provides methods to load libraries from standard .NET search locations. This class is not used to loa...
static NativeLibraryHandle Load(string nameOrPath)
Loads the given library in a platform dependent manner.
static string MapLibraryName(string name)
Returns a version of the library name with the OS specific prefix and suffix.
Runtime support for a class loader.
IDiagnosticHandler Diagnostics
Gets the IDiagnosticHandler where events should be sent.
void GenericJniTrace(string arg0)
The 'GenericJniTrace' diagnostic.
void GenericJniError(string arg0)
The 'GenericJniError' diagnostic.