2
Copyright (C) 2002-2009 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
25
using System.Collections.Generic;
26
using System.Diagnostics;
28
using System.Reflection;
29
using System.Runtime.InteropServices;
32
// Java type JNI aliases
33
using jboolean = System.SByte;
34
using jbyte = System.SByte;
35
using jchar = System.UInt16;
36
using jshort = System.Int16;
37
using jint = System.Int32;
38
using jsize = System.Int32;
39
using jlong = System.Int64;
40
using jfloat = System.Single;
41
using jdouble = System.Double;
42
using jobject = System.IntPtr;
43
using jstring = System.IntPtr;
44
using jclass = System.IntPtr;
45
using jarray = System.IntPtr;
46
using jobjectArray = System.IntPtr;
47
using jbooleanArray = System.IntPtr;
48
using jbyteArray = System.IntPtr;
49
using jcharArray = System.IntPtr;
50
using jshortArray = System.IntPtr;
51
using jintArray = System.IntPtr;
52
using jlongArray = System.IntPtr;
53
using jfloatArray = System.IntPtr;
54
using jdoubleArray = System.IntPtr;
55
using jthrowable = System.IntPtr;
56
using jweak = System.IntPtr;
57
using jmethodID = System.IntPtr;
58
using jfieldID = System.IntPtr;
60
namespace IKVM.Runtime
62
[StructLayout(LayoutKind.Sequential)]
63
unsafe struct JavaVMOption
65
internal byte* optionString;
66
internal void* extraInfo;
69
[StructLayout(LayoutKind.Sequential)]
70
unsafe struct JavaVMInitArgs
72
internal jint version;
73
internal jint nOptions;
74
internal JavaVMOption* options;
75
internal jboolean ignoreUnrecognized;
78
public unsafe sealed class JNI
80
internal static volatile bool jvmCreated;
81
internal static volatile bool jvmDestroyed;
82
internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr>";
84
internal static bool IsSupportedJniVersion(jint version)
86
return version == JNIEnv.JNI_VERSION_1_1 || version == JNIEnv.JNI_VERSION_1_2 || version == JNIEnv.JNI_VERSION_1_4 || version == JNIEnv.JNI_VERSION_1_6;
89
public static int CreateJavaVM(void* ppvm, void* ppenv, void* args)
91
JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args;
92
// we don't support the JDK 1.1 JavaVMInitArgs
93
if(!IsSupportedJniVersion(pInitArgs->version) || pInitArgs->version == JNIEnv.JNI_VERSION_1_1)
95
return JNIEnv.JNI_EVERSION;
99
return JNIEnv.JNI_ERR;
101
System.Collections.Hashtable props = new System.Collections.Hashtable();
102
for(int i = 0; i < pInitArgs->nOptions; i++)
104
string option = JNIEnv.StringFromOEM(pInitArgs->options[i].optionString);
105
if(option.StartsWith("-D"))
107
int idx = option.IndexOf('=', 2);
108
props[option.Substring(2, idx - 2)] = option.Substring(idx + 1);
110
else if(option.StartsWith("-verbose"))
114
else if(option == "vfprintf" || option == "exit" || option == "abort")
118
else if(pInitArgs->ignoreUnrecognized == JNIEnv.JNI_FALSE)
120
return JNIEnv.JNI_ERR;
124
ikvm.runtime.Startup.setProperties(props);
126
// initialize the class library
127
java.lang.Thread.currentThread();
129
*((void**)ppvm) = JavaVM.pJavaVM;
130
return JavaVM.AttachCurrentThread(JavaVM.pJavaVM, (void**)ppenv, null);
133
public static int GetDefaultJavaVMInitArgs(void* vm_args)
135
// This is only used for JDK 1.1 JavaVMInitArgs, and we don't support those.
136
return JNIEnv.JNI_ERR;
139
public static int GetCreatedJavaVMs(void* ppvmBuf, int bufLen, int* nVMs)
145
*((void**)ppvmBuf) = JavaVM.pJavaVM;
152
else if(nVMs != null)
156
return JNIEnv.JNI_OK;
161
private JNIEnv.ManagedJNIEnv env;
162
private JNIEnv.ManagedJNIEnv.FrameState prevFrameState;
164
internal ClassLoaderWrapper Enter(ClassLoaderWrapper loader)
166
Enter((ikvm.@internal.CallerID)null);
167
ClassLoaderWrapper prev = env.classLoader;
168
env.classLoader = loader;
172
internal void Leave(ClassLoaderWrapper prev)
174
env.classLoader = prev;
178
public IntPtr Enter(ikvm.@internal.CallerID callerID)
180
env = TlsHack.ManagedJNIEnv;
183
env = JNIEnv.CreateJNIEnv()->GetManagedJNIEnv();
185
prevFrameState = env.Enter(callerID);
186
return (IntPtr)(void*)env.pJNIEnv;
191
Exception x = env.Leave(prevFrameState);
198
public static IntPtr GetFuncPtr(ikvm.@internal.CallerID callerID, string clazz, string name, string sig)
200
ClassLoaderWrapper loader = ClassLoaderWrapper.FromCallerID(callerID);
202
for(int i = 1; sig[i] != ')'; i++)
208
while(sig[++i] == '[');
211
while(sig[++i] != ';');
216
while(sig[++i] != ';');
235
string mangledClass = JniMangle(clazz);
236
string mangledName = JniMangle(name);
237
string mangledSig = JniMangle(sig.Substring(1, sig.IndexOf(')') - 1));
238
string shortMethodName = String.Format("Java_{0}_{1}", mangledClass, mangledName);
239
string longMethodName = String.Format("Java_{0}_{1}__{2}", mangledClass, mangledName, mangledSig);
240
Tracer.Info(Tracer.Jni, "Linking native method: {0}.{1}{2}, class loader = {3}, short = {4}, long = {5}, args = {6}",
241
clazz, name, sig, loader, shortMethodName, longMethodName, sp + 2 * IntPtr.Size);
242
lock(JniHelper.JniLock)
244
foreach(IntPtr p in loader.GetNativeLibraries())
246
IntPtr pfunc = NativeLibrary.GetProcAddress(p, shortMethodName, sp + 2 * IntPtr.Size);
247
if(pfunc != IntPtr.Zero)
249
Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (short)", clazz, name, sig, p.ToInt64());
252
pfunc = NativeLibrary.GetProcAddress(p, longMethodName, sp + 2 * IntPtr.Size);
253
if(pfunc != IntPtr.Zero)
255
Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (long)", clazz, name, sig, p.ToInt64());
260
string msg = string.Format("{0}.{1}{2}", clazz, name, sig);
261
Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg);
262
throw new java.lang.UnsatisfiedLinkError(msg);
265
private static string JniMangle(string name)
267
StringBuilder sb = new StringBuilder();
268
foreach(char c in name)
286
else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
292
sb.Append(String.Format("_0{0:x4}", (int)c));
295
return sb.ToString();
298
public IntPtr MakeLocalRef(object obj)
300
return env.MakeLocalRef(obj);
303
// NOTE this method has the wrong name, it should unwrap *any* jobject reference type (local and global)
304
public object UnwrapLocalRef(IntPtr p)
306
return JNIEnv.UnwrapRef(env, p);
311
abstract unsafe class NativeLibrary
313
private NativeLibrary() { }
314
private static readonly NativeLibrary impl;
316
static NativeLibrary()
320
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
322
if (IntPtr.Size == 4)
324
impl = new Win32_x86();
328
impl = new Win32_x64();
330
// call a method to trigger the native library load
331
// (if this fails, we fall back to the classic native library)
332
impl._MarshalDelegate(null);
336
impl = new Classic();
339
catch (DllNotFoundException)
341
impl = new Classic();
343
catch (BadImageFormatException)
345
impl = new Classic();
349
private sealed class Win32_x86 : NativeLibrary
351
private const string library = "ikvm-native-win32-x86";
354
private static extern IntPtr ikvm_LoadLibrary(string filename);
356
private static extern void ikvm_FreeLibrary(IntPtr handle);
358
private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
360
private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
362
private static extern void** ikvm_GetJNIEnvVTable();
364
private static extern void* ikvm_MarshalDelegate(Delegate d);
366
protected override IntPtr _LoadLibrary(string filename)
368
return ikvm_LoadLibrary(filename);
371
protected override void _FreeLibrary(IntPtr handle)
373
ikvm_FreeLibrary(handle);
376
protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
378
return ikvm_GetProcAddress(handle, name, argc);
381
protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
383
return ikvm_CallOnLoad(method, jvm, reserved);
386
protected override void** _GetJNIEnvVTable()
388
return ikvm_GetJNIEnvVTable();
391
protected override void* _MarshalDelegate(Delegate d)
393
return ikvm_MarshalDelegate(d);
397
private sealed class Win32_x64 : NativeLibrary
399
private const string library = "ikvm-native-win32-x64";
402
private static extern IntPtr ikvm_LoadLibrary(string filename);
404
private static extern void ikvm_FreeLibrary(IntPtr handle);
406
private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
408
private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
410
private static extern void** ikvm_GetJNIEnvVTable();
412
private static extern void* ikvm_MarshalDelegate(Delegate d);
414
protected override IntPtr _LoadLibrary(string filename)
416
return ikvm_LoadLibrary(filename);
419
protected override void _FreeLibrary(IntPtr handle)
421
ikvm_FreeLibrary(handle);
424
protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
426
return ikvm_GetProcAddress(handle, name, argc);
429
protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
431
return ikvm_CallOnLoad(method, jvm, reserved);
434
protected override void** _GetJNIEnvVTable()
436
return ikvm_GetJNIEnvVTable();
439
protected override void* _MarshalDelegate(Delegate d)
441
return ikvm_MarshalDelegate(d);
445
private sealed class Classic : NativeLibrary
447
private const string library = "ikvm-native";
450
private static extern IntPtr ikvm_LoadLibrary(string filename);
452
private static extern void ikvm_FreeLibrary(IntPtr handle);
454
private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
456
private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
458
private static extern void** ikvm_GetJNIEnvVTable();
460
private static extern void* ikvm_MarshalDelegate(Delegate d);
462
protected override IntPtr _LoadLibrary(string filename)
464
return ikvm_LoadLibrary(filename);
467
protected override void _FreeLibrary(IntPtr handle)
469
ikvm_FreeLibrary(handle);
472
protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
474
return ikvm_GetProcAddress(handle, name, argc);
477
protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
479
return ikvm_CallOnLoad(method, jvm, reserved);
482
protected override void** _GetJNIEnvVTable()
484
return ikvm_GetJNIEnvVTable();
487
protected override void* _MarshalDelegate(Delegate d)
489
return ikvm_MarshalDelegate(d);
493
protected abstract IntPtr _LoadLibrary(string filename);
494
protected abstract void _FreeLibrary(IntPtr handle);
495
protected abstract IntPtr _GetProcAddress(IntPtr handle, string name, int argc);
496
protected abstract int _CallOnLoad(IntPtr method, void* jvm, void* reserved);
497
protected abstract void** _GetJNIEnvVTable();
498
protected abstract void* _MarshalDelegate(Delegate d);
500
internal static IntPtr LoadLibrary(string filename)
502
return impl._LoadLibrary(filename);
505
internal static void FreeLibrary(IntPtr handle)
507
impl._FreeLibrary(handle);
510
internal static IntPtr GetProcAddress(IntPtr handle, string name, int argc)
512
return impl._GetProcAddress(handle, name, argc);
515
internal static int CallOnLoad(IntPtr method, void* jvm, void* reserved)
517
return impl._CallOnLoad(method, jvm, reserved);
520
internal static void** GetJNIEnvVTable()
522
return impl._GetJNIEnvVTable();
525
internal static void* MarshalDelegate(Delegate d)
527
return impl._MarshalDelegate(d);
531
sealed class JniHelper
533
private static List<IntPtr> nativeLibraries = new List<IntPtr>();
534
internal static readonly object JniLock = new object();
536
// MONOBUG with mcs we can't pass ClassLoaderWrapper from IKVM.Runtime.dll to IKVM.Runtime.JNI.dll
537
internal unsafe static long LoadLibrary(string filename, object loader)
539
return LoadLibrary(filename, (ClassLoaderWrapper)loader);
542
// MONOBUG with mcs we can't pass ClassLoaderWrapper from IKVM.Runtime.dll to IKVM.Runtime.JNI.dll
543
internal static void UnloadLibrary(long handle, object loader)
545
UnloadLibrary(handle, (ClassLoaderWrapper)loader);
548
private unsafe static long LoadLibrary(string filename, ClassLoaderWrapper loader)
550
Tracer.Info(Tracer.Jni, "loadLibrary: {0}, class loader: {1}", filename, loader);
553
IntPtr p = NativeLibrary.LoadLibrary(filename);
556
Tracer.Info(Tracer.Jni, "Library not found: {0}", filename);
561
foreach(IntPtr tmp in loader.GetNativeLibraries())
565
// the library was already loaded by the current class loader,
566
// no need to do anything
567
NativeLibrary.FreeLibrary(p);
568
Tracer.Warning(Tracer.Jni, "Library was already loaded: {0}", filename);
572
if(nativeLibraries.Contains(p))
574
string msg = string.Format("Native library {0} already loaded in another classloader", filename);
575
Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg);
576
throw new java.lang.UnsatisfiedLinkError(msg);
578
Tracer.Info(Tracer.Jni, "Library loaded: {0}, handle = 0x{1:X}", filename, p.ToInt64());
579
IntPtr onload = NativeLibrary.GetProcAddress(p, "JNI_OnLoad", IntPtr.Size * 2);
580
if(onload != IntPtr.Zero)
582
Tracer.Info(Tracer.Jni, "Calling JNI_OnLoad on: {0}", filename);
583
JNI.Frame f = new JNI.Frame();
585
ClassLoaderWrapper prevLoader = f.Enter(loader);
588
// TODO on Whidbey we should be able to use Marshal.GetDelegateForFunctionPointer to call OnLoad
589
version = NativeLibrary.CallOnLoad(onload, JavaVM.pJavaVM, null);
590
Tracer.Info(Tracer.Jni, "JNI_OnLoad returned: 0x{0:X8}", version);
596
if(!JNI.IsSupportedJniVersion(version))
598
string msg = string.Format("Unsupported JNI version 0x{0:X} required by {1}", version, filename);
599
Tracer.Error(Tracer.Jni, "UnsatisfiedLinkError: {0}", msg);
600
throw new java.lang.UnsatisfiedLinkError(msg);
603
nativeLibraries.Add(p);
604
loader.RegisterNativeLibrary(p);
609
NativeLibrary.FreeLibrary(p);
615
private unsafe static void UnloadLibrary(long handle, ClassLoaderWrapper loader)
619
Tracer.Info(Tracer.Jni, "Unloading library: handle = 0x{0:X}, class loader = {1}", handle, loader);
620
IntPtr p = (IntPtr)handle;
621
IntPtr onunload = NativeLibrary.GetProcAddress(p, "JNI_OnUnload", IntPtr.Size * 2);
622
if (onunload != IntPtr.Zero)
624
Tracer.Info(Tracer.Jni, "Calling JNI_OnUnload on: handle = 0x{0:X}", handle);
625
JNI.Frame f = new JNI.Frame();
626
ClassLoaderWrapper prevLoader = f.Enter(loader);
629
// TODO on Whidbey we should be able to use Marshal.GetDelegateForFunctionPointer to call OnLoad
630
NativeLibrary.CallOnLoad(onunload, JavaVM.pJavaVM, null);
637
nativeLibraries.Remove(p);
638
loader.UnregisterNativeLibrary(p);
639
NativeLibrary.FreeLibrary((IntPtr)handle);
644
static class GlobalRefs
646
internal static System.Collections.ArrayList globalRefs = new System.Collections.ArrayList();
647
internal static readonly object weakRefLock = new object();
648
internal static GCHandle[] weakRefs = new GCHandle[16];
650
internal static object Unwrap(int i)
653
if ((i & (1 << 30)) != 0)
655
lock (GlobalRefs.weakRefLock)
657
return GlobalRefs.weakRefs[i - (1 << 30)].Target;
662
lock (GlobalRefs.globalRefs)
664
return GlobalRefs.globalRefs[i - 1];
670
unsafe class VtableBuilder
672
delegate int pf_int_IntPtr(JNIEnv* pEnv, IntPtr p);
673
delegate IntPtr pf_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p);
674
delegate void pf_void_IntPtr(JNIEnv* pEnv, IntPtr p);
675
delegate IntPtr pf_IntPtr(JNIEnv* pEnv);
676
delegate void pf_void(JNIEnv* pEnv);
677
delegate sbyte pf_sbyte(JNIEnv* pEnv);
678
delegate IntPtr pf_IntPtr_pbyte(JNIEnv* pEnv, byte* p);
679
delegate int pf_int(JNIEnv* pEnv);
680
delegate IntPtr pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv* pEnv, byte* p1, IntPtr p2, sbyte* p3, int p4);
681
delegate IntPtr pf_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
682
delegate jchar* pf_pjchar_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
683
delegate void pf_void_IntPtr_pvoid_int(JNIEnv* pEnv, IntPtr p1, void* p2, int p3);
684
delegate void* pf_pvoid_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
685
delegate int pf_int_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2);
686
delegate void pf_void_pbyte(JNIEnv* pEnv, byte* p1);
687
delegate IntPtr pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2, byte* p3);
688
delegate int pf_int_IntPtr_pJNINativeMethod_int(JNIEnv* pEnv, IntPtr p1, JNIEnv.JNINativeMethod* p2, int p3);
689
delegate int pf_int_ppJavaVM(JNIEnv* pEnv, JavaVM** ppJavaVM);
690
delegate sbyte pf_sbyte_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
691
delegate short pf_short_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
692
delegate ushort pf_ushort_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
693
delegate int pf_int_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
694
delegate long pf_long_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
695
delegate float pf_float_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
696
delegate double pf_double_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
697
delegate void pf_void_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3);
698
delegate void pf_void_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3);
699
delegate void pf_void_IntPtr_IntPtr_short(JNIEnv* pEnv, IntPtr p1, IntPtr p2, short p3);
700
delegate void pf_void_IntPtr_IntPtr_ushort(JNIEnv* pEnv, IntPtr p1, IntPtr p2, ushort p3);
701
delegate void pf_void_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, IntPtr p2, int p3);
702
delegate void pf_void_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, IntPtr p2, long p3);
703
delegate void pf_void_IntPtr_IntPtr_float(JNIEnv* pEnv, IntPtr p1, IntPtr p2, float p3);
704
delegate void pf_void_IntPtr_IntPtr_double(JNIEnv* pEnv, IntPtr p1, IntPtr p2, double p3);
705
delegate IntPtr pf_IntPtr_pjchar_int(JNIEnv* pEnv, jchar* p1, int p2);
706
delegate void pf_void_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
707
delegate void pf_void_IntPtr_pjchar(JNIEnv* pEnv, IntPtr p1, jchar* p2);
708
delegate IntPtr pf_IntPtr_int_IntPtr_IntPtr(JNIEnv* pEnv, int p1, IntPtr p2, IntPtr p3);
709
delegate IntPtr pf_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, int p2);
710
delegate void pf_void_IntPtr_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, IntPtr p3);
711
delegate IntPtr pf_IntPtr_int(JNIEnv* pEnv, int p1);
712
delegate void pf_void_IntPtr_int_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, int p3, IntPtr p4);
713
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
714
delegate sbyte pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
715
delegate short pf_short_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
716
delegate ushort pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
717
delegate int pf_int_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
718
delegate long pf_long_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
719
delegate float pf_float_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
720
delegate double pf_double_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
721
delegate void pf_void_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
722
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
723
delegate sbyte pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
724
delegate ushort pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
725
delegate short pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
726
delegate int pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
727
delegate long pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
728
delegate float pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
729
delegate double pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
730
delegate void pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
731
delegate byte* pf_pbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
732
delegate void pf_void_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2);
733
delegate jboolean* pf_pjboolean_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
734
delegate jbyte* pf_pjbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
735
delegate jshort* pf_pjshort_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
736
delegate jint* pf_pjint_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
737
delegate jlong* pf_pjlong_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
738
delegate jfloat* pf_pjfloat_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
739
delegate jdouble* pf_pjdouble_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
740
delegate void pf_void_IntPtr_pjboolean_int(JNIEnv* pEnv, IntPtr p1, jboolean* p2, int p3);
741
delegate void pf_void_IntPtr_pjbyte_int(JNIEnv* pEnv, IntPtr p1, jbyte* p2, int p3);
742
delegate void pf_void_IntPtr_pjchar_int(JNIEnv* pEnv, IntPtr p1, jchar* p2, int p3);
743
delegate void pf_void_IntPtr_pjshort_int(JNIEnv* pEnv, IntPtr p1, jshort* p2, int p3);
744
delegate void pf_void_IntPtr_pjint_int(JNIEnv* pEnv, IntPtr p1, jint* p2, int p3);
745
delegate void pf_void_IntPtr_pjlong_int(JNIEnv* pEnv, IntPtr p1, jlong* p2, int p3);
746
delegate void pf_void_IntPtr_pjfloat_int(JNIEnv* pEnv, IntPtr p1, jfloat* p2, int p3);
747
delegate void pf_void_IntPtr_pjdouble_int(JNIEnv* pEnv, IntPtr p1, jdouble* p2, int p3);
748
delegate int pf_int_int(JNIEnv* pEnv, int p1);
749
delegate IntPtr pf_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, long p2);
750
delegate long pf_long_IntPtr(JNIEnv* pEnv, IntPtr p1);
751
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3);
753
internal static void* vtable;
755
static VtableBuilder()
757
JNI.jvmCreated = true;
759
void** pmcpp = NativeLibrary.GetJNIEnvVTable();
760
void** p = (void**)JniMem.Alloc(IntPtr.Size * vtableDelegates.Length);
761
for(int i = 0; i < vtableDelegates.Length; i++)
763
if(vtableDelegates[i] != null)
765
// TODO on Whidbey we can use Marshal.GetFunctionPointerForDelegate
766
p[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]);
776
static Delegate[] vtableDelegates =
778
new pf_int_IntPtr_pbyte(JNIEnv.GetMethodArgs), //virtual void JNICALL reserved0();
779
null, //virtual void JNICALL reserved1();
780
null, //virtual void JNICALL reserved2();
781
null, //virtual void JNICALL reserved3();
783
new pf_int(JNIEnv.GetVersion), //virtual jint JNICALL GetVersion();
785
new pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv.DefineClass), //virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len);
786
new pf_IntPtr_pbyte(JNIEnv.FindClass), //virtual jclass JNICALL FindClass(const char *name);
788
new pf_IntPtr_IntPtr(JNIEnv.FromReflectedMethod), //virtual jmethodID JNICALL FromReflectedMethod(jobject method);
789
new pf_IntPtr_IntPtr(JNIEnv.FromReflectedField), //virtual jfieldID JNICALL FromReflectedField(jobject field);
790
new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedMethod), //virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID, jboolean isStatic);
792
new pf_IntPtr_IntPtr(JNIEnv.GetSuperclass), //virtual jclass JNICALL GetSuperclass(jclass sub);
793
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsAssignableFrom), //virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup);
795
new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID, jboolean isStatic);
797
new pf_int_IntPtr(JNIEnv.Throw), //virtual jint JNICALL Throw(jthrowable obj);
798
new pf_int_IntPtr_pbyte(JNIEnv.ThrowNew), //virtual jint JNICALL ThrowNew(jclass clazz, const char *msg);
799
new pf_IntPtr(JNIEnv.ExceptionOccurred), //virtual jthrowable JNICALL ExceptionOccurred();
800
new pf_void(JNIEnv.ExceptionDescribe), //virtual void JNICALL ExceptionDescribe();
801
new pf_void(JNIEnv.ExceptionClear), //virtual void JNICALL ExceptionClear();
802
new pf_void_pbyte(JNIEnv.FatalError), //virtual void JNICALL FatalError(const char *msg);
804
new pf_int_int(JNIEnv.PushLocalFrame), //virtual jint JNICALL PushLocalFrame(jint capacity);
805
new pf_IntPtr_IntPtr(JNIEnv.PopLocalFrame), //virtual jobject JNICALL PopLocalFrame(jobject result);
807
new pf_IntPtr_IntPtr(JNIEnv.NewGlobalRef), //virtual jobject JNICALL NewGlobalRef(jobject lobj);
808
new pf_void_IntPtr(JNIEnv.DeleteGlobalRef), //virtual void JNICALL DeleteGlobalRef(jobject gref);
809
new pf_void_IntPtr(JNIEnv.DeleteLocalRef), //virtual void JNICALL DeleteLocalRef(jobject obj);
810
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsSameObject), //virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2);
812
new pf_IntPtr_IntPtr(JNIEnv.NewLocalRef), //virtual jobject JNICALL NewLocalRef(jobject ref);
813
new pf_int_int(JNIEnv.EnsureLocalCapacity), //virtual jint JNICALL EnsureLocalCapacity(jint capacity);
815
new pf_IntPtr_IntPtr(JNIEnv.AllocObject), //virtual jobject JNICALL AllocObject(jclass clazz);
816
null, //virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...);
817
null, //virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args);
818
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.NewObjectA), //virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args);
820
new pf_IntPtr_IntPtr(JNIEnv.GetObjectClass), //virtual jclass JNICALL GetObjectClass(jobject obj);
821
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsInstanceOf), //virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz);
823
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetMethodID), //virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig);
825
null, //virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...);
826
null, //virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args);
827
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallObjectMethodA), //virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args);
829
null, //virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...);
830
null, //virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args);
831
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallBooleanMethodA), //virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args);
833
null, //virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...);
834
null, //virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args);
835
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallByteMethodA), //virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args);
837
null, //virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...);
838
null, //virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args);
839
new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallCharMethodA), //virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args);
841
null, //virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...);
842
null, //virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args);
843
new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallShortMethodA), //virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args);
845
null, //virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...);
846
null, //virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args);
847
new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallIntMethodA), //virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args);
849
null, //virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...);
850
null, //virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args);
851
new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallLongMethodA), //virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args);
853
null, //virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...);
854
null, //virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args);
855
new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallFloatMethodA), //virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args);
857
null, //virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...);
858
null, //virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args);
859
new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallDoubleMethodA), //virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args);
861
null, //virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...);
862
null, //virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args);
863
new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallVoidMethodA), //virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args);
865
null, //virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
866
null, //virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
867
new pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualObjectMethodA), //virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
869
null, //virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
870
null, //virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
871
new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualBooleanMethodA), //virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
873
null, //virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
874
null, //virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
875
new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualByteMethodA), //virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
877
null, //virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
878
null, //virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
879
new pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualCharMethodA), //virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
881
null, //virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
882
null, //virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
883
new pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualShortMethodA), //virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
885
null, //virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
886
null, //virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
887
new pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualIntMethodA), //virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
889
null, //virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
890
null, //virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
891
new pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualLongMethodA), //virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
893
null, //virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
894
null, //virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
895
new pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualFloatMethodA), //virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
897
null, //virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
898
null, //virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
899
new pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualDoubleMethodA), //virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
901
null, //virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
902
null, //virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
903
new pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualVoidMethodA), //virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
905
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetFieldID), //virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig);
907
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID);
908
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID);
909
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID);
910
new pf_ushort_IntPtr_IntPtr(JNIEnv.GetCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID);
911
new pf_short_IntPtr_IntPtr(JNIEnv.GetShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID);
912
new pf_int_IntPtr_IntPtr(JNIEnv.GetIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID);
913
new pf_long_IntPtr_IntPtr(JNIEnv.GetLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID);
914
new pf_float_IntPtr_IntPtr(JNIEnv.GetFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID);
915
new pf_double_IntPtr_IntPtr(JNIEnv.GetDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID);
917
new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val);
918
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
919
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val);
920
new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val);
921
new pf_void_IntPtr_IntPtr_short(JNIEnv.SetShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val);
922
new pf_void_IntPtr_IntPtr_int(JNIEnv.SetIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val);
923
new pf_void_IntPtr_IntPtr_long(JNIEnv.SetLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val);
924
new pf_void_IntPtr_IntPtr_float(JNIEnv.SetFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
925
new pf_void_IntPtr_IntPtr_double(JNIEnv.SetDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
927
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticMethodID), //virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig);
929
null, //virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...);
930
null, //virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args);
931
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticObjectMethodA), //virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args);
933
null, //virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...);
934
null, //virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args);
935
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticBooleanMethodA), //virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args);
937
null, //virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...);
938
null, //virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args);
939
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticByteMethodA), //virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args);
941
null, //virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...);
942
null, //virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args);
943
new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticCharMethodA), //virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args);
945
null, //virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...);
946
null, //virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args);
947
new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticShortMethodA), //virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args);
949
null, //virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...);
950
null, //virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args);
951
new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticIntMethodA), //virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args);
953
null, //virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...);
954
null, //virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args);
955
new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticLongMethodA), //virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args);
957
null, //virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...);
958
null, //virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args);
959
new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticFloatMethodA), //virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args);
961
null, //virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...);
962
null, //virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args);
963
new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticDoubleMethodA), //virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args);
965
null, //virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...);
966
null, //virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args);
967
new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticVoidMethodA), //virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args);
969
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticFieldID), //virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig);
971
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStaticObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID);
972
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID);
973
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID);
974
new pf_ushort_IntPtr_IntPtr(JNIEnv.GetStaticCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID);
975
new pf_short_IntPtr_IntPtr(JNIEnv.GetStaticShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID);
976
new pf_int_IntPtr_IntPtr(JNIEnv.GetStaticIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID);
977
new pf_long_IntPtr_IntPtr(JNIEnv.GetStaticLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID);
978
new pf_float_IntPtr_IntPtr(JNIEnv.GetStaticFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID);
979
new pf_double_IntPtr_IntPtr(JNIEnv.GetStaticDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID);
981
new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetStaticObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val);
982
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
983
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val);
984
new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetStaticCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val);
985
new pf_void_IntPtr_IntPtr_short(JNIEnv.SetStaticShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val);
986
new pf_void_IntPtr_IntPtr_int(JNIEnv.SetStaticIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val);
987
new pf_void_IntPtr_IntPtr_long(JNIEnv.SetStaticLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val);
988
new pf_void_IntPtr_IntPtr_float(JNIEnv.SetStaticFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
989
new pf_void_IntPtr_IntPtr_double(JNIEnv.SetStaticDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
991
new pf_IntPtr_pjchar_int(JNIEnv.NewString), //virtual jstring JNICALL NewString(const jchar *unicode, jsize len);
992
new pf_int_IntPtr(JNIEnv.GetStringLength), //virtual jsize JNICALL GetStringLength(jstring str);
993
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringChars), //virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy);
994
new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringChars), //virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars);
996
new pf_IntPtr_pbyte(JNIEnv.NewStringUTF), //virtual jstring JNICALL NewStringUTF(const char *utf);
997
new pf_int_IntPtr(JNIEnv.GetStringUTFLength), //virtual jsize JNICALL GetStringUTFLength(jstring str);
998
new pf_pbyte_IntPtr_pjboolean(JNIEnv.GetStringUTFChars), //virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy);
999
new pf_void_IntPtr_pbyte(JNIEnv.ReleaseStringUTFChars), //virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars);
1001
new pf_int_IntPtr(JNIEnv.GetArrayLength), //virtual jsize JNICALL GetArrayLength(jarray array);
1003
new pf_IntPtr_int_IntPtr_IntPtr(JNIEnv.NewObjectArray), //virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init);
1004
new pf_IntPtr_IntPtr_int(JNIEnv.GetObjectArrayElement), //virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index);
1005
new pf_void_IntPtr_int_IntPtr(JNIEnv.SetObjectArrayElement), //virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val);
1007
new pf_IntPtr_int(JNIEnv.NewBooleanArray), //virtual jbooleanArray JNICALL NewBooleanArray(jsize len);
1008
new pf_IntPtr_int(JNIEnv.NewByteArray), //virtual jbyteArray JNICALL NewByteArray(jsize len);
1009
new pf_IntPtr_int(JNIEnv.NewCharArray), //virtual jcharArray JNICALL NewCharArray(jsize len);
1010
new pf_IntPtr_int(JNIEnv.NewShortArray), //virtual jshortArray JNICALL NewShortArray(jsize len);
1011
new pf_IntPtr_int(JNIEnv.NewIntArray), //virtual jintArray JNICALL NewIntArray(jsize len);
1012
new pf_IntPtr_int(JNIEnv.NewLongArray), //virtual jlongArray JNICALL NewLongArray(jsize len);
1013
new pf_IntPtr_int(JNIEnv.NewFloatArray), //virtual jfloatArray JNICALL NewFloatArray(jsize len);
1014
new pf_IntPtr_int(JNIEnv.NewDoubleArray), //virtual jdoubleArray JNICALL NewDoubleArray(jsize len);
1016
new pf_pjboolean_IntPtr_pjboolean(JNIEnv.GetBooleanArrayElements), //virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy);
1017
new pf_pjbyte_IntPtr_pjboolean(JNIEnv.GetByteArrayElements), //virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy);
1018
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetCharArrayElements), //virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy);
1019
new pf_pjshort_IntPtr_pjboolean(JNIEnv.GetShortArrayElements), //virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy);
1020
new pf_pjint_IntPtr_pjboolean(JNIEnv.GetIntArrayElements), //virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy);
1021
new pf_pjlong_IntPtr_pjboolean(JNIEnv.GetLongArrayElements), //virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy);
1022
new pf_pjfloat_IntPtr_pjboolean(JNIEnv.GetFloatArrayElements), //virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy);
1023
new pf_pjdouble_IntPtr_pjboolean(JNIEnv.GetDoubleArrayElements), //virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy);
1025
new pf_void_IntPtr_pjboolean_int(JNIEnv.ReleaseBooleanArrayElements), //virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode);
1026
new pf_void_IntPtr_pjbyte_int(JNIEnv.ReleaseByteArrayElements), //virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode);
1027
new pf_void_IntPtr_pjchar_int(JNIEnv.ReleaseCharArrayElements), //virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode);
1028
new pf_void_IntPtr_pjshort_int(JNIEnv.ReleaseShortArrayElements), //virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode);
1029
new pf_void_IntPtr_pjint_int(JNIEnv.ReleaseIntArrayElements), //virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode);
1030
new pf_void_IntPtr_pjlong_int(JNIEnv.ReleaseLongArrayElements), //virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode);
1031
new pf_void_IntPtr_pjfloat_int(JNIEnv.ReleaseFloatArrayElements), //virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode);
1032
new pf_void_IntPtr_pjdouble_int(JNIEnv.ReleaseDoubleArrayElements), //virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode);
1034
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetBooleanArrayRegion), //virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
1035
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetByteArrayRegion), //virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
1036
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetCharArrayRegion), //virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
1037
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetShortArrayRegion), //virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
1038
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetIntArrayRegion), //virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
1039
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetLongArrayRegion), //virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
1040
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetFloatArrayRegion), //virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
1041
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetDoubleArrayRegion), //virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
1043
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetBooleanArrayRegion), //virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
1044
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetByteArrayRegion), //virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
1045
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetCharArrayRegion), //virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
1046
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetShortArrayRegion), //virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
1047
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetIntArrayRegion), //virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
1048
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetLongArrayRegion), //virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
1049
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetFloatArrayRegion), //virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
1050
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetDoubleArrayRegion), //virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
1052
new pf_int_IntPtr_pJNINativeMethod_int(JNIEnv.RegisterNatives), //virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);
1053
new pf_int_IntPtr(JNIEnv.UnregisterNatives), //virtual jint JNICALL UnregisterNatives(jclass clazz);
1055
new pf_int_IntPtr(JNIEnv.MonitorEnter), //virtual jint JNICALL MonitorEnter(jobject obj);
1056
new pf_int_IntPtr(JNIEnv.MonitorExit), //virtual jint JNICALL MonitorExit(jobject obj);
1058
new pf_int_ppJavaVM(JNIEnv.GetJavaVM), //virtual jint JNICALL GetJavaVM(JavaVM **vm);
1060
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringRegion), //virtual void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf);
1061
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringUTFRegion), //virtual void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf);
1063
new pf_pvoid_IntPtr_pjboolean(JNIEnv.GetPrimitiveArrayCritical), //virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy);
1064
new pf_void_IntPtr_pvoid_int(JNIEnv.ReleasePrimitiveArrayCritical), //virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode);
1066
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringCritical), //virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy);
1067
new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringCritical), //virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring);
1069
new pf_IntPtr_IntPtr(JNIEnv.NewWeakGlobalRef), //virtual jweak JNICALL NewWeakGlobalRef(jobject obj);
1070
new pf_void_IntPtr(JNIEnv.DeleteWeakGlobalRef), //virtual void JNICALL DeleteWeakGlobalRef(jweak ref);
1072
new pf_sbyte(JNIEnv.ExceptionCheck), //virtual jboolean JNICALL ExceptionCheck();
1074
new pf_IntPtr_IntPtr_long(JNIEnv.NewDirectByteBuffer), //virtual jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity);
1075
new pf_IntPtr_IntPtr(JNIEnv.GetDirectBufferAddress), //virtual void* JNICALL GetDirectBufferAddress(jobject buf);
1076
new pf_long_IntPtr(JNIEnv.GetDirectBufferCapacity), //virtual jlong JNICALL GetDirectBufferCapacity(jobject buf);
1078
new pf_int_IntPtr(JNIEnv.GetObjectRefType) // virtual jobjectRefType GetObjectRefType(jobject obj);
1082
[StructLayout(LayoutKind.Sequential)]
1083
unsafe struct JavaVMAttachArgs
1085
internal jint version;
1086
internal byte* name;
1087
internal jobject group;
1090
[StructLayout(LayoutKind.Sequential)]
1091
unsafe struct JavaVM
1093
internal static JavaVM* pJavaVM;
1095
void* firstVtableEntry;
1096
delegate int pf_int(JavaVM* pJVM);
1097
delegate int pf_int_ppvoid_pvoid(JavaVM* pJVM, void** p1, void* p2);
1098
delegate int pf_int_ppvoid_int(JavaVM* pJVM, void** p1, int p2);
1100
static Delegate[] vtableDelegates =
1105
new pf_int(DestroyJavaVM),
1106
new pf_int_ppvoid_pvoid(AttachCurrentThread),
1107
new pf_int(DetachCurrentThread),
1108
new pf_int_ppvoid_int(GetEnv),
1109
new pf_int_ppvoid_pvoid(AttachCurrentThreadAsDaemon)
1114
JNI.jvmCreated = true;
1115
pJavaVM = (JavaVM*)(void*)JniMem.Alloc(IntPtr.Size * (1 + vtableDelegates.Length));
1116
pJavaVM->vtable = &pJavaVM->firstVtableEntry;
1117
for(int i = 0; i < vtableDelegates.Length; i++)
1119
pJavaVM->vtable[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]);
1123
internal static jint DestroyJavaVM(JavaVM* pJVM)
1125
if(JNI.jvmDestroyed)
1127
return JNIEnv.JNI_ERR;
1129
JNI.jvmDestroyed = true;
1130
IKVM.NativeCode.java.lang.Thread.WaitUntilLastJniThread();
1131
return JNIEnv.JNI_OK;
1134
internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args)
1136
return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, false);
1139
internal static jint AttachCurrentThreadImpl(JavaVM* pJVM, void** penv, JavaVMAttachArgs* pAttachArgs, bool asDaemon)
1141
if(pAttachArgs != null)
1143
if(!JNI.IsSupportedJniVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1)
1146
return JNIEnv.JNI_EVERSION;
1149
JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv;
1152
*penv = env.pJNIEnv;
1153
return JNIEnv.JNI_OK;
1155
// NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code,
1156
// but it's not impossible that the thread started life as a managed thread and if it did the changes to the
1157
// thread we're making are somewhat dubious.
1158
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
1159
if(pAttachArgs != null)
1161
if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
1165
System.Threading.Thread.CurrentThread.Name = JNIEnv.StringFromUTF8(pAttachArgs->name);
1167
catch(InvalidOperationException)
1169
// someone beat us to it...
1172
object threadGroup = GlobalRefs.Unwrap(pAttachArgs->group.ToInt32());
1173
if(threadGroup != null)
1175
IKVM.NativeCode.java.lang.Thread.AttachThreadFromJni(threadGroup);
1178
*penv = JNIEnv.CreateJNIEnv();
1179
return JNIEnv.JNI_OK;
1182
internal static jint DetachCurrentThread(JavaVM* pJVM)
1184
if(TlsHack.ManagedJNIEnv == null)
1186
// the JDK allows detaching from an already detached thread
1187
return JNIEnv.JNI_OK;
1189
// TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true.
1190
JNIEnv.FreeJNIEnv();
1191
IKVM.NativeCode.ikvm.runtime.Startup.jniDetach();
1192
return JNIEnv.JNI_OK;
1195
internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version)
1197
if(JNI.IsSupportedJniVersion(version))
1199
JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv;
1202
*penv = env.pJNIEnv;
1203
return JNIEnv.JNI_OK;
1206
return JNIEnv.JNI_EDETACHED;
1209
return JNIEnv.JNI_EVERSION;
1212
internal static jint AttachCurrentThreadAsDaemon(JavaVM* pJVM, void **penv, void *args)
1214
return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, true);
1218
[StructLayout(LayoutKind.Sequential)]
1219
unsafe struct JNIEnv
1221
internal const int JNI_OK = 0;
1222
internal const int JNI_ERR = -1;
1223
internal const int JNI_EDETACHED = -2;
1224
internal const int JNI_EVERSION = -3;
1225
internal const int JNI_COMMIT = 1;
1226
internal const int JNI_ABORT = 2;
1227
internal const int JNI_VERSION_1_1 = 0x00010001;
1228
internal const int JNI_VERSION_1_2 = 0x00010002;
1229
internal const int JNI_VERSION_1_4 = 0x00010004;
1230
internal const int JNI_VERSION_1_6 = 0x00010006;
1231
internal const int JNIInvalidRefType = 0;
1232
internal const int JNILocalRefType = 1;
1233
internal const int JNIGlobalRefType = 2;
1234
internal const int JNIWeakGlobalRefType = 3;
1235
internal const sbyte JNI_TRUE = 1;
1236
internal const sbyte JNI_FALSE = 0;
1237
private void* vtable;
1238
private GCHandle managedJNIEnv;
1239
private GCHandle* pinHandles;
1240
private int pinHandleMaxCount;
1241
private int pinHandleInUseCount;
1245
// we set the field here so that IKVM.Runtime.dll doesn't have to load us if we're not otherwise needed
1246
IKVM.NativeCode.java.lang.SecurityManager.jniAssembly = typeof(JNIEnv).Assembly;
1249
internal ManagedJNIEnv GetManagedJNIEnv()
1251
return (ManagedJNIEnv)managedJNIEnv.Target;
1254
internal sealed class ManagedJNIEnv
1256
// NOTE the initial bucket size must be a power of two < LOCAL_REF_MAX_BUCKET_SIZE,
1257
// because each time we grow it, we double the size and it must eventually reach
1258
// exactly LOCAL_REF_MAX_BUCKET_SIZE
1259
private const int LOCAL_REF_INITIAL_BUCKET_SIZE = 32;
1260
private const int LOCAL_REF_SHIFT = 10;
1261
private const int LOCAL_REF_MAX_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT);
1262
private const int LOCAL_REF_MASK = (LOCAL_REF_MAX_BUCKET_SIZE - 1);
1263
internal readonly JNIEnv* pJNIEnv;
1264
internal ClassLoaderWrapper classLoader;
1265
internal ikvm.@internal.CallerID callerID;
1266
private object[][] localRefs;
1267
private int localRefSlot;
1268
private int localRefIndex;
1269
private object[] active;
1270
internal Exception pendingException;
1272
internal ManagedJNIEnv()
1274
pJNIEnv = (JNIEnv*)JniMem.Alloc(sizeof(JNIEnv));
1275
localRefs = new object[32][];
1276
active = localRefs[0] = new object[LOCAL_REF_INITIAL_BUCKET_SIZE];
1277
// stuff something in the first entry to make sure we don't hand out a zero handle
1278
// (a zero handle corresponds to a null reference)
1285
// NOTE don't clean up when we're being unloaded (we'll get cleaned up anyway and because
1286
// of the unorderedness of the finalization process native code could still be run after
1288
// NOTE when we're not the default AppDomain and we're being unloaded,
1289
// we're leaking the JNIEnv (but since JNI outside of the default AppDomain isn't currently supported,
1290
// I can live with that).
1291
if(!Environment.HasShutdownStarted)
1293
if(pJNIEnv->managedJNIEnv.IsAllocated)
1295
pJNIEnv->managedJNIEnv.Free();
1297
for(int i = 0; i < pJNIEnv->pinHandleMaxCount; i++)
1299
if(pJNIEnv->pinHandles[i].IsAllocated)
1301
pJNIEnv->pinHandles[i].Free();
1304
JniMem.Free((IntPtr)(void*)pJNIEnv);
1308
internal struct FrameState
1310
internal readonly ikvm.@internal.CallerID callerID;
1311
internal readonly int localRefSlot;
1312
internal readonly int localRefIndex;
1314
internal FrameState(ikvm.@internal.CallerID callerID, int localRefSlot, int localRefIndex)
1316
this.callerID = callerID;
1317
this.localRefSlot = localRefSlot;
1318
this.localRefIndex = localRefIndex;
1322
internal FrameState Enter(ikvm.@internal.CallerID newCallerID)
1324
FrameState prev = new FrameState(callerID, localRefSlot, localRefIndex);
1325
this.callerID = newCallerID;
1327
if (localRefSlot >= localRefs.Length)
1329
object[][] tmp = new object[localRefs.Length * 2][];
1330
Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
1334
active = localRefs[localRefSlot];
1337
active = localRefs[localRefSlot] = new object[LOCAL_REF_INITIAL_BUCKET_SIZE];
1342
internal Exception Leave(FrameState prev)
1344
// on the current (.NET 2.0 SP2) x86 JIT an explicit for loop is faster than Array.Clear() up to about 100 elements
1345
for (int i = 0; i < localRefIndex; i++)
1349
while (--localRefSlot != prev.localRefSlot)
1351
if (localRefs[localRefSlot] != null)
1353
if (localRefs[localRefSlot].Length == LOCAL_REF_MAX_BUCKET_SIZE)
1355
// if the bucket is totally allocated, we're assuming a leaky method so we throw the bucket away
1356
localRefs[localRefSlot] = null;
1360
Array.Clear(localRefs[localRefSlot], 0, localRefs[localRefSlot].Length);
1364
active = localRefs[localRefSlot];
1365
this.localRefIndex = prev.localRefIndex;
1366
this.callerID = prev.callerID;
1367
Exception x = pendingException;
1368
pendingException = null;
1372
internal jobject MakeLocalRef(object obj)
1380
if (localRefIndex == active.Length)
1382
index = FindFreeIndex();
1386
index = localRefIndex++;
1388
active[index] = obj;
1389
return (IntPtr)((localRefSlot << LOCAL_REF_SHIFT) + index);
1392
private int FindFreeIndex()
1394
for (int i = 0; i < active.Length; i++)
1396
if (active[i] == null)
1398
while (localRefIndex - 1 > i && active[localRefIndex - 1] == null)
1406
return localRefIndex++;
1409
private void GrowActiveSlot()
1411
if (active.Length < LOCAL_REF_MAX_BUCKET_SIZE)
1413
object[] tmp = new object[active.Length * 2];
1414
Array.Copy(active, tmp, active.Length);
1415
active = localRefs[localRefSlot] = tmp;
1418
// if we get here, we're in a native method that most likely is leaking locals refs,
1419
// so we're going to allocate a new bucket and increment localRefSlot, this means that
1420
// any slots that become available in the previous bucket are not going to be reused,
1421
// but since we're assuming that the method is leaking anyway, that isn't a problem
1422
// (it's never a correctness issue, just a resource consumption issue)
1425
if (localRefSlot == localRefs.Length)
1427
object[][] tmp = new object[localRefSlot * 2][];
1428
Array.Copy(localRefs, 0, tmp, 0, localRefSlot);
1431
active = localRefs[localRefSlot];
1434
active = localRefs[localRefSlot] = new object[LOCAL_REF_MAX_BUCKET_SIZE];
1438
internal object UnwrapLocalRef(int i)
1440
return localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK];
1443
internal int PushLocalFrame(jint capacity)
1446
if (localRefSlot >= localRefs.Length)
1448
object[][] tmp = new object[localRefs.Length * 2][];
1449
Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
1452
// we use a null slot to mark the fact that we used PushLocalFrame
1453
localRefs[localRefSlot - 1] = null;
1454
if (localRefs[localRefSlot] == null)
1456
// we can't use capacity directly, because the array length must be a power of two
1457
// and it can't be bigger than LOCAL_REF_MAX_BUCKET_SIZE
1459
capacity = Math.Min(capacity, LOCAL_REF_MAX_BUCKET_SIZE);
1460
while (r < capacity)
1464
localRefs[localRefSlot] = new object[r];
1467
active = localRefs[localRefSlot];
1471
internal jobject PopLocalFrame(object res)
1473
while (localRefs[localRefSlot] != null)
1475
localRefs[localRefSlot] = null;
1479
localRefIndex = localRefs[localRefSlot].Length;
1480
active = localRefs[localRefSlot];
1481
return MakeLocalRef(res);
1484
internal void DeleteLocalRef(jobject obj)
1486
int i = obj.ToInt32();
1489
localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK] = null;
1494
Debug.Assert(false, "bogus localref in DeleteLocalRef");
1499
internal static JNIEnv* CreateJNIEnv()
1501
ManagedJNIEnv env = new ManagedJNIEnv();
1502
TlsHack.ManagedJNIEnv = env;
1503
JNIEnv* pJNIEnv = env.pJNIEnv;
1504
pJNIEnv->vtable = VtableBuilder.vtable;
1505
pJNIEnv->managedJNIEnv = GCHandle.Alloc(env, GCHandleType.WeakTrackResurrection);
1506
pJNIEnv->pinHandles = null;
1507
pJNIEnv->pinHandleMaxCount = 0;
1508
pJNIEnv->pinHandleInUseCount = 0;
1512
internal static void FreeJNIEnv()
1514
TlsHack.ManagedJNIEnv = null;
1517
internal static string StringFromOEM(byte* psz)
1519
for(int i = 0;; i++)
1523
int oem = System.Globalization.CultureInfo.CurrentCulture.TextInfo.OEMCodePage;
1524
return new String((sbyte*)psz, 0, i, Encoding.GetEncoding(oem));
1529
internal static string StringFromUTF8(byte* psz)
1531
// Sun's modified UTF8 encoding is not compatible with System.Text.Encoding.UTF8,
1532
// so we need to roll our own
1534
bool hasNonAscii = false;
1535
while(psz[len] != 0)
1537
hasNonAscii |= psz[len] >= 128;
1542
// optimize the common case of 7-bit ASCII
1543
return new String((sbyte*)psz);
1545
StringBuilder sb = new StringBuilder(len);
1546
for(int i = 0; i < len; i++)
1556
c = (((c & 0x1F) << 6) | (char2 & 0x3F));
1563
c = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F);
1568
return sb.ToString();
1571
private static int StringUTF8Length(string s)
1574
for(int i = 0; i < s.Length; i++)
1577
if((ch != 0) && (ch <= 0x7F))
1581
else if(ch <= 0x7FF)
1593
internal static jint GetMethodArgs(JNIEnv* pEnv, IntPtr method, byte* sig)
1595
TypeWrapper[] argTypes = MethodWrapper.FromCookie(method).GetParameters();
1596
for (int i = 0; i < argTypes.Length; i++)
1598
TypeWrapper tw = argTypes[i];
1601
sig[i] = (byte)tw.SigName[0];
1608
return argTypes.Length;
1611
internal static jint GetVersion(JNIEnv* pEnv)
1613
return JNI_VERSION_1_6;
1616
internal static jclass DefineClass(JNIEnv* pEnv, byte* name, jobject loader, jbyte* pbuf, jint length)
1620
byte[] buf = new byte[length];
1621
Marshal.Copy((IntPtr)(void*)pbuf, buf, 0, length);
1622
// TODO what should the protection domain be?
1623
// NOTE I'm assuming name is platform encoded (as opposed to UTF-8), but the Sun JVM only seems to work for ASCII.
1624
global::java.lang.ClassLoader classLoader = (global::java.lang.ClassLoader)pEnv->UnwrapRef(loader);
1625
return pEnv->MakeLocalRef(IKVM.NativeCode.java.lang.ClassLoader.defineClass0(classLoader, name != null ? StringFromOEM(name) : null, buf, 0, buf.Length, null));
1629
SetPendingException(pEnv, x);
1634
private static ClassLoaderWrapper FindNativeMethodClassLoader(JNIEnv* pEnv)
1636
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1637
if(env.callerID != null)
1639
return ClassLoaderWrapper.FromCallerID(env.callerID);
1641
if(env.classLoader != null)
1643
return env.classLoader;
1645
return ClassLoaderWrapper.GetClassLoaderWrapper(java.lang.ClassLoader.getSystemClassLoader());
1648
internal static jclass FindClass(JNIEnv* pEnv, byte* pszName)
1652
string name = StringFromOEM(pszName);
1653
// don't allow dotted names!
1654
if(name.IndexOf('.') >= 0)
1656
SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name));
1659
// spec doesn't say it, but Sun allows signature format class names (but not for primitives)
1660
if(name.StartsWith("L") && name.EndsWith(";"))
1662
name = name.Substring(1, name.Length - 2);
1664
TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedNameFast(name.Replace('/', '.'));
1667
SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name));
1671
// spec doesn't say it, but Sun runs the static initializer
1672
wrapper.RunClassInit();
1673
return pEnv->MakeLocalRef(wrapper.ClassObject);
1677
if(x is RetargetableJavaException)
1679
x = ((RetargetableJavaException)x).ToJava();
1681
SetPendingException(pEnv, x);
1686
internal static jmethodID FromReflectedMethod(JNIEnv* pEnv, jobject method)
1688
return MethodWrapper.FromMethodOrConstructor(pEnv->UnwrapRef(method)).Cookie;
1691
internal static jfieldID FromReflectedField(JNIEnv* pEnv, jobject field)
1693
return FieldWrapper.FromField(pEnv->UnwrapRef(field)).Cookie;
1696
internal static jobject ToReflectedMethod(JNIEnv* pEnv, jclass clazz_ignored, jmethodID method, jboolean isStatic)
1698
return pEnv->MakeLocalRef(MethodWrapper.FromCookie(method).ToMethodOrConstructor(true));
1701
internal static jclass GetSuperclass(JNIEnv* pEnv, jclass sub)
1703
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(sub)).BaseTypeWrapper;
1704
return pEnv->MakeLocalRef(wrapper == null ? null : wrapper.ClassObject);
1707
internal static jboolean IsAssignableFrom(JNIEnv* pEnv, jclass sub, jclass super)
1709
TypeWrapper w1 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(sub));
1710
TypeWrapper w2 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(super));
1711
return w1.IsAssignableTo(w2) ? JNI_TRUE : JNI_FALSE;
1714
internal static jobject ToReflectedField(JNIEnv* pEnv, jclass clazz_ignored, jfieldID field, jboolean isStatic)
1716
return pEnv->MakeLocalRef(FieldWrapper.FromCookie(field).ToField(true));
1719
private static void SetPendingException(JNIEnv* pEnv, Exception x)
1721
pEnv->GetManagedJNIEnv().pendingException = ikvm.runtime.Util.mapException(x);
1724
internal static jint Throw(JNIEnv* pEnv, jthrowable throwable)
1726
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1727
Exception x = UnwrapRef(env, throwable) as Exception;
1728
env.pendingException = x;
1732
internal static jint ThrowNew(JNIEnv* pEnv, jclass clazz, byte* msg)
1734
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1735
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)UnwrapRef(env, clazz));
1736
MethodWrapper mw = wrapper.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
1740
Exception exception;
1744
java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)mw.ToMethodOrConstructor(false);
1745
exception = (Exception)cons.newInstance(new object[] { StringFromOEM(msg) }, env.callerID);
1748
catch(RetargetableJavaException x)
1750
exception = x.ToJava();
1758
SetPendingException(pEnv, exception);
1763
SetPendingException(pEnv, new java.lang.NoSuchMethodError("<init>(Ljava.lang.String;)V"));
1768
internal static jthrowable ExceptionOccurred(JNIEnv* pEnv)
1770
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1771
return pEnv->MakeLocalRef(env.pendingException);
1774
internal static void ExceptionDescribe(JNIEnv* pEnv)
1776
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1777
Exception x = env.pendingException;
1780
env.pendingException = null;
1783
ikvm.extensions.ExtensionMethods.printStackTrace(x);
1787
Debug.Assert(false, ex.ToString());
1792
internal static void ExceptionClear(JNIEnv* pEnv)
1794
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1795
env.pendingException = null;
1798
internal static void FatalError(JNIEnv* pEnv, byte* msg)
1800
Console.Error.WriteLine("FATAL ERROR in native method: {0}", msg == null ? "(null)" : StringFromOEM(msg));
1801
Console.Error.WriteLine(new StackTrace(1, true));
1802
Environment.Exit(1);
1805
internal static jint PushLocalFrame(JNIEnv* pEnv, jint capacity)
1807
return pEnv->GetManagedJNIEnv().PushLocalFrame(capacity);
1810
internal static jobject PopLocalFrame(JNIEnv* pEnv, jobject result)
1812
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1813
return env.PopLocalFrame(UnwrapRef(env, result));
1816
internal static jobject NewGlobalRef(JNIEnv* pEnv, jobject obj)
1818
object o = pEnv->UnwrapRef(obj);
1823
lock(GlobalRefs.globalRefs)
1825
int index = GlobalRefs.globalRefs.IndexOf(null);
1828
GlobalRefs.globalRefs[index] = o;
1832
index = GlobalRefs.globalRefs.Add(o);
1834
return (IntPtr)(-(index + 1));
1838
internal static void DeleteGlobalRef(JNIEnv* pEnv, jobject obj)
1840
int i = obj.ToInt32();
1843
lock(GlobalRefs.globalRefs)
1845
GlobalRefs.globalRefs[(-i) - 1] = null;
1851
Debug.Assert(false, "Local ref passed to DeleteGlobalRef");
1855
internal static void DeleteLocalRef(JNIEnv* pEnv, jobject obj)
1857
pEnv->GetManagedJNIEnv().DeleteLocalRef(obj);
1860
internal static jboolean IsSameObject(JNIEnv* pEnv, jobject obj1, jobject obj2)
1862
return pEnv->UnwrapRef(obj1) == pEnv->UnwrapRef(obj2) ? JNI_TRUE : JNI_FALSE;
1865
internal static jobject NewLocalRef(JNIEnv* pEnv, jobject obj)
1867
return pEnv->MakeLocalRef(pEnv->UnwrapRef(obj));
1870
internal static jint EnsureLocalCapacity(JNIEnv* pEnv, jint capacity)
1872
// since we can dynamically grow the local ref table, we'll just return success for any number
1876
internal static jobject AllocObject(JNIEnv* pEnv, jclass clazz)
1878
return AllocObjectImpl(pEnv, TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)));
1881
private static jobject AllocObjectImpl(JNIEnv* pEnv, TypeWrapper wrapper)
1885
if(wrapper.IsAbstract)
1887
SetPendingException(pEnv, new java.lang.InstantiationException(wrapper.Name));
1891
return pEnv->MakeLocalRef(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType));
1893
catch(RetargetableJavaException x)
1895
SetPendingException(pEnv, x.ToJava());
1900
SetPendingException(pEnv, x);
1905
[StructLayout(LayoutKind.Explicit)]
1906
internal struct jvalue
1928
private static object InvokeHelper(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args, bool nonVirtual)
1930
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
1931
MethodWrapper mw = MethodWrapper.FromCookie(methodID);
1932
TypeWrapper[] argTypes = mw.GetParameters();
1933
object[] argarray = new object[argTypes.Length];
1934
for (int i = 0; i < argarray.Length; i++)
1936
TypeWrapper type = argTypes[i];
1937
if (type == PrimitiveTypeWrapper.BOOLEAN)
1938
argarray[i] = java.lang.Boolean.valueOf(args[i].z != JNI_FALSE);
1939
else if (type == PrimitiveTypeWrapper.BYTE)
1940
argarray[i] = java.lang.Byte.valueOf((byte)args[i].b);
1941
else if (type == PrimitiveTypeWrapper.CHAR)
1942
argarray[i] = java.lang.Character.valueOf((char)args[i].c);
1943
else if (type == PrimitiveTypeWrapper.SHORT)
1944
argarray[i] = java.lang.Short.valueOf(args[i].s);
1945
else if (type == PrimitiveTypeWrapper.INT)
1946
argarray[i] = java.lang.Integer.valueOf(args[i].i);
1947
else if (type == PrimitiveTypeWrapper.LONG)
1948
argarray[i] = java.lang.Long.valueOf(args[i].j);
1949
else if (type == PrimitiveTypeWrapper.FLOAT)
1950
argarray[i] = java.lang.Float.valueOf(args[i].f);
1951
else if (type == PrimitiveTypeWrapper.DOUBLE)
1952
argarray[i] = java.lang.Double.valueOf(args[i].d);
1954
argarray[i] = UnwrapRef(env, args[i].l);
1958
return mw.InvokeJNI(UnwrapRef(env, obj), argarray, nonVirtual, env.callerID);
1960
catch(java.lang.reflect.InvocationTargetException x)
1962
SetPendingException(pEnv, ikvm.runtime.Util.mapException(x.getCause()));
1967
SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
1972
internal static jobject NewObjectA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
1974
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
1975
if(!wrapper.IsAbstract && wrapper.TypeAsBaseType.IsAbstract)
1977
// static newinstance helper method
1978
return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
1980
jobject obj = AllocObjectImpl(pEnv, wrapper);
1981
if(obj != IntPtr.Zero)
1983
InvokeHelper(pEnv, obj, methodID, args, false);
1984
if(ExceptionCheck(pEnv) == JNI_TRUE)
1986
DeleteLocalRef(pEnv, obj);
1993
internal static jclass GetObjectClass(JNIEnv* pEnv, jobject obj)
1995
return pEnv->MakeLocalRef(IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj)));
1998
internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz)
2000
// NOTE if clazz is an interface, this is still the right thing to do
2001
// (i.e. if the object implements the interface, we return true)
2002
java.lang.Class objClass = IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj));
2003
TypeWrapper w1 = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
2004
TypeWrapper w2 = TypeWrapper.FromClass(objClass);
2005
return w2.IsAssignableTo(w1) ? JNI_TRUE : JNI_FALSE;
2008
private static MethodWrapper GetMethodImpl(TypeWrapper tw, string name, string sig)
2012
MethodWrapper mw = tw.GetMethodWrapper(name, sig, true);
2013
if(mw == null || !mw.IsHideFromReflection)
2017
tw = mw.DeclaringType.BaseTypeWrapper;
2025
private static void AppendInterfaces(List<TypeWrapper> list, IList<TypeWrapper> add)
2027
foreach (TypeWrapper iface in add)
2029
if (!list.Contains(iface))
2036
private static List<TypeWrapper> TransitiveInterfaces(TypeWrapper tw)
2038
List<TypeWrapper> list = new List<TypeWrapper>();
2039
if (tw.BaseTypeWrapper != null)
2041
AppendInterfaces(list, TransitiveInterfaces(tw.BaseTypeWrapper));
2043
foreach (TypeWrapper iface in tw.Interfaces)
2045
AppendInterfaces(list, TransitiveInterfaces(iface));
2047
AppendInterfaces(list, tw.Interfaces);
2051
private static MethodWrapper GetInterfaceMethodImpl(TypeWrapper tw, string name, string sig)
2053
foreach (TypeWrapper iface in TransitiveInterfaces(tw))
2055
MethodWrapper mw = iface.GetMethodWrapper(name, sig, false);
2056
if (mw != null && !mw.IsHideFromReflection)
2064
private static jmethodID FindMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
2068
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
2070
// if name == NULL, the JDK returns the constructor
2071
string methodname = (IntPtr)name == IntPtr.Zero ? "<init>" : StringFromUTF8(name);
2072
string methodsig = StringFromUTF8(sig);
2073
MethodWrapper mw = null;
2074
// don't allow dotted names!
2075
if(methodsig.IndexOf('.') < 0)
2077
methodsig = methodsig.Replace('/', '.');
2078
if(methodname == "<init>" || methodname == "<clinit>")
2080
mw = wrapper.GetMethodWrapper(methodname, methodsig, false);
2084
mw = GetMethodImpl(wrapper, methodname, methodsig);
2087
mw = GetInterfaceMethodImpl(wrapper, methodname, methodsig);
2091
if(mw != null && mw.IsStatic == isstatic)
2096
SetPendingException(pEnv, new java.lang.NoSuchMethodError(string.Format("{0}{1}", methodname, methodsig)));
2098
catch(RetargetableJavaException x)
2100
SetPendingException(pEnv, x.ToJava());
2104
SetPendingException(pEnv, x);
2109
internal static jmethodID GetMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2111
return FindMethodID(pEnv, clazz, name, sig, false);
2114
internal static jobject CallObjectMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2116
return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, false));
2119
internal static jboolean CallBooleanMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2121
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2124
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
2129
internal static jbyte CallByteMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2131
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2134
return (jbyte)(byte)o;
2139
internal static jchar CallCharMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2141
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2144
return (jchar)(char)o;
2149
internal static jshort CallShortMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2151
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2154
return (jshort)(short)o;
2159
internal static jint CallIntMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2161
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2164
return (jint)(int)o;
2169
internal static jlong CallLongMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2171
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2174
return (jlong)(long)o;
2179
internal static jfloat CallFloatMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2181
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2184
return (jfloat)(float)o;
2189
internal static jdouble CallDoubleMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2191
object o = InvokeHelper(pEnv, obj, methodID, args, false);
2194
return (jdouble)(double)o;
2199
internal static void CallVoidMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2201
InvokeHelper(pEnv, obj, methodID, args, false);
2204
internal static jobject CallNonvirtualObjectMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2206
return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, true));
2209
internal static jboolean CallNonvirtualBooleanMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2211
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2214
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
2219
internal static jbyte CallNonvirtualByteMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2221
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2224
return (jbyte)(byte)o;
2229
internal static jchar CallNonvirtualCharMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2231
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2234
return (jchar)(char)o;
2239
internal static jshort CallNonvirtualShortMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2241
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2244
return (jshort)(short)o;
2249
internal static jint CallNonvirtualIntMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2251
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2254
return (jint)(int)o;
2259
internal static jlong CallNonvirtualLongMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2261
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2264
return (jlong)(long)o;
2269
internal static jfloat CallNonvirtualFloatMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2271
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2274
return (jfloat)(float)o;
2279
internal static jdouble CallNonvirtualDoubleMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2281
object o = InvokeHelper(pEnv, obj, methodID, args, true);
2284
return (jdouble)(double)o;
2289
internal static void CallNonvirtualVoidMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
2291
InvokeHelper(pEnv, obj, methodID, args, true);
2294
private static FieldWrapper GetFieldImpl(TypeWrapper tw, string name, string sig)
2298
FieldWrapper fw = tw.GetFieldWrapper(name, sig);
2299
if(fw == null || !fw.IsHideFromReflection)
2303
tw = fw.DeclaringType.BaseTypeWrapper;
2311
private static jfieldID FindFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
2315
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
2317
string fieldsig = StringFromUTF8(sig);
2318
// don't allow dotted names!
2319
if(fieldsig.IndexOf('.') < 0)
2321
FieldWrapper fw = GetFieldImpl(wrapper, StringFromUTF8(name), fieldsig.Replace('/', '.'));
2324
if(fw.IsStatic == isstatic)
2330
SetPendingException(pEnv, new java.lang.NoSuchFieldError((isstatic ? "Static" : "Instance") + " field '" + StringFromUTF8(name) + "' with signature '" + fieldsig + "' not found in class '" + wrapper.Name + "'"));
2332
catch(RetargetableJavaException x)
2334
SetPendingException(pEnv, x.ToJava());
2338
SetPendingException(pEnv, x);
2343
internal static jfieldID GetFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2345
return FindFieldID(pEnv, clazz, name, sig, false);
2348
private static sun.reflect.FieldAccessor GetFieldAccessor(jfieldID cookie)
2350
return (sun.reflect.FieldAccessor)FieldWrapper.FromCookie(cookie).GetFieldAccessorJNI();
2353
internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2355
return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(pEnv->UnwrapRef(obj)));
2358
internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2360
return GetFieldAccessor(fieldID).getBoolean(pEnv->UnwrapRef(obj)) ? JNI_TRUE : JNI_FALSE;
2363
internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2365
return (jbyte)GetFieldAccessor(fieldID).getByte(pEnv->UnwrapRef(obj));
2368
internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2370
return (jchar)GetFieldAccessor(fieldID).getChar(pEnv->UnwrapRef(obj));
2373
internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2375
return (jshort)GetFieldAccessor(fieldID).getShort(pEnv->UnwrapRef(obj));
2378
internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2380
return (jint)GetFieldAccessor(fieldID).getInt(pEnv->UnwrapRef(obj));
2383
internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2385
return (jlong)GetFieldAccessor(fieldID).getLong(pEnv->UnwrapRef(obj));
2388
internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2390
return (jfloat)GetFieldAccessor(fieldID).getFloat(pEnv->UnwrapRef(obj));
2393
internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2395
return (jdouble)GetFieldAccessor(fieldID).getDouble(pEnv->UnwrapRef(obj));
2398
internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val)
2400
GetFieldAccessor(fieldID).set(pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val));
2403
internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val)
2405
GetFieldAccessor(fieldID).setBoolean(pEnv->UnwrapRef(obj), val != JNI_FALSE);
2408
internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val)
2410
GetFieldAccessor(fieldID).setByte(pEnv->UnwrapRef(obj), (byte)val);
2413
internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val)
2415
GetFieldAccessor(fieldID).setChar(pEnv->UnwrapRef(obj), (char)val);
2418
internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val)
2420
GetFieldAccessor(fieldID).setShort(pEnv->UnwrapRef(obj), (short)val);
2423
internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val)
2425
GetFieldAccessor(fieldID).setInt(pEnv->UnwrapRef(obj), (int)val);
2428
internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val)
2430
GetFieldAccessor(fieldID).setLong(pEnv->UnwrapRef(obj), (long)val);
2433
internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val)
2435
GetFieldAccessor(fieldID).setFloat(pEnv->UnwrapRef(obj), (float)val);
2438
internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val)
2440
GetFieldAccessor(fieldID).setDouble(pEnv->UnwrapRef(obj), (double)val);
2443
internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2445
return FindMethodID(pEnv, clazz, name, sig, true);
2448
internal static jobject CallStaticObjectMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2450
return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
2453
internal static jboolean CallStaticBooleanMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2455
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2458
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
2463
internal static jbyte CallStaticByteMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2465
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2468
return (jbyte)(byte)o;
2473
internal static jchar CallStaticCharMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2475
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2478
return (jchar)(char)o;
2483
internal static jshort CallStaticShortMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2485
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2488
return (jshort)(short)o;
2493
internal static jint CallStaticIntMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2495
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2498
return (jint)(int)o;
2503
internal static jlong CallStaticLongMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2505
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2508
return (jlong)(long)o;
2513
internal static jfloat CallStaticFloatMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2515
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2518
return (jfloat)(float)o;
2523
internal static jdouble CallStaticDoubleMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2525
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2528
return (jdouble)(double)o;
2533
internal static void CallStaticVoidMethodA(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args)
2535
InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
2538
internal static jfieldID GetStaticFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2540
return FindFieldID(pEnv, clazz, name, sig, true);
2543
internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2545
return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(null));
2548
internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2550
return GetFieldAccessor(fieldID).getBoolean(null) ? JNI_TRUE : JNI_FALSE;
2553
internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2555
return (jbyte)GetFieldAccessor(fieldID).getByte(null);
2558
internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2560
return (jchar)GetFieldAccessor(fieldID).getChar(null);
2563
internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2565
return (jshort)GetFieldAccessor(fieldID).getShort(null);
2568
internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2570
return (jint)GetFieldAccessor(fieldID).getInt(null);
2573
internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2575
return (jlong)GetFieldAccessor(fieldID).getLong(null);
2578
internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2580
return (jfloat)GetFieldAccessor(fieldID).getFloat(null);
2583
internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2585
return (jdouble)GetFieldAccessor(fieldID).getDouble(null);
2588
internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val)
2590
GetFieldAccessor(fieldID).set(null, pEnv->UnwrapRef(val));
2593
internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val)
2595
GetFieldAccessor(fieldID).setBoolean(null, val != JNI_FALSE);
2598
internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val)
2600
GetFieldAccessor(fieldID).setByte(null, (byte)val);
2603
internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val)
2605
GetFieldAccessor(fieldID).setChar(null, (char)val);
2608
internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val)
2610
GetFieldAccessor(fieldID).setShort(null, (short)val);
2613
internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val)
2615
GetFieldAccessor(fieldID).setInt(null, (int)val);
2618
internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val)
2620
GetFieldAccessor(fieldID).setLong(null, (long)val);
2623
internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val)
2625
GetFieldAccessor(fieldID).setFloat(null, (float)val);
2628
internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val)
2630
GetFieldAccessor(fieldID).setDouble(null, (double)val);
2633
internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len)
2635
return pEnv->MakeLocalRef(new String((char*)unicode, 0, len));
2638
internal static jint GetStringLength(JNIEnv* pEnv, jstring str)
2640
return ((string)pEnv->UnwrapRef(str)).Length;
2643
internal static jchar* GetStringChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
2645
string s = (string)pEnv->UnwrapRef(str);
2650
return (jchar*)(void*)Marshal.StringToHGlobalUni(s);
2653
internal static void ReleaseStringChars(JNIEnv* pEnv, jstring str, jchar* chars)
2655
Marshal.FreeHGlobal((IntPtr)(void*)chars);
2658
internal static jobject NewStringUTF(JNIEnv* pEnv, byte* psz)
2660
return pEnv->MakeLocalRef(StringFromUTF8(psz));
2663
internal static jint GetStringUTFLength(JNIEnv* pEnv, jstring str)
2665
return StringUTF8Length((string)pEnv->UnwrapRef(str));
2668
internal static byte* GetStringUTFChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
2670
string s = (string)pEnv->UnwrapRef(str);
2671
byte* buf = (byte*)JniMem.Alloc(StringUTF8Length(s) + 1);
2673
for(int i = 0; i < s.Length; i++)
2676
if((ch != 0) && (ch <= 0x7F))
2678
buf[j++] = (byte)ch;
2680
else if(ch <= 0x7FF)
2682
buf[j++] = (byte)((ch >> 6) | 0xC0);
2683
buf[j++] = (byte)((ch & 0x3F) | 0x80);
2687
buf[j++] = (byte)((ch >> 12) | 0xE0);
2688
buf[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80);
2689
buf[j++] = (byte)((ch & 0x3F) | 0x80);
2700
internal static void ReleaseStringUTFChars(JNIEnv* pEnv, jstring str, byte* chars)
2702
JniMem.Free((IntPtr)(void*)chars);
2705
internal static jsize GetArrayLength(JNIEnv* pEnv, jarray array)
2707
return ((Array)pEnv->UnwrapRef(array)).Length;
2710
internal static jobject NewObjectArray(JNIEnv* pEnv, jsize len, jclass clazz, jobject init)
2714
// we want to support (non-primitive) value types so we can't cast to object[]
2715
Array array = Array.CreateInstance(TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)).TypeAsArrayType, len);
2716
object o = pEnv->UnwrapRef(init);
2719
for(int i = 0; i < array.Length; i++)
2721
array.SetValue(o, i);
2724
return pEnv->MakeLocalRef(array);
2726
catch(ArgumentOutOfRangeException)
2728
SetPendingException(pEnv, new java.lang.NegativeArraySizeException());
2733
SetPendingException(pEnv, x);
2738
internal static jobject GetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index)
2742
// we want to support (non-primitive) value types so we can't cast to object[]
2743
return pEnv->MakeLocalRef(((Array)pEnv->UnwrapRef(array)).GetValue(index));
2745
catch(IndexOutOfRangeException)
2747
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
2752
internal static void SetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index, jobject val)
2756
// we want to support (non-primitive) value types so we can't cast to object[]
2757
((Array)pEnv->UnwrapRef(array)).SetValue(pEnv->UnwrapRef(val), index);
2759
catch(IndexOutOfRangeException)
2761
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
2765
internal static jbooleanArray NewBooleanArray(JNIEnv* pEnv, jsize len)
2769
return pEnv->MakeLocalRef(new bool[len]);
2773
SetPendingException(pEnv, x);
2778
internal static jbyteArray NewByteArray(JNIEnv* pEnv, jsize len)
2782
return pEnv->MakeLocalRef(new byte[len]);
2786
SetPendingException(pEnv, x);
2791
internal static jcharArray NewCharArray(JNIEnv* pEnv, jsize len)
2795
return pEnv->MakeLocalRef(new char[len]);
2799
SetPendingException(pEnv, x);
2804
internal static jshortArray NewShortArray(JNIEnv* pEnv, jsize len)
2808
return pEnv->MakeLocalRef(new short[len]);
2812
SetPendingException(pEnv, x);
2817
internal static jintArray NewIntArray(JNIEnv* pEnv, jsize len)
2821
return pEnv->MakeLocalRef(new int[len]);
2825
SetPendingException(pEnv, x);
2830
internal static jlongArray NewLongArray(JNIEnv* pEnv, jsize len)
2834
return pEnv->MakeLocalRef(new long[len]);
2838
SetPendingException(pEnv, x);
2843
internal static jfloatArray NewFloatArray(JNIEnv* pEnv, jsize len)
2847
return pEnv->MakeLocalRef(new float[len]);
2851
SetPendingException(pEnv, x);
2856
internal static jdoubleArray NewDoubleArray(JNIEnv* pEnv, jsize len)
2860
return pEnv->MakeLocalRef(new double[len]);
2864
SetPendingException(pEnv, x);
2869
internal static jboolean* GetBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* isCopy)
2871
bool[] b = (bool[])pEnv->UnwrapRef(array);
2872
jboolean* p = (jboolean*)(void*)JniMem.Alloc(b.Length * 1);
2873
for(int i = 0; i < b.Length; i++)
2875
p[i] = b[i] ? JNI_TRUE : JNI_FALSE;
2884
internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy)
2886
byte[] b = (byte[])pEnv->UnwrapRef(array);
2887
jbyte* p = (jbyte*)(void*)JniMem.Alloc(b.Length * 1);
2888
for(int i = 0; i < b.Length; i++)
2899
internal static jchar* GetCharArrayElements(JNIEnv* pEnv, jcharArray array, jboolean* isCopy)
2901
char[] b = (char[])pEnv->UnwrapRef(array);
2902
IntPtr buf = JniMem.Alloc(b.Length * 2);
2903
Marshal.Copy(b, 0, buf, b.Length);
2908
return (jchar*)(void*)buf;
2911
internal static jshort* GetShortArrayElements(JNIEnv* pEnv, jshortArray array, jboolean* isCopy)
2913
short[] b = (short[])pEnv->UnwrapRef(array);
2914
IntPtr buf = JniMem.Alloc(b.Length * 2);
2915
Marshal.Copy(b, 0, buf, b.Length);
2920
return (jshort*)(void*)buf;
2923
internal static jint* GetIntArrayElements(JNIEnv* pEnv, jintArray array, jboolean* isCopy)
2925
int[] b = (int[])pEnv->UnwrapRef(array);
2926
IntPtr buf = JniMem.Alloc(b.Length * 4);
2927
Marshal.Copy(b, 0, buf, b.Length);
2932
return (jint*)(void*)buf;
2935
internal static jlong* GetLongArrayElements(JNIEnv* pEnv, jlongArray array, jboolean* isCopy)
2937
long[] b = (long[])pEnv->UnwrapRef(array);
2938
IntPtr buf = JniMem.Alloc(b.Length * 8);
2939
Marshal.Copy(b, 0, buf, b.Length);
2944
return (jlong*)(void*)buf;
2947
internal static jfloat* GetFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jboolean* isCopy)
2949
float[] b = (float[])pEnv->UnwrapRef(array);
2950
IntPtr buf = JniMem.Alloc(b.Length * 4);
2951
Marshal.Copy(b, 0, buf, b.Length);
2956
return (jfloat*)(void*)buf;
2959
internal static jdouble* GetDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jboolean* isCopy)
2961
double[] b = (double[])pEnv->UnwrapRef(array);
2962
IntPtr buf = JniMem.Alloc(b.Length * 8);
2963
Marshal.Copy(b, 0, buf, b.Length);
2968
return (jdouble*)(void*)buf;
2971
internal static void ReleaseBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* elems, jint mode)
2973
if(mode == 0 || mode == JNI_COMMIT)
2975
bool[] b = (bool[])pEnv->UnwrapRef(array);
2976
for(int i = 0; i < b.Length; i++)
2978
b[i] = elems[i] != JNI_FALSE;
2981
if(mode == 0 || mode == JNI_ABORT)
2983
JniMem.Free((IntPtr)(void*)elems);
2987
internal static void ReleaseByteArrayElements(JNIEnv* pEnv, jbyteArray array, jbyte* elems, jint mode)
2989
if(mode == 0 || mode == JNI_COMMIT)
2991
byte[] b = (byte[])pEnv->UnwrapRef(array);
2992
for(int i = 0; i < b.Length; i++)
2994
b[i] = (byte)elems[i];
2997
if(mode == 0 || mode == JNI_ABORT)
2999
JniMem.Free((IntPtr)(void*)elems);
3003
internal static void ReleaseCharArrayElements(JNIEnv* pEnv, jcharArray array, jchar* elems, jint mode)
3005
if(mode == 0 || mode == JNI_COMMIT)
3007
char[] b = (char[])pEnv->UnwrapRef(array);
3008
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3010
if(mode == 0 || mode == JNI_ABORT)
3012
JniMem.Free((IntPtr)(void*)elems);
3016
internal static void ReleaseShortArrayElements(JNIEnv* pEnv, jshortArray array, jshort* elems, jint mode)
3018
if(mode == 0 || mode == JNI_COMMIT)
3020
short[] b = (short[])pEnv->UnwrapRef(array);
3021
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3023
if(mode == 0 || mode == JNI_ABORT)
3025
JniMem.Free((IntPtr)(void*)elems);
3029
internal static void ReleaseIntArrayElements(JNIEnv* pEnv, jintArray array, jint* elems, jint mode)
3031
if(mode == 0 || mode == JNI_COMMIT)
3033
int[] b = (int[])pEnv->UnwrapRef(array);
3034
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3036
if(mode == 0 || mode == JNI_ABORT)
3038
JniMem.Free((IntPtr)(void*)elems);
3042
internal static void ReleaseLongArrayElements(JNIEnv* pEnv, jlongArray array, jlong* elems, jint mode)
3044
if(mode == 0 || mode == JNI_COMMIT)
3046
long[] b = (long[])pEnv->UnwrapRef(array);
3047
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3049
if(mode == 0 || mode == JNI_ABORT)
3051
JniMem.Free((IntPtr)(void*)elems);
3055
internal static void ReleaseFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jfloat* elems, jint mode)
3057
if(mode == 0 || mode == JNI_COMMIT)
3059
float[] b = (float[])pEnv->UnwrapRef(array);
3060
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3062
if(mode == 0 || mode == JNI_ABORT)
3064
JniMem.Free((IntPtr)(void*)elems);
3068
internal static void ReleaseDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jdouble* elems, jint mode)
3070
if(mode == 0 || mode == JNI_COMMIT)
3072
double[] b = (double[])pEnv->UnwrapRef(array);
3073
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
3075
if(mode == 0 || mode == JNI_ABORT)
3077
JniMem.Free((IntPtr)(void*)elems);
3081
internal static void GetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3085
bool[] b = (bool[])pEnv->UnwrapRef(array);
3086
sbyte* p = (sbyte*)(void*)buf;
3087
for(int i = 0; i < len; i++)
3089
*p++ = b[start + i] ? JNI_TRUE : JNI_FALSE;
3092
catch(IndexOutOfRangeException)
3094
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3098
internal static void GetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3102
byte[] b = (byte[])pEnv->UnwrapRef(array);
3103
byte* p = (byte*)(void*)buf;
3104
for(int i = 0; i < len; i++)
3106
*p++ = b[start + i];
3109
catch(IndexOutOfRangeException)
3111
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3115
internal static void GetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3119
char[] b = (char[])pEnv->UnwrapRef(array);
3120
Marshal.Copy(b, start, buf, len);
3122
catch(ArgumentOutOfRangeException)
3124
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3128
internal static void GetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3132
short[] b = (short[])pEnv->UnwrapRef(array);
3133
Marshal.Copy(b, start, buf, len);
3135
catch(ArgumentOutOfRangeException)
3137
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3141
internal static void GetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3145
int[] b = (int[])pEnv->UnwrapRef(array);
3146
Marshal.Copy(b, start, buf, len);
3148
catch(ArgumentOutOfRangeException)
3150
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3154
internal static void GetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3158
long[] b = (long[])pEnv->UnwrapRef(array);
3159
Marshal.Copy(b, start, buf, len);
3161
catch(ArgumentOutOfRangeException)
3163
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3167
internal static void GetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3171
float[] b = (float[])pEnv->UnwrapRef(array);
3172
Marshal.Copy(b, start, buf, len);
3174
catch(ArgumentOutOfRangeException)
3176
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3180
internal static void GetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3184
double[] b = (double[])pEnv->UnwrapRef(array);
3185
Marshal.Copy(b, start, buf, len);
3187
catch(ArgumentOutOfRangeException)
3189
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3193
internal static void SetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3197
bool[] b = (bool[])pEnv->UnwrapRef(array);
3198
sbyte* p = (sbyte*)(void*)buf;
3199
for(int i = 0; i < len; i++)
3201
b[start + i] = *p++ != JNI_FALSE;
3204
catch(IndexOutOfRangeException)
3206
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3210
internal static void SetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3214
byte[] b = (byte[])pEnv->UnwrapRef(array);
3215
byte* p = (byte*)(void*)buf;
3216
for(int i = 0; i < len; i++)
3218
b[start + i] = *p++;
3221
catch(IndexOutOfRangeException)
3223
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3227
internal static void SetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3231
char[] b = (char[])pEnv->UnwrapRef(array);
3232
Marshal.Copy(buf, b, start, len);
3234
catch(ArgumentOutOfRangeException)
3236
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3240
internal static void SetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3244
short[] b = (short[])pEnv->UnwrapRef(array);
3245
Marshal.Copy(buf, b, start, len);
3247
catch(ArgumentOutOfRangeException)
3249
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3253
internal static void SetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3257
int[] b = (int[])pEnv->UnwrapRef(array);
3258
Marshal.Copy(buf, b, start, len);
3260
catch(ArgumentOutOfRangeException)
3262
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3266
internal static void SetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3270
long[] b = (long[])pEnv->UnwrapRef(array);
3271
Marshal.Copy(buf, b, start, len);
3273
catch(ArgumentOutOfRangeException)
3275
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3279
internal static void SetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3283
float[] b = (float[])pEnv->UnwrapRef(array);
3284
Marshal.Copy(buf, b, start, len);
3286
catch(ArgumentOutOfRangeException)
3288
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3292
internal static void SetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
3296
double[] b = (double[])pEnv->UnwrapRef(array);
3297
Marshal.Copy(buf, b, start, len);
3299
catch(ArgumentOutOfRangeException)
3301
SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
3305
[StructLayout(LayoutKind.Sequential)]
3306
unsafe internal struct JNINativeMethod
3309
public byte* signature;
3313
internal static int RegisterNatives(JNIEnv* pEnv, IntPtr clazz, JNINativeMethod* methods, int nMethods)
3317
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
3319
for(int i = 0; i < nMethods; i++)
3321
string methodName = StringFromUTF8(methods[i].name);
3322
string methodSig = StringFromUTF8(methods[i].signature);
3323
Tracer.Info(Tracer.Jni, "Registering native method: {0}.{1}{2}, fnPtr = 0x{3:X}", wrapper.Name, methodName, methodSig, ((IntPtr)methods[i].fnPtr).ToInt64());
3324
FieldInfo fi = null;
3325
// don't allow dotted names!
3326
if(methodSig.IndexOf('.') < 0)
3328
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
3329
fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + methodName + methodSig, BindingFlags.Static | BindingFlags.NonPublic);
3333
Tracer.Error(Tracer.Jni, "Failed to register native method: {0}.{1}{2}", wrapper.Name, methodName, methodSig);
3334
SetPendingException(pEnv, new java.lang.NoSuchMethodError(methodName));
3337
fi.SetValue(null, (IntPtr)methods[i].fnPtr);
3341
catch(RetargetableJavaException x)
3343
SetPendingException(pEnv, x.ToJava());
3348
SetPendingException(pEnv, x);
3353
internal static int UnregisterNatives(JNIEnv* pEnv, IntPtr clazz)
3357
TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
3359
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
3360
foreach(FieldInfo fi in wrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.NonPublic))
3362
string name = fi.Name;
3363
if(name.StartsWith(JNI.METHOD_PTR_FIELD_PREFIX))
3365
Tracer.Info(Tracer.Jni, "Unregistering native method: {0}.{1}", wrapper.Name, name.Substring(JNI.METHOD_PTR_FIELD_PREFIX.Length));
3366
fi.SetValue(null, IntPtr.Zero);
3371
catch(RetargetableJavaException x)
3373
SetPendingException(pEnv, x.ToJava());
3378
SetPendingException(pEnv, x);
3383
internal static int MonitorEnter(JNIEnv* pEnv, IntPtr obj)
3387
// on .NET 4.0 Monitor.Enter has been marked obsolete,
3388
// but in this case the alternative adds no value
3389
#pragma warning disable 618
3390
System.Threading.Monitor.Enter(pEnv->UnwrapRef(obj));
3391
#pragma warning restore 618
3396
SetPendingException(pEnv, x);
3401
internal static int MonitorExit(JNIEnv* pEnv, IntPtr obj)
3405
System.Threading.Monitor.Exit(pEnv->UnwrapRef(obj));
3410
SetPendingException(pEnv, x);
3415
internal static int GetJavaVM(JNIEnv* pEnv, JavaVM **ppJavaVM)
3417
*ppJavaVM = JavaVM.pJavaVM;
3421
internal static void GetStringRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
3423
string s = (string)pEnv->UnwrapRef(str);
3426
if(start < 0 || start > s.Length || s.Length - start < len)
3428
SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException());
3433
char* p = (char*)(void*)buf;
3434
// TODO isn't there a managed memcpy?
3435
for(int i = 0; i < len; i++)
3437
*p++ = s[start + i];
3444
SetPendingException(pEnv, new java.lang.NullPointerException());
3448
internal static void GetStringUTFRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
3450
string s = (string)pEnv->UnwrapRef(str);
3453
if(start < 0 || start > s.Length || s.Length - start < len)
3455
SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException());
3460
byte* p = (byte*)(void*)buf;
3461
for(int i = 0; i < len; i++)
3463
char ch = s[start + i];
3464
if((ch != 0) && (ch <= 0x7F))
3468
else if(ch <= 0x7FF)
3470
*p++ = (byte)((ch >> 6) | 0xC0);
3471
*p++ = (byte)((ch & 0x3F) | 0x80);
3475
*p++ = (byte)((ch >> 12) | 0xE0);
3476
*p++ = (byte)(((ch >> 6) & 0x3F) | 0x80);
3477
*p++ = (byte)((ch & 0x3F) | 0x80);
3485
SetPendingException(pEnv, new java.lang.NullPointerException());
3489
private void* PinObject(object obj)
3491
if(pinHandleInUseCount == pinHandleMaxCount)
3493
int newCount = pinHandleMaxCount + 32;
3494
GCHandle* pNew = (GCHandle*)JniMem.Alloc(sizeof(GCHandle) * newCount);
3495
for(int i = 0; i < pinHandleMaxCount; i++)
3497
pNew[i] = pinHandles[i];
3499
for(int i = pinHandleMaxCount; i < newCount; i++)
3501
pNew[i] = new GCHandle();
3503
JniMem.Free((IntPtr)pinHandles);
3505
pinHandleMaxCount = newCount;
3507
int index = pinHandleInUseCount++;
3508
if(!pinHandles[index].IsAllocated)
3510
pinHandles[index] = GCHandle.Alloc(null, GCHandleType.Pinned);
3512
pinHandles[index].Target = obj;
3513
return (void*)pinHandles[index].AddrOfPinnedObject();
3516
private void UnpinObject(object obj)
3518
for(int i = 0; i < pinHandleInUseCount; i++)
3520
if(pinHandles[i].Target == obj)
3522
pinHandles[i].Target = pinHandles[--pinHandleInUseCount].Target;
3523
pinHandles[pinHandleInUseCount].Target = null;
3529
internal static void* GetPrimitiveArrayCritical(JNIEnv* pEnv, jarray array, jboolean* isCopy)
3533
*isCopy = JNI_FALSE;
3535
return pEnv->PinObject(pEnv->UnwrapRef(array));
3538
internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, jarray array, void* carray, jint mode)
3540
pEnv->UnpinObject(pEnv->UnwrapRef(array));
3543
internal static jchar* GetStringCritical(JNIEnv* pEnv, jstring str, jboolean* isCopy)
3547
*isCopy = JNI_FALSE;
3549
return (jchar*)pEnv->PinObject(pEnv->UnwrapRef(str));
3552
internal static void ReleaseStringCritical(JNIEnv* pEnv, jstring str, jchar* cstring)
3554
pEnv->UnpinObject(pEnv->UnwrapRef(str));
3557
internal static jweak NewWeakGlobalRef(JNIEnv* pEnv, jobject obj)
3559
object o = pEnv->UnwrapRef(obj);
3564
lock(GlobalRefs.weakRefLock)
3566
for(int i = 0; i < GlobalRefs.weakRefs.Length; i++)
3568
if(!GlobalRefs.weakRefs[i].IsAllocated)
3570
GlobalRefs.weakRefs[i] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
3571
return (IntPtr)(- (i | (1 << 30)));
3574
int len = GlobalRefs.weakRefs.Length;
3575
GCHandle[] tmp = new GCHandle[len * 2];
3576
Array.Copy(GlobalRefs.weakRefs, 0, tmp, 0, len);
3577
tmp[len] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
3578
GlobalRefs.weakRefs = tmp;
3579
return (IntPtr)(- (len | (1 << 30)));
3583
internal static void DeleteWeakGlobalRef(JNIEnv* pEnv, jweak obj)
3585
int i = obj.ToInt32();
3590
lock(GlobalRefs.weakRefLock)
3592
GlobalRefs.weakRefs[i].Free();
3597
Debug.Assert(false, "local ref passed to DeleteWeakGlobalRef");
3601
internal static jboolean ExceptionCheck(JNIEnv* pEnv)
3603
ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
3604
return env.pendingException != null ? JNI_TRUE : JNI_FALSE;
3607
internal static jobject NewDirectByteBuffer(JNIEnv* pEnv, IntPtr address, jlong capacity)
3611
if(capacity < 0 || capacity > int.MaxValue)
3613
SetPendingException(pEnv, new java.lang.IllegalArgumentException("capacity"));
3616
return pEnv->MakeLocalRef(JVM.NewDirectByteBuffer(address.ToInt64(), (int)capacity));
3620
SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
3625
internal static IntPtr GetDirectBufferAddress(JNIEnv* pEnv, jobject buf)
3629
return (IntPtr)((sun.nio.ch.DirectBuffer)pEnv->UnwrapRef(buf)).address();
3633
SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
3638
internal static jlong GetDirectBufferCapacity(JNIEnv* pEnv, jobject buf)
3642
return (jlong)(long)((java.nio.Buffer)pEnv->UnwrapRef(buf)).capacity();
3646
SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
3651
internal static int GetObjectRefType(JNIEnv* pEnv, jobject obj)
3653
int i = obj.ToInt32();
3656
return JNILocalRefType;
3659
if((i & (1 << 30)) != 0)
3661
return JNIWeakGlobalRefType;
3665
return JNIGlobalRefType;
3669
internal IntPtr MakeLocalRef(object obj)
3671
return GetManagedJNIEnv().MakeLocalRef(obj);
3674
internal object UnwrapRef(IntPtr o)
3676
int i = o.ToInt32();
3679
return GetManagedJNIEnv().UnwrapLocalRef(i);
3683
return GlobalRefs.Unwrap(i);
3688
internal static object UnwrapRef(ManagedJNIEnv env, IntPtr o)
3690
int i = o.ToInt32();
3693
return env.UnwrapLocalRef(i);
3697
return GlobalRefs.Unwrap(i);
3705
internal static IntPtr Alloc(int cb)
3707
return Marshal.AllocHGlobal(cb);
3710
internal static void Free(IntPtr p)
3712
Marshal.FreeHGlobal(p);
3716
static class TlsHack
3719
internal static JNIEnv.ManagedJNIEnv ManagedJNIEnv;