~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/runtime/JniInterface.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2002-2009 Jeroen Frijters
 
3
 
 
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.
 
7
 
 
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:
 
11
 
 
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.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
using System;
 
25
using System.Collections.Generic;
 
26
using System.Diagnostics;
 
27
using System.Text;
 
28
using System.Reflection;
 
29
using System.Runtime.InteropServices;
 
30
using IKVM.Internal;
 
31
 
 
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;
 
59
 
 
60
namespace IKVM.Runtime
 
61
{
 
62
        [StructLayout(LayoutKind.Sequential)]
 
63
        unsafe struct JavaVMOption
 
64
        {
 
65
                internal byte* optionString;
 
66
                internal void* extraInfo;
 
67
        }
 
68
 
 
69
        [StructLayout(LayoutKind.Sequential)]
 
70
        unsafe struct JavaVMInitArgs
 
71
        {
 
72
                internal jint version;
 
73
                internal jint nOptions;
 
74
                internal JavaVMOption* options;
 
75
                internal jboolean ignoreUnrecognized;
 
76
        }
 
77
 
 
78
        public unsafe sealed class JNI
 
79
        {
 
80
                internal static volatile bool jvmCreated;
 
81
                internal static volatile bool jvmDestroyed;
 
82
                internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr>";
 
83
 
 
84
                internal static bool IsSupportedJniVersion(jint version)
 
85
                {
 
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;
 
87
                }
 
88
 
 
89
                public static int CreateJavaVM(void* ppvm, void* ppenv, void* args)
 
90
                {
 
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)
 
94
                        {
 
95
                                return JNIEnv.JNI_EVERSION;
 
96
                        }
 
97
                        if(jvmCreated)
 
98
                        {
 
99
                                return JNIEnv.JNI_ERR;
 
100
                        }
 
101
                        System.Collections.Hashtable props = new System.Collections.Hashtable();
 
102
                        for(int i = 0; i < pInitArgs->nOptions; i++)
 
103
                        {
 
104
                                string option = JNIEnv.StringFromOEM(pInitArgs->options[i].optionString);
 
105
                                if(option.StartsWith("-D"))
 
106
                                {
 
107
                                        int idx = option.IndexOf('=', 2);
 
108
                                        props[option.Substring(2, idx - 2)] = option.Substring(idx + 1);
 
109
                                }
 
110
                                else if(option.StartsWith("-verbose"))
 
111
                                {
 
112
                                        // ignore
 
113
                                }
 
114
                                else if(option == "vfprintf" || option == "exit" || option == "abort")
 
115
                                {
 
116
                                        // not supported
 
117
                                }
 
118
                                else if(pInitArgs->ignoreUnrecognized == JNIEnv.JNI_FALSE)
 
119
                                {
 
120
                                        return JNIEnv.JNI_ERR;
 
121
                                }
 
122
                        }
 
123
 
 
124
                        ikvm.runtime.Startup.setProperties(props);
 
125
 
 
126
                        // initialize the class library
 
127
                        java.lang.Thread.currentThread();
 
128
 
 
129
                        *((void**)ppvm) = JavaVM.pJavaVM;
 
130
                        return JavaVM.AttachCurrentThread(JavaVM.pJavaVM, (void**)ppenv, null);
 
131
                }
 
132
 
 
133
                public static int GetDefaultJavaVMInitArgs(void* vm_args)
 
134
                {
 
135
                        // This is only used for JDK 1.1 JavaVMInitArgs, and we don't support those.
 
136
                        return JNIEnv.JNI_ERR;
 
137
                }
 
138
 
 
139
                public static int GetCreatedJavaVMs(void* ppvmBuf, int bufLen, int* nVMs)
 
140
                {
 
141
                        if(jvmCreated)
 
142
                        {
 
143
                                if(bufLen >= 1)
 
144
                                {
 
145
                                        *((void**)ppvmBuf) = JavaVM.pJavaVM;
 
146
                                }
 
147
                                if(nVMs != null)
 
148
                                {
 
149
                                        *nVMs = 1;
 
150
                                }
 
151
                        }
 
152
                        else if(nVMs != null)
 
153
                        {
 
154
                                *nVMs = 0;
 
155
                        }
 
156
                        return JNIEnv.JNI_OK;
 
157
                }
 
158
 
 
159
                public struct Frame
 
160
                {
 
161
                        private JNIEnv.ManagedJNIEnv env;
 
162
                        private JNIEnv.ManagedJNIEnv.FrameState prevFrameState;
 
163
 
 
164
                        internal ClassLoaderWrapper Enter(ClassLoaderWrapper loader)
 
165
                        {
 
166
                                Enter((ikvm.@internal.CallerID)null);
 
167
                                ClassLoaderWrapper prev = env.classLoader;
 
168
                                env.classLoader = loader;
 
169
                                return prev;
 
170
                        }
 
171
 
 
172
                        internal void Leave(ClassLoaderWrapper prev)
 
173
                        {
 
174
                                env.classLoader = prev;
 
175
                                Leave();
 
176
                        }
 
177
 
 
178
                        public IntPtr Enter(ikvm.@internal.CallerID callerID)
 
179
                        {
 
180
                                env = TlsHack.ManagedJNIEnv;
 
181
                                if(env == null)
 
182
                                {
 
183
                                        env = JNIEnv.CreateJNIEnv()->GetManagedJNIEnv();
 
184
                                }
 
185
                                prevFrameState = env.Enter(callerID);
 
186
                                return (IntPtr)(void*)env.pJNIEnv;
 
187
                        }
 
188
 
 
189
                        public void Leave()
 
190
                        {
 
191
                                Exception x = env.Leave(prevFrameState);
 
192
                                if(x != null)
 
193
                                {
 
194
                                        throw x;
 
195
                                }
 
196
                        }
 
197
 
 
198
                        public static IntPtr GetFuncPtr(ikvm.@internal.CallerID callerID, string clazz, string name, string sig)
 
199
                        {
 
200
                                ClassLoaderWrapper loader = ClassLoaderWrapper.FromCallerID(callerID);
 
201
                                int sp = 0;
 
202
                                for(int i = 1; sig[i] != ')'; i++)
 
203
                                {
 
204
                                        switch(sig[i])
 
205
                                        {
 
206
                                                case '[':
 
207
                                                        sp += IntPtr.Size;
 
208
                                                        while(sig[++i] == '[');
 
209
                                                        if(sig[i] == 'L')
 
210
                                                        {
 
211
                                                                while(sig[++i] != ';');
 
212
                                                        }
 
213
                                                        break;
 
214
                                                case 'L':
 
215
                                                        sp += IntPtr.Size;
 
216
                                                        while(sig[++i] != ';');
 
217
                                                        break;
 
218
                                                case 'J':
 
219
                                                case 'D':
 
220
                                                        sp += 8;
 
221
                                                        break;
 
222
                                                case 'F':
 
223
                                                case 'I':
 
224
                                                case 'C':
 
225
                                                case 'Z':
 
226
                                                case 'S':
 
227
                                                case 'B':
 
228
                                                        sp += 4;
 
229
                                                        break;
 
230
                                                default:
 
231
                                                        Debug.Assert(false);
 
232
                                                        break;
 
233
                                        }
 
234
                                }
 
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)
 
243
                                {
 
244
                                        foreach(IntPtr p in loader.GetNativeLibraries())
 
245
                                        {
 
246
                                                IntPtr pfunc = NativeLibrary.GetProcAddress(p, shortMethodName, sp + 2 * IntPtr.Size);
 
247
                                                if(pfunc != IntPtr.Zero)
 
248
                                                {
 
249
                                                        Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (short)", clazz, name, sig, p.ToInt64());
 
250
                                                        return pfunc;
 
251
                                                }
 
252
                                                pfunc = NativeLibrary.GetProcAddress(p, longMethodName, sp + 2 * IntPtr.Size);
 
253
                                                if(pfunc != IntPtr.Zero)
 
254
                                                {
 
255
                                                        Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (long)", clazz, name, sig, p.ToInt64());
 
256
                                                        return pfunc;
 
257
                                                }
 
258
                                        }
 
259
                                }
 
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);
 
263
                        }
 
264
 
 
265
                        private static string JniMangle(string name)
 
266
                        {
 
267
                                StringBuilder sb = new StringBuilder();
 
268
                                foreach(char c in name)
 
269
                                {
 
270
                                        if(c == '/')
 
271
                                        {
 
272
                                                sb.Append('_');
 
273
                                        }
 
274
                                        else if(c == '_')
 
275
                                        {
 
276
                                                sb.Append("_1");
 
277
                                        }
 
278
                                        else if(c == ';')
 
279
                                        {
 
280
                                                sb.Append("_2");
 
281
                                        }
 
282
                                        else if(c == '[')
 
283
                                        {
 
284
                                                sb.Append("_3");
 
285
                                        }
 
286
                                        else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
 
287
                                        {
 
288
                                                sb.Append(c);
 
289
                                        }
 
290
                                        else
 
291
                                        {
 
292
                                                sb.Append(String.Format("_0{0:x4}", (int)c));
 
293
                                        }
 
294
                                }
 
295
                                return sb.ToString();
 
296
                        }
 
297
 
 
298
                        public IntPtr MakeLocalRef(object obj)
 
299
                        {
 
300
                                return env.MakeLocalRef(obj);
 
301
                        }
 
302
 
 
303
                        // NOTE this method has the wrong name, it should unwrap *any* jobject reference type (local and global)
 
304
                        public object UnwrapLocalRef(IntPtr p)
 
305
                        {
 
306
                                return JNIEnv.UnwrapRef(env, p);
 
307
                        }
 
308
                }
 
309
        }
 
310
 
 
311
        abstract unsafe class NativeLibrary
 
312
        {
 
313
                private NativeLibrary() { }
 
314
                private static readonly NativeLibrary impl;
 
315
 
 
316
                static NativeLibrary()
 
317
                {
 
318
                        try
 
319
                        {
 
320
                                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
 
321
                                {
 
322
                                        if (IntPtr.Size == 4)
 
323
                                        {
 
324
                                                impl = new Win32_x86();
 
325
                                        }
 
326
                                        else
 
327
                                        {
 
328
                                                impl = new Win32_x64();
 
329
                                        }
 
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);
 
333
                                }
 
334
                                else
 
335
                                {
 
336
                                        impl = new Classic();
 
337
                                }
 
338
                        }
 
339
                        catch (DllNotFoundException)
 
340
                        {
 
341
                                impl = new Classic();
 
342
                        }
 
343
                        catch (BadImageFormatException)
 
344
                        {
 
345
                                impl = new Classic();
 
346
                        }
 
347
                }
 
348
 
 
349
                private sealed class Win32_x86 : NativeLibrary
 
350
                {
 
351
                        private const string library = "ikvm-native-win32-x86";
 
352
 
 
353
                        [DllImport(library)]
 
354
                        private static extern IntPtr ikvm_LoadLibrary(string filename);
 
355
                        [DllImport(library)]
 
356
                        private static extern void ikvm_FreeLibrary(IntPtr handle);
 
357
                        [DllImport(library)]
 
358
                        private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
 
359
                        [DllImport(library)]
 
360
                        private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
 
361
                        [DllImport(library)]
 
362
                        private static extern void** ikvm_GetJNIEnvVTable();
 
363
                        [DllImport(library)]
 
364
                        private static extern void* ikvm_MarshalDelegate(Delegate d);
 
365
 
 
366
                        protected override IntPtr _LoadLibrary(string filename)
 
367
                        {
 
368
                                return ikvm_LoadLibrary(filename);
 
369
                        }
 
370
 
 
371
                        protected override void _FreeLibrary(IntPtr handle)
 
372
                        {
 
373
                                ikvm_FreeLibrary(handle);
 
374
                        }
 
375
 
 
376
                        protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
 
377
                        {
 
378
                                return ikvm_GetProcAddress(handle, name, argc);
 
379
                        }
 
380
 
 
381
                        protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
 
382
                        {
 
383
                                return ikvm_CallOnLoad(method, jvm, reserved);
 
384
                        }
 
385
 
 
386
                        protected override void** _GetJNIEnvVTable()
 
387
                        {
 
388
                                return ikvm_GetJNIEnvVTable();
 
389
                        }
 
390
 
 
391
                        protected override void* _MarshalDelegate(Delegate d)
 
392
                        {
 
393
                                return ikvm_MarshalDelegate(d);
 
394
                        }
 
395
                }
 
396
 
 
397
                private sealed class Win32_x64 : NativeLibrary
 
398
                {
 
399
                        private const string library = "ikvm-native-win32-x64";
 
400
 
 
401
                        [DllImport(library)]
 
402
                        private static extern IntPtr ikvm_LoadLibrary(string filename);
 
403
                        [DllImport(library)]
 
404
                        private static extern void ikvm_FreeLibrary(IntPtr handle);
 
405
                        [DllImport(library)]
 
406
                        private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
 
407
                        [DllImport(library)]
 
408
                        private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
 
409
                        [DllImport(library)]
 
410
                        private static extern void** ikvm_GetJNIEnvVTable();
 
411
                        [DllImport(library)]
 
412
                        private static extern void* ikvm_MarshalDelegate(Delegate d);
 
413
 
 
414
                        protected override IntPtr _LoadLibrary(string filename)
 
415
                        {
 
416
                                return ikvm_LoadLibrary(filename);
 
417
                        }
 
418
 
 
419
                        protected override void _FreeLibrary(IntPtr handle)
 
420
                        {
 
421
                                ikvm_FreeLibrary(handle);
 
422
                        }
 
423
 
 
424
                        protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
 
425
                        {
 
426
                                return ikvm_GetProcAddress(handle, name, argc);
 
427
                        }
 
428
 
 
429
                        protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
 
430
                        {
 
431
                                return ikvm_CallOnLoad(method, jvm, reserved);
 
432
                        }
 
433
 
 
434
                        protected override void** _GetJNIEnvVTable()
 
435
                        {
 
436
                                return ikvm_GetJNIEnvVTable();
 
437
                        }
 
438
 
 
439
                        protected override void* _MarshalDelegate(Delegate d)
 
440
                        {
 
441
                                return ikvm_MarshalDelegate(d);
 
442
                        }
 
443
                }
 
444
 
 
445
                private sealed class Classic : NativeLibrary
 
446
                {
 
447
                        private const string library = "ikvm-native";
 
448
 
 
449
                        [DllImport(library)]
 
450
                        private static extern IntPtr ikvm_LoadLibrary(string filename);
 
451
                        [DllImport(library)]
 
452
                        private static extern void ikvm_FreeLibrary(IntPtr handle);
 
453
                        [DllImport(library)]
 
454
                        private static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
 
455
                        [DllImport(library)]
 
456
                        private static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
 
457
                        [DllImport(library)]
 
458
                        private static extern void** ikvm_GetJNIEnvVTable();
 
459
                        [DllImport(library)]
 
460
                        private static extern void* ikvm_MarshalDelegate(Delegate d);
 
461
 
 
462
                        protected override IntPtr _LoadLibrary(string filename)
 
463
                        {
 
464
                                return ikvm_LoadLibrary(filename);
 
465
                        }
 
466
 
 
467
                        protected override void _FreeLibrary(IntPtr handle)
 
468
                        {
 
469
                                ikvm_FreeLibrary(handle);
 
470
                        }
 
471
 
 
472
                        protected override IntPtr _GetProcAddress(IntPtr handle, string name, int argc)
 
473
                        {
 
474
                                return ikvm_GetProcAddress(handle, name, argc);
 
475
                        }
 
476
 
 
477
                        protected override int _CallOnLoad(IntPtr method, void* jvm, void* reserved)
 
478
                        {
 
479
                                return ikvm_CallOnLoad(method, jvm, reserved);
 
480
                        }
 
481
 
 
482
                        protected override void** _GetJNIEnvVTable()
 
483
                        {
 
484
                                return ikvm_GetJNIEnvVTable();
 
485
                        }
 
486
 
 
487
                        protected override void* _MarshalDelegate(Delegate d)
 
488
                        {
 
489
                                return ikvm_MarshalDelegate(d);
 
490
                        }
 
491
                }
 
492
 
 
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);
 
499
 
 
500
                internal static IntPtr LoadLibrary(string filename)
 
501
                {
 
502
                        return impl._LoadLibrary(filename);
 
503
                }
 
504
 
 
505
                internal static void FreeLibrary(IntPtr handle)
 
506
                {
 
507
                        impl._FreeLibrary(handle);
 
508
                }
 
509
 
 
510
                internal static IntPtr GetProcAddress(IntPtr handle, string name, int argc)
 
511
                {
 
512
                        return impl._GetProcAddress(handle, name, argc);
 
513
                }
 
514
 
 
515
                internal static int CallOnLoad(IntPtr method, void* jvm, void* reserved)
 
516
                {
 
517
                        return impl._CallOnLoad(method, jvm, reserved);
 
518
                }
 
519
 
 
520
                internal static void** GetJNIEnvVTable()
 
521
                {
 
522
                        return impl._GetJNIEnvVTable();
 
523
                }
 
524
 
 
525
                internal static void* MarshalDelegate(Delegate d)
 
526
                {
 
527
                        return impl._MarshalDelegate(d);
 
528
                }
 
529
        }
 
530
 
 
531
        sealed class JniHelper
 
532
        {
 
533
                private static List<IntPtr> nativeLibraries = new List<IntPtr>();
 
534
                internal static readonly object JniLock = new object();
 
535
 
 
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)
 
538
                {
 
539
                        return LoadLibrary(filename, (ClassLoaderWrapper)loader);
 
540
                }
 
541
 
 
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)
 
544
                {
 
545
                        UnloadLibrary(handle, (ClassLoaderWrapper)loader);
 
546
                }
 
547
 
 
548
                private unsafe static long LoadLibrary(string filename, ClassLoaderWrapper loader)
 
549
                {
 
550
                        Tracer.Info(Tracer.Jni, "loadLibrary: {0}, class loader: {1}", filename, loader);
 
551
                        lock(JniLock)
 
552
                        {
 
553
                                IntPtr p = NativeLibrary.LoadLibrary(filename);
 
554
                                if(p == IntPtr.Zero)
 
555
                                {
 
556
                                        Tracer.Info(Tracer.Jni, "Library not found: {0}", filename);
 
557
                                        return 0;
 
558
                                }
 
559
                                try
 
560
                                {
 
561
                                        foreach(IntPtr tmp in loader.GetNativeLibraries())
 
562
                                        {
 
563
                                                if(tmp == p)
 
564
                                                {
 
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);
 
569
                                                        return p.ToInt64();
 
570
                                                }
 
571
                                        }
 
572
                                        if(nativeLibraries.Contains(p))
 
573
                                        {
 
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);
 
577
                                        }
 
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)
 
581
                                        {
 
582
                                                Tracer.Info(Tracer.Jni, "Calling JNI_OnLoad on: {0}", filename);
 
583
                                                JNI.Frame f = new JNI.Frame();
 
584
                                                int version;
 
585
                                                ClassLoaderWrapper prevLoader = f.Enter(loader);
 
586
                                                try
 
587
                                                {
 
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);
 
591
                                                }
 
592
                                                finally
 
593
                                                {
 
594
                                                        f.Leave(prevLoader);
 
595
                                                }
 
596
                                                if(!JNI.IsSupportedJniVersion(version))
 
597
                                                {
 
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);
 
601
                                                }
 
602
                                        }
 
603
                                        nativeLibraries.Add(p);
 
604
                                        loader.RegisterNativeLibrary(p);
 
605
                                        return p.ToInt64();
 
606
                                }
 
607
                                catch
 
608
                                {
 
609
                                        NativeLibrary.FreeLibrary(p);
 
610
                                        throw;
 
611
                                }
 
612
                        }
 
613
                }
 
614
 
 
615
                private unsafe static void UnloadLibrary(long handle, ClassLoaderWrapper loader)
 
616
                {
 
617
                        lock (JniLock)
 
618
                        {
 
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)
 
623
                                {
 
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);
 
627
                                        try
 
628
                                        {
 
629
                                                // TODO on Whidbey we should be able to use Marshal.GetDelegateForFunctionPointer to call OnLoad
 
630
                                                NativeLibrary.CallOnLoad(onunload, JavaVM.pJavaVM, null);
 
631
                                        }
 
632
                                        finally
 
633
                                        {
 
634
                                                f.Leave(prevLoader);
 
635
                                        }
 
636
                                }
 
637
                                nativeLibraries.Remove(p);
 
638
                                loader.UnregisterNativeLibrary(p);
 
639
                                NativeLibrary.FreeLibrary((IntPtr)handle);
 
640
                        }
 
641
                }
 
642
        }
 
643
 
 
644
        static class GlobalRefs
 
645
        {
 
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];
 
649
 
 
650
                internal static object Unwrap(int i)
 
651
                {
 
652
                        i = -i;
 
653
                        if ((i & (1 << 30)) != 0)
 
654
                        {
 
655
                                lock (GlobalRefs.weakRefLock)
 
656
                                {
 
657
                                        return GlobalRefs.weakRefs[i - (1 << 30)].Target;
 
658
                                }
 
659
                        }
 
660
                        else
 
661
                        {
 
662
                                lock (GlobalRefs.globalRefs)
 
663
                                {
 
664
                                        return GlobalRefs.globalRefs[i - 1];
 
665
                                }
 
666
                        }
 
667
                }
 
668
        }
 
669
 
 
670
        unsafe class VtableBuilder
 
671
        {
 
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);
 
752
 
 
753
                internal static void* vtable;
 
754
 
 
755
                static VtableBuilder()
 
756
                {
 
757
                        JNI.jvmCreated = true;
 
758
                        // JNIEnv
 
759
                        void** pmcpp = NativeLibrary.GetJNIEnvVTable();
 
760
                        void** p = (void**)JniMem.Alloc(IntPtr.Size * vtableDelegates.Length);
 
761
                        for(int i = 0; i < vtableDelegates.Length; i++)
 
762
                        {
 
763
                                if(vtableDelegates[i] != null)
 
764
                                {
 
765
                                        // TODO on Whidbey we can use Marshal.GetFunctionPointerForDelegate
 
766
                                        p[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]);
 
767
                                }
 
768
                                else
 
769
                                {
 
770
                                        p[i] = pmcpp[i];
 
771
                                }
 
772
                        }
 
773
                        vtable = p;
 
774
                }
 
775
 
 
776
                static Delegate[] vtableDelegates =
 
777
                {
 
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();
 
782
 
 
783
                        new pf_int(JNIEnv.GetVersion), //virtual jint JNICALL GetVersion();
 
784
 
 
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);
 
787
 
 
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);
 
791
 
 
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);
 
794
 
 
795
                        new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID, jboolean isStatic);
 
796
 
 
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);
 
803
 
 
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);
 
806
 
 
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);
 
811
 
 
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);
 
814
 
 
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);
 
819
 
 
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);
 
822
 
 
823
                        new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetMethodID), //virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig);
 
824
 
 
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);
 
828
 
 
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);
 
832
 
 
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);
 
836
 
 
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);
 
840
 
 
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);
 
844
 
 
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);
 
848
 
 
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);
 
852
 
 
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);
 
856
 
 
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);
 
860
 
 
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);
 
864
 
 
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);
 
868
 
 
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);
 
872
 
 
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);
 
876
 
 
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);
 
880
 
 
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);
 
884
 
 
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);
 
888
 
 
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);
 
892
 
 
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);
 
896
 
 
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);
 
900
 
 
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);
 
904
 
 
905
                        new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetFieldID), //virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig);
 
906
 
 
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);
 
916
 
 
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);
 
926
 
 
927
                        new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticMethodID), //virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig);
 
928
 
 
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);
 
932
 
 
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);
 
936
 
 
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);
 
940
 
 
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);
 
944
 
 
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);
 
948
 
 
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);
 
952
 
 
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);
 
956
 
 
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);
 
960
 
 
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);
 
964
 
 
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);
 
968
 
 
969
                        new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticFieldID), //virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig);
 
970
 
 
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);
 
980
 
 
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);
 
990
 
 
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);
 
995
 
 
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);
 
1000
 
 
1001
                        new pf_int_IntPtr(JNIEnv.GetArrayLength), //virtual jsize JNICALL GetArrayLength(jarray array);
 
1002
 
 
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);
 
1006
 
 
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);
 
1015
 
 
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);
 
1024
 
 
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);
 
1033
 
 
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);
 
1042
 
 
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);
 
1051
 
 
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);
 
1054
 
 
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);
 
1057
 
 
1058
                        new pf_int_ppJavaVM(JNIEnv.GetJavaVM), //virtual jint JNICALL GetJavaVM(JavaVM **vm);
 
1059
 
 
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);
 
1062
 
 
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);
 
1065
 
 
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);
 
1068
 
 
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);
 
1071
 
 
1072
                        new pf_sbyte(JNIEnv.ExceptionCheck), //virtual jboolean JNICALL ExceptionCheck();
 
1073
 
 
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);
 
1077
 
 
1078
                        new pf_int_IntPtr(JNIEnv.GetObjectRefType) // virtual jobjectRefType GetObjectRefType(jobject obj);
 
1079
                };
 
1080
        }
 
1081
 
 
1082
        [StructLayout(LayoutKind.Sequential)]
 
1083
        unsafe struct JavaVMAttachArgs
 
1084
        {
 
1085
                internal jint version;
 
1086
                internal byte* name;
 
1087
                internal jobject group;
 
1088
        }
 
1089
 
 
1090
        [StructLayout(LayoutKind.Sequential)]
 
1091
        unsafe struct JavaVM
 
1092
        {
 
1093
                internal static JavaVM* pJavaVM;
 
1094
                void** vtable;
 
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);
 
1099
 
 
1100
                static Delegate[] vtableDelegates =
 
1101
                {
 
1102
                        null,
 
1103
                        null,
 
1104
                        null,
 
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)
 
1110
                };
 
1111
 
 
1112
                static JavaVM()
 
1113
                {
 
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++)
 
1118
                        {
 
1119
                                pJavaVM->vtable[i] = NativeLibrary.MarshalDelegate(vtableDelegates[i]);
 
1120
                        }
 
1121
                }
 
1122
 
 
1123
                internal static jint DestroyJavaVM(JavaVM* pJVM)
 
1124
                {
 
1125
                        if(JNI.jvmDestroyed)
 
1126
                        {
 
1127
                                return JNIEnv.JNI_ERR;
 
1128
                        }
 
1129
                        JNI.jvmDestroyed = true;
 
1130
                        IKVM.NativeCode.java.lang.Thread.WaitUntilLastJniThread();
 
1131
                        return JNIEnv.JNI_OK;
 
1132
                }
 
1133
 
 
1134
                internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args)
 
1135
                {
 
1136
                        return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, false);
 
1137
                }
 
1138
 
 
1139
                internal static jint AttachCurrentThreadImpl(JavaVM* pJVM, void** penv, JavaVMAttachArgs* pAttachArgs, bool asDaemon)
 
1140
                {
 
1141
                        if(pAttachArgs != null)
 
1142
                        {
 
1143
                                if(!JNI.IsSupportedJniVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1)
 
1144
                                {
 
1145
                                        *penv = null;
 
1146
                                        return JNIEnv.JNI_EVERSION;
 
1147
                                }
 
1148
                        }
 
1149
                        JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv;
 
1150
                        if(env != null)
 
1151
                        {
 
1152
                                *penv = env.pJNIEnv;
 
1153
                                return JNIEnv.JNI_OK;
 
1154
                        }
 
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)
 
1160
                        {
 
1161
                                if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
 
1162
                                {
 
1163
                                        try
 
1164
                                        {
 
1165
                                                System.Threading.Thread.CurrentThread.Name = JNIEnv.StringFromUTF8(pAttachArgs->name);
 
1166
                                        }
 
1167
                                        catch(InvalidOperationException)
 
1168
                                        {
 
1169
                                                // someone beat us to it...
 
1170
                                        }
 
1171
                                }
 
1172
                                object threadGroup = GlobalRefs.Unwrap(pAttachArgs->group.ToInt32());
 
1173
                                if(threadGroup != null)
 
1174
                                {
 
1175
                                        IKVM.NativeCode.java.lang.Thread.AttachThreadFromJni(threadGroup);
 
1176
                                }
 
1177
                        }
 
1178
                        *penv = JNIEnv.CreateJNIEnv();
 
1179
                        return JNIEnv.JNI_OK;
 
1180
                }
 
1181
 
 
1182
                internal static jint DetachCurrentThread(JavaVM* pJVM)
 
1183
                {
 
1184
                        if(TlsHack.ManagedJNIEnv == null)
 
1185
                        {
 
1186
                                // the JDK allows detaching from an already detached thread
 
1187
                                return JNIEnv.JNI_OK;
 
1188
                        }
 
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;
 
1193
                }
 
1194
 
 
1195
                internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version)
 
1196
                {
 
1197
                        if(JNI.IsSupportedJniVersion(version))
 
1198
                        {
 
1199
                                JNIEnv.ManagedJNIEnv env = TlsHack.ManagedJNIEnv;
 
1200
                                if(env != null)
 
1201
                                {
 
1202
                                        *penv = env.pJNIEnv;
 
1203
                                        return JNIEnv.JNI_OK;
 
1204
                                }
 
1205
                                *penv = null;
 
1206
                                return JNIEnv.JNI_EDETACHED;
 
1207
                        }
 
1208
                        *penv = null;
 
1209
                        return JNIEnv.JNI_EVERSION;
 
1210
                }
 
1211
 
 
1212
                internal static jint AttachCurrentThreadAsDaemon(JavaVM* pJVM, void **penv, void *args)
 
1213
                {
 
1214
                        return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, true);
 
1215
                }
 
1216
        }
 
1217
 
 
1218
        [StructLayout(LayoutKind.Sequential)]
 
1219
        unsafe struct JNIEnv
 
1220
        {
 
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;
 
1242
 
 
1243
                static JNIEnv()
 
1244
                {
 
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;
 
1247
                }
 
1248
 
 
1249
                internal ManagedJNIEnv GetManagedJNIEnv()
 
1250
                {
 
1251
                        return (ManagedJNIEnv)managedJNIEnv.Target;
 
1252
                }
 
1253
 
 
1254
                internal sealed class ManagedJNIEnv
 
1255
                {
 
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;
 
1271
 
 
1272
                        internal ManagedJNIEnv()
 
1273
                        {
 
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)
 
1279
                                active[0] = "";
 
1280
                                localRefIndex = 1;
 
1281
                        }
 
1282
 
 
1283
                        ~ManagedJNIEnv()
 
1284
                        {
 
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
 
1287
                                // we run).
 
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)
 
1292
                                {
 
1293
                                        if(pJNIEnv->managedJNIEnv.IsAllocated)
 
1294
                                        {
 
1295
                                                pJNIEnv->managedJNIEnv.Free();
 
1296
                                        }
 
1297
                                        for(int i = 0; i < pJNIEnv->pinHandleMaxCount; i++)
 
1298
                                        {
 
1299
                                                if(pJNIEnv->pinHandles[i].IsAllocated)
 
1300
                                                {
 
1301
                                                        pJNIEnv->pinHandles[i].Free();
 
1302
                                                }
 
1303
                                        }
 
1304
                                        JniMem.Free((IntPtr)(void*)pJNIEnv);
 
1305
                                }
 
1306
                        }
 
1307
 
 
1308
                        internal struct FrameState
 
1309
                        {
 
1310
                                internal readonly ikvm.@internal.CallerID callerID;
 
1311
                                internal readonly int localRefSlot;
 
1312
                                internal readonly int localRefIndex;
 
1313
 
 
1314
                                internal FrameState(ikvm.@internal.CallerID callerID, int localRefSlot, int localRefIndex)
 
1315
                                {
 
1316
                                        this.callerID = callerID;
 
1317
                                        this.localRefSlot = localRefSlot;
 
1318
                                        this.localRefIndex = localRefIndex;
 
1319
                                }
 
1320
                        }
 
1321
 
 
1322
                        internal FrameState Enter(ikvm.@internal.CallerID newCallerID)
 
1323
                        {
 
1324
                                FrameState prev = new FrameState(callerID, localRefSlot, localRefIndex);
 
1325
                                this.callerID = newCallerID;
 
1326
                                localRefSlot++;
 
1327
                                if (localRefSlot >= localRefs.Length)
 
1328
                                {
 
1329
                                        object[][] tmp = new object[localRefs.Length * 2][];
 
1330
                                        Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
 
1331
                                        localRefs = tmp;
 
1332
                                }
 
1333
                                localRefIndex = 0;
 
1334
                                active = localRefs[localRefSlot];
 
1335
                                if (active == null)
 
1336
                                {
 
1337
                                        active = localRefs[localRefSlot] = new object[LOCAL_REF_INITIAL_BUCKET_SIZE];
 
1338
                                }
 
1339
                                return prev;
 
1340
                        }
 
1341
 
 
1342
                        internal Exception Leave(FrameState prev)
 
1343
                        {
 
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++)
 
1346
                                {
 
1347
                                        active[i] = null;
 
1348
                                }
 
1349
                                while (--localRefSlot != prev.localRefSlot)
 
1350
                                {
 
1351
                                        if (localRefs[localRefSlot] != null)
 
1352
                                        {
 
1353
                                                if (localRefs[localRefSlot].Length == LOCAL_REF_MAX_BUCKET_SIZE)
 
1354
                                                {
 
1355
                                                        // if the bucket is totally allocated, we're assuming a leaky method so we throw the bucket away
 
1356
                                                        localRefs[localRefSlot] = null;
 
1357
                                                }
 
1358
                                                else
 
1359
                                                {
 
1360
                                                        Array.Clear(localRefs[localRefSlot], 0, localRefs[localRefSlot].Length);
 
1361
                                                }
 
1362
                                        }
 
1363
                                }
 
1364
                                active = localRefs[localRefSlot];
 
1365
                                this.localRefIndex = prev.localRefIndex;
 
1366
                                this.callerID = prev.callerID;
 
1367
                                Exception x = pendingException;
 
1368
                                pendingException = null;
 
1369
                                return x;
 
1370
                        }
 
1371
 
 
1372
                        internal jobject MakeLocalRef(object obj)
 
1373
                        {
 
1374
                                if (obj == null)
 
1375
                                {
 
1376
                                        return IntPtr.Zero;
 
1377
                                }
 
1378
 
 
1379
                                int index;
 
1380
                                if (localRefIndex == active.Length)
 
1381
                                {
 
1382
                                        index = FindFreeIndex();
 
1383
                                }
 
1384
                                else
 
1385
                                {
 
1386
                                        index = localRefIndex++;
 
1387
                                }
 
1388
                                active[index] = obj;
 
1389
                                return (IntPtr)((localRefSlot << LOCAL_REF_SHIFT) + index);
 
1390
                        }
 
1391
 
 
1392
                        private int FindFreeIndex()
 
1393
                        {
 
1394
                                for (int i = 0; i < active.Length; i++)
 
1395
                                {
 
1396
                                        if (active[i] == null)
 
1397
                                        {
 
1398
                                                while (localRefIndex - 1 > i && active[localRefIndex - 1] == null)
 
1399
                                                {
 
1400
                                                        localRefIndex--;
 
1401
                                                }
 
1402
                                                return i;
 
1403
                                        }
 
1404
                                }
 
1405
                                GrowActiveSlot();
 
1406
                                return localRefIndex++;
 
1407
                        }
 
1408
 
 
1409
                        private void GrowActiveSlot()
 
1410
                        {
 
1411
                                if (active.Length < LOCAL_REF_MAX_BUCKET_SIZE)
 
1412
                                {
 
1413
                                        object[] tmp = new object[active.Length * 2];
 
1414
                                        Array.Copy(active, tmp, active.Length);
 
1415
                                        active = localRefs[localRefSlot] = tmp;
 
1416
                                        return;
 
1417
                                }
 
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)
 
1423
                                localRefSlot++;
 
1424
                                localRefIndex = 0;
 
1425
                                if (localRefSlot == localRefs.Length)
 
1426
                                {
 
1427
                                        object[][] tmp = new object[localRefSlot * 2][];
 
1428
                                        Array.Copy(localRefs, 0, tmp, 0, localRefSlot);
 
1429
                                        localRefs = tmp;
 
1430
                                }
 
1431
                                active = localRefs[localRefSlot];
 
1432
                                if (active == null)
 
1433
                                {
 
1434
                                        active = localRefs[localRefSlot] = new object[LOCAL_REF_MAX_BUCKET_SIZE];
 
1435
                                }
 
1436
                        }
 
1437
 
 
1438
                        internal object UnwrapLocalRef(int i)
 
1439
                        {
 
1440
                                return localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK];
 
1441
                        }
 
1442
 
 
1443
                        internal int PushLocalFrame(jint capacity)
 
1444
                        {
 
1445
                                localRefSlot += 2;
 
1446
                                if (localRefSlot >= localRefs.Length)
 
1447
                                {
 
1448
                                        object[][] tmp = new object[localRefs.Length * 2][];
 
1449
                                        Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
 
1450
                                        localRefs = tmp;
 
1451
                                }
 
1452
                                // we use a null slot to mark the fact that we used PushLocalFrame
 
1453
                                localRefs[localRefSlot - 1] = null;
 
1454
                                if (localRefs[localRefSlot] == null)
 
1455
                                {
 
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
 
1458
                                        int r = 1;
 
1459
                                        capacity = Math.Min(capacity, LOCAL_REF_MAX_BUCKET_SIZE);
 
1460
                                        while (r < capacity)
 
1461
                                        {
 
1462
                                                r *= 2;
 
1463
                                        }
 
1464
                                        localRefs[localRefSlot] = new object[r];
 
1465
                                }
 
1466
                                localRefIndex = 0;
 
1467
                                active = localRefs[localRefSlot];
 
1468
                                return JNI_OK;
 
1469
                        }
 
1470
 
 
1471
                        internal jobject PopLocalFrame(object res)
 
1472
                        {
 
1473
                                while (localRefs[localRefSlot] != null)
 
1474
                                {
 
1475
                                        localRefs[localRefSlot] = null;
 
1476
                                        localRefSlot--;
 
1477
                                }
 
1478
                                localRefSlot--;
 
1479
                                localRefIndex = localRefs[localRefSlot].Length;
 
1480
                                active = localRefs[localRefSlot];
 
1481
                                return MakeLocalRef(res);
 
1482
                        }
 
1483
 
 
1484
                        internal void DeleteLocalRef(jobject obj)
 
1485
                        {
 
1486
                                int i = obj.ToInt32();
 
1487
                                if (i > 0)
 
1488
                                {
 
1489
                                        localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK] = null;
 
1490
                                        return;
 
1491
                                }
 
1492
                                if (i < 0)
 
1493
                                {
 
1494
                                        Debug.Assert(false, "bogus localref in DeleteLocalRef");
 
1495
                                }
 
1496
                        }
 
1497
                }
 
1498
 
 
1499
                internal static JNIEnv* CreateJNIEnv()
 
1500
                {
 
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;
 
1509
                        return pJNIEnv;
 
1510
                }
 
1511
 
 
1512
                internal static void FreeJNIEnv()
 
1513
                {
 
1514
                        TlsHack.ManagedJNIEnv = null;
 
1515
                }
 
1516
 
 
1517
                internal static string StringFromOEM(byte* psz)
 
1518
                {
 
1519
                        for(int i = 0;; i++)
 
1520
                        {
 
1521
                                if(psz[i] == 0)
 
1522
                                {
 
1523
                                        int oem = System.Globalization.CultureInfo.CurrentCulture.TextInfo.OEMCodePage;
 
1524
                                        return new String((sbyte*)psz, 0, i, Encoding.GetEncoding(oem));
 
1525
                                }
 
1526
                        }
 
1527
                }
 
1528
 
 
1529
                internal static string StringFromUTF8(byte* psz)
 
1530
                {
 
1531
                        // Sun's modified UTF8 encoding is not compatible with System.Text.Encoding.UTF8,
 
1532
                        // so we need to roll our own
 
1533
                        int len = 0;
 
1534
                        bool hasNonAscii = false;
 
1535
                        while(psz[len] != 0)
 
1536
                        {
 
1537
                                hasNonAscii |= psz[len] >= 128;
 
1538
                                len++;
 
1539
                        }
 
1540
                        if(!hasNonAscii)
 
1541
                        {
 
1542
                                // optimize the common case of 7-bit ASCII
 
1543
                                return new String((sbyte*)psz);
 
1544
                        }
 
1545
                        StringBuilder sb = new StringBuilder(len);
 
1546
                        for(int i = 0; i < len; i++)
 
1547
                        {
 
1548
                                int c = *psz++;
 
1549
                                int char2, char3;
 
1550
                                switch(c >> 4)
 
1551
                                {
 
1552
                                        case 12:
 
1553
                                        case 13:
 
1554
                                                char2 = *psz++;
 
1555
                                                i++;
 
1556
                                                c = (((c & 0x1F) << 6) | (char2 & 0x3F));
 
1557
                                                break;
 
1558
                                        case 14:
 
1559
                                                char2 = *psz++;
 
1560
                                                char3 = *psz++;
 
1561
                                                i++;
 
1562
                                                i++;
 
1563
                                                c = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F);
 
1564
                                                break;
 
1565
                                }
 
1566
                                sb.Append((char)c);
 
1567
                        }
 
1568
                        return sb.ToString();
 
1569
                }
 
1570
 
 
1571
                private static int StringUTF8Length(string s)
 
1572
                {
 
1573
                        int len = 0;
 
1574
                        for(int i = 0; i < s.Length; i++)
 
1575
                        {
 
1576
                                char ch = s[i];
 
1577
                                if((ch != 0) && (ch <= 0x7F))
 
1578
                                {
 
1579
                                        len++;
 
1580
                                }
 
1581
                                else if(ch <= 0x7FF)
 
1582
                                {
 
1583
                                        len += 2;
 
1584
                                }
 
1585
                                else
 
1586
                                {
 
1587
                                        len += 3;
 
1588
                                }
 
1589
                        }
 
1590
                        return len;
 
1591
                }
 
1592
 
 
1593
                internal static jint GetMethodArgs(JNIEnv* pEnv, IntPtr method, byte* sig)
 
1594
                {
 
1595
                        TypeWrapper[] argTypes = MethodWrapper.FromCookie(method).GetParameters();
 
1596
                        for (int i = 0; i < argTypes.Length; i++)
 
1597
                        {
 
1598
                                TypeWrapper tw = argTypes[i];
 
1599
                                if (tw.IsPrimitive)
 
1600
                                {
 
1601
                                        sig[i] = (byte)tw.SigName[0];
 
1602
                                }
 
1603
                                else
 
1604
                                {
 
1605
                                        sig[i] = (byte)'L';
 
1606
                                }
 
1607
                        }
 
1608
                        return argTypes.Length;
 
1609
                }
 
1610
 
 
1611
                internal static jint GetVersion(JNIEnv* pEnv)
 
1612
                {
 
1613
                        return JNI_VERSION_1_6;
 
1614
                }
 
1615
 
 
1616
                internal static jclass DefineClass(JNIEnv* pEnv, byte* name, jobject loader, jbyte* pbuf, jint length)
 
1617
                {
 
1618
                        try
 
1619
                        {
 
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));
 
1626
                        }
 
1627
                        catch(Exception x)
 
1628
                        {
 
1629
                                SetPendingException(pEnv, x);
 
1630
                                return IntPtr.Zero;
 
1631
                        }
 
1632
                }
 
1633
 
 
1634
                private static ClassLoaderWrapper FindNativeMethodClassLoader(JNIEnv* pEnv)
 
1635
                {
 
1636
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1637
                        if(env.callerID != null)
 
1638
                        {
 
1639
                                return ClassLoaderWrapper.FromCallerID(env.callerID);
 
1640
                        }
 
1641
                        if(env.classLoader != null)
 
1642
                        {
 
1643
                                return env.classLoader;
 
1644
                        }
 
1645
                        return ClassLoaderWrapper.GetClassLoaderWrapper(java.lang.ClassLoader.getSystemClassLoader());
 
1646
                }
 
1647
 
 
1648
                internal static jclass FindClass(JNIEnv* pEnv, byte* pszName)
 
1649
                {
 
1650
                        try
 
1651
                        {
 
1652
                                string name = StringFromOEM(pszName);
 
1653
                                // don't allow dotted names!
 
1654
                                if(name.IndexOf('.') >= 0)
 
1655
                                {
 
1656
                                        SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name));
 
1657
                                        return IntPtr.Zero;
 
1658
                                }
 
1659
                                // spec doesn't say it, but Sun allows signature format class names (but not for primitives)
 
1660
                                if(name.StartsWith("L") && name.EndsWith(";"))
 
1661
                                {
 
1662
                                        name = name.Substring(1, name.Length - 2);
 
1663
                                }
 
1664
                                TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedNameFast(name.Replace('/', '.'));
 
1665
                                if(wrapper == null)
 
1666
                                {
 
1667
                                        SetPendingException(pEnv, new java.lang.NoClassDefFoundError(name));
 
1668
                                        return IntPtr.Zero;
 
1669
                                }
 
1670
                                wrapper.Finish();
 
1671
                                // spec doesn't say it, but Sun runs the static initializer
 
1672
                                wrapper.RunClassInit();
 
1673
                                return pEnv->MakeLocalRef(wrapper.ClassObject);
 
1674
                        }
 
1675
                        catch(Exception x)
 
1676
                        {
 
1677
                                if(x is RetargetableJavaException)
 
1678
                                {
 
1679
                                        x = ((RetargetableJavaException)x).ToJava();
 
1680
                                }
 
1681
                                SetPendingException(pEnv, x);
 
1682
                                return IntPtr.Zero;
 
1683
                        }
 
1684
                }
 
1685
 
 
1686
                internal static jmethodID FromReflectedMethod(JNIEnv* pEnv, jobject method)
 
1687
                {
 
1688
                        return MethodWrapper.FromMethodOrConstructor(pEnv->UnwrapRef(method)).Cookie;
 
1689
                }
 
1690
 
 
1691
                internal static jfieldID FromReflectedField(JNIEnv* pEnv, jobject field)
 
1692
                {
 
1693
                        return FieldWrapper.FromField(pEnv->UnwrapRef(field)).Cookie;
 
1694
                }
 
1695
 
 
1696
                internal static jobject ToReflectedMethod(JNIEnv* pEnv, jclass clazz_ignored, jmethodID method, jboolean isStatic)
 
1697
                {
 
1698
                        return pEnv->MakeLocalRef(MethodWrapper.FromCookie(method).ToMethodOrConstructor(true));
 
1699
                }
 
1700
 
 
1701
                internal static jclass GetSuperclass(JNIEnv* pEnv, jclass sub)
 
1702
                {
 
1703
                        TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(sub)).BaseTypeWrapper;
 
1704
                        return pEnv->MakeLocalRef(wrapper == null ? null : wrapper.ClassObject);
 
1705
                }
 
1706
 
 
1707
                internal static jboolean IsAssignableFrom(JNIEnv* pEnv, jclass sub, jclass super)
 
1708
                {
 
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;
 
1712
                }
 
1713
 
 
1714
                internal static jobject ToReflectedField(JNIEnv* pEnv, jclass clazz_ignored, jfieldID field, jboolean isStatic)
 
1715
                {
 
1716
                        return pEnv->MakeLocalRef(FieldWrapper.FromCookie(field).ToField(true));
 
1717
                }
 
1718
 
 
1719
                private static void SetPendingException(JNIEnv* pEnv, Exception x)
 
1720
                {
 
1721
                        pEnv->GetManagedJNIEnv().pendingException = ikvm.runtime.Util.mapException(x);
 
1722
                }
 
1723
 
 
1724
                internal static jint Throw(JNIEnv* pEnv, jthrowable throwable)
 
1725
                {
 
1726
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1727
                        Exception x = UnwrapRef(env, throwable) as Exception;
 
1728
                        env.pendingException = x;
 
1729
                        return JNI_OK;
 
1730
                }
 
1731
 
 
1732
                internal static jint ThrowNew(JNIEnv* pEnv, jclass clazz, byte* msg)
 
1733
                {
 
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);
 
1737
                        if(mw != null)
 
1738
                        {
 
1739
                                jint rc;
 
1740
                                Exception exception;
 
1741
                                try
 
1742
                                {
 
1743
                                        wrapper.Finish();
 
1744
                                        java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)mw.ToMethodOrConstructor(false);
 
1745
                                        exception = (Exception)cons.newInstance(new object[] { StringFromOEM(msg) }, env.callerID);
 
1746
                                        rc = JNI_OK;
 
1747
                                }
 
1748
                                catch(RetargetableJavaException x)
 
1749
                                {
 
1750
                                        exception = x.ToJava();
 
1751
                                        rc = JNI_ERR;
 
1752
                                }
 
1753
                                catch(Exception x)
 
1754
                                {
 
1755
                                        exception = x;
 
1756
                                        rc = JNI_ERR;
 
1757
                                }
 
1758
                                SetPendingException(pEnv, exception);
 
1759
                                return rc;
 
1760
                        }
 
1761
                        else
 
1762
                        {
 
1763
                                SetPendingException(pEnv, new java.lang.NoSuchMethodError("<init>(Ljava.lang.String;)V"));
 
1764
                                return JNI_ERR;
 
1765
                        }
 
1766
                }
 
1767
 
 
1768
                internal static jthrowable ExceptionOccurred(JNIEnv* pEnv)
 
1769
                {
 
1770
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1771
                        return pEnv->MakeLocalRef(env.pendingException);
 
1772
                }
 
1773
 
 
1774
                internal static void ExceptionDescribe(JNIEnv* pEnv)
 
1775
                {
 
1776
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1777
                        Exception x = env.pendingException;
 
1778
                        if(x != null)
 
1779
                        {
 
1780
                                env.pendingException = null;
 
1781
                                try
 
1782
                                {
 
1783
                                        ikvm.extensions.ExtensionMethods.printStackTrace(x);
 
1784
                                }
 
1785
                                catch(Exception ex)
 
1786
                                {
 
1787
                                        Debug.Assert(false, ex.ToString());
 
1788
                                }
 
1789
                        }
 
1790
                }
 
1791
 
 
1792
                internal static void ExceptionClear(JNIEnv* pEnv)
 
1793
                {
 
1794
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1795
                        env.pendingException = null;
 
1796
                }
 
1797
 
 
1798
                internal static void FatalError(JNIEnv* pEnv, byte* msg)
 
1799
                {
 
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);
 
1803
                }
 
1804
 
 
1805
                internal static jint PushLocalFrame(JNIEnv* pEnv, jint capacity)
 
1806
                {
 
1807
                        return pEnv->GetManagedJNIEnv().PushLocalFrame(capacity);
 
1808
                }
 
1809
 
 
1810
                internal static jobject PopLocalFrame(JNIEnv* pEnv, jobject result)
 
1811
                {
 
1812
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
1813
                        return env.PopLocalFrame(UnwrapRef(env, result));
 
1814
                }
 
1815
 
 
1816
                internal static jobject NewGlobalRef(JNIEnv* pEnv, jobject obj)
 
1817
                {
 
1818
                        object o = pEnv->UnwrapRef(obj);
 
1819
                        if(o == null)
 
1820
                        {
 
1821
                                return IntPtr.Zero;
 
1822
                        }
 
1823
                        lock(GlobalRefs.globalRefs)
 
1824
                        {
 
1825
                                int index = GlobalRefs.globalRefs.IndexOf(null);
 
1826
                                if(index >= 0)
 
1827
                                {
 
1828
                                        GlobalRefs.globalRefs[index] = o;
 
1829
                                }
 
1830
                                else
 
1831
                                {
 
1832
                                        index = GlobalRefs.globalRefs.Add(o);
 
1833
                                }
 
1834
                                return (IntPtr)(-(index + 1));
 
1835
                        }
 
1836
                }
 
1837
 
 
1838
                internal static void DeleteGlobalRef(JNIEnv* pEnv, jobject obj)
 
1839
                {
 
1840
                        int i = obj.ToInt32();
 
1841
                        if(i < 0)
 
1842
                        {
 
1843
                                lock(GlobalRefs.globalRefs)
 
1844
                                {
 
1845
                                        GlobalRefs.globalRefs[(-i) - 1] = null;
 
1846
                                }
 
1847
                                return;
 
1848
                        }
 
1849
                        if(i > 0)
 
1850
                        {
 
1851
                                Debug.Assert(false, "Local ref passed to DeleteGlobalRef");
 
1852
                        }
 
1853
                }
 
1854
 
 
1855
                internal static void DeleteLocalRef(JNIEnv* pEnv, jobject obj)
 
1856
                {
 
1857
                        pEnv->GetManagedJNIEnv().DeleteLocalRef(obj);
 
1858
                }
 
1859
 
 
1860
                internal static jboolean IsSameObject(JNIEnv* pEnv, jobject obj1, jobject obj2)
 
1861
                {
 
1862
                        return pEnv->UnwrapRef(obj1) == pEnv->UnwrapRef(obj2) ? JNI_TRUE : JNI_FALSE;
 
1863
                }
 
1864
 
 
1865
                internal static jobject NewLocalRef(JNIEnv* pEnv, jobject obj)
 
1866
                {
 
1867
                        return pEnv->MakeLocalRef(pEnv->UnwrapRef(obj));
 
1868
                }
 
1869
 
 
1870
                internal static jint EnsureLocalCapacity(JNIEnv* pEnv, jint capacity)
 
1871
                {
 
1872
                        // since we can dynamically grow the local ref table, we'll just return success for any number
 
1873
                        return JNI_OK;
 
1874
                }
 
1875
 
 
1876
                internal static jobject AllocObject(JNIEnv* pEnv, jclass clazz)
 
1877
                {
 
1878
                        return AllocObjectImpl(pEnv, TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz)));
 
1879
                }
 
1880
 
 
1881
                private static jobject AllocObjectImpl(JNIEnv* pEnv, TypeWrapper wrapper)
 
1882
                {
 
1883
                        try
 
1884
                        {
 
1885
                                if(wrapper.IsAbstract)
 
1886
                                {
 
1887
                                        SetPendingException(pEnv, new java.lang.InstantiationException(wrapper.Name));
 
1888
                                        return IntPtr.Zero;
 
1889
                                }
 
1890
                                wrapper.Finish();
 
1891
                                return pEnv->MakeLocalRef(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType));
 
1892
                        }
 
1893
                        catch(RetargetableJavaException x)
 
1894
                        {
 
1895
                                SetPendingException(pEnv, x.ToJava());
 
1896
                                return IntPtr.Zero;
 
1897
                        }
 
1898
                        catch(Exception x)
 
1899
                        {
 
1900
                                SetPendingException(pEnv, x);
 
1901
                                return IntPtr.Zero;
 
1902
                        }
 
1903
                }
 
1904
 
 
1905
                [StructLayout(LayoutKind.Explicit)]
 
1906
                        internal struct jvalue
 
1907
                {
 
1908
                        [FieldOffset(0)]
 
1909
                        public jboolean z;
 
1910
                        [FieldOffset(0)]
 
1911
                        public jbyte b;
 
1912
                        [FieldOffset(0)]
 
1913
                        public jchar c;
 
1914
                        [FieldOffset(0)]
 
1915
                        public jshort s;
 
1916
                        [FieldOffset(0)]
 
1917
                        public jint i;
 
1918
                        [FieldOffset(0)]
 
1919
                        public jlong j;
 
1920
                        [FieldOffset(0)]
 
1921
                        public jfloat f;
 
1922
                        [FieldOffset(0)]
 
1923
                        public jdouble d;
 
1924
                        [FieldOffset(0)]
 
1925
                        public jobject l;
 
1926
                }
 
1927
 
 
1928
                private static object InvokeHelper(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args, bool nonVirtual)
 
1929
                {
 
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++)
 
1935
                        {
 
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);
 
1953
                                else
 
1954
                                        argarray[i] = UnwrapRef(env, args[i].l);
 
1955
                        }
 
1956
                        try
 
1957
                        {
 
1958
                                return mw.InvokeJNI(UnwrapRef(env, obj), argarray, nonVirtual, env.callerID);
 
1959
                        }
 
1960
                        catch(java.lang.reflect.InvocationTargetException x)
 
1961
                        {
 
1962
                                SetPendingException(pEnv, ikvm.runtime.Util.mapException(x.getCause()));
 
1963
                                return null;
 
1964
                        }
 
1965
                        catch(Exception x)
 
1966
                        {
 
1967
                                SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
 
1968
                                return null;
 
1969
                        }
 
1970
                }
 
1971
 
 
1972
                internal static jobject NewObjectA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
1973
                {
 
1974
                        TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
 
1975
                        if(!wrapper.IsAbstract && wrapper.TypeAsBaseType.IsAbstract)
 
1976
                        {
 
1977
                                // static newinstance helper method
 
1978
                                return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
 
1979
                        }
 
1980
                        jobject obj = AllocObjectImpl(pEnv, wrapper);
 
1981
                        if(obj != IntPtr.Zero)
 
1982
                        {
 
1983
                                InvokeHelper(pEnv, obj, methodID, args, false);
 
1984
                                if(ExceptionCheck(pEnv) == JNI_TRUE)
 
1985
                                {
 
1986
                                        DeleteLocalRef(pEnv, obj);
 
1987
                                        obj = IntPtr.Zero;
 
1988
                                }
 
1989
                        }
 
1990
                        return obj;
 
1991
                }
 
1992
 
 
1993
                internal static jclass GetObjectClass(JNIEnv* pEnv, jobject obj)
 
1994
                {
 
1995
                        return pEnv->MakeLocalRef(IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj)));
 
1996
                }
 
1997
 
 
1998
                internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz)
 
1999
                {
 
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;
 
2006
                }
 
2007
 
 
2008
                private static MethodWrapper GetMethodImpl(TypeWrapper tw, string name, string sig)
 
2009
                {
 
2010
                        for(;;)
 
2011
                        {
 
2012
                                MethodWrapper mw = tw.GetMethodWrapper(name, sig, true);
 
2013
                                if(mw == null || !mw.IsHideFromReflection)
 
2014
                                {
 
2015
                                        return mw;
 
2016
                                }
 
2017
                                tw = mw.DeclaringType.BaseTypeWrapper;
 
2018
                                if(tw == null)
 
2019
                                {
 
2020
                                        return null;
 
2021
                                }
 
2022
                        }
 
2023
                }
 
2024
 
 
2025
                private static void AppendInterfaces(List<TypeWrapper> list, IList<TypeWrapper> add)
 
2026
                {
 
2027
                        foreach (TypeWrapper iface in add)
 
2028
                        {
 
2029
                                if (!list.Contains(iface))
 
2030
                                {
 
2031
                                        list.Add(iface);
 
2032
                                }
 
2033
                        }
 
2034
                }
 
2035
 
 
2036
                private static List<TypeWrapper> TransitiveInterfaces(TypeWrapper tw)
 
2037
                {
 
2038
                        List<TypeWrapper> list = new List<TypeWrapper>();
 
2039
                        if (tw.BaseTypeWrapper != null)
 
2040
                        {
 
2041
                                AppendInterfaces(list, TransitiveInterfaces(tw.BaseTypeWrapper));
 
2042
                        }
 
2043
                        foreach (TypeWrapper iface in tw.Interfaces)
 
2044
                        {
 
2045
                                AppendInterfaces(list, TransitiveInterfaces(iface));
 
2046
                        }
 
2047
                        AppendInterfaces(list, tw.Interfaces);
 
2048
                        return list;
 
2049
                }
 
2050
 
 
2051
                private static MethodWrapper GetInterfaceMethodImpl(TypeWrapper tw, string name, string sig)
 
2052
                {
 
2053
                        foreach (TypeWrapper iface in TransitiveInterfaces(tw))
 
2054
                        {
 
2055
                                MethodWrapper mw = iface.GetMethodWrapper(name, sig, false);
 
2056
                                if (mw != null && !mw.IsHideFromReflection)
 
2057
                                {
 
2058
                                        return mw;
 
2059
                                }
 
2060
                        }
 
2061
                        return null;
 
2062
                }
 
2063
 
 
2064
                private static jmethodID FindMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
 
2065
                {
 
2066
                        try
 
2067
                        {
 
2068
                                TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
 
2069
                                wrapper.Finish();
 
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)
 
2076
                                {
 
2077
                                        methodsig = methodsig.Replace('/', '.');
 
2078
                                        if(methodname == "<init>" || methodname == "<clinit>")
 
2079
                                        {
 
2080
                                                mw = wrapper.GetMethodWrapper(methodname, methodsig, false);
 
2081
                                        }
 
2082
                                        else
 
2083
                                        {
 
2084
                                                mw = GetMethodImpl(wrapper, methodname, methodsig);
 
2085
                                                if(mw == null)
 
2086
                                                {
 
2087
                                                        mw = GetInterfaceMethodImpl(wrapper, methodname, methodsig);
 
2088
                                                }
 
2089
                                        }
 
2090
                                }
 
2091
                                if(mw != null && mw.IsStatic == isstatic)
 
2092
                                {
 
2093
                                        mw.Link();
 
2094
                                        return mw.Cookie;
 
2095
                                }
 
2096
                                SetPendingException(pEnv, new java.lang.NoSuchMethodError(string.Format("{0}{1}", methodname, methodsig)));
 
2097
                        }
 
2098
                        catch(RetargetableJavaException x)
 
2099
                        {
 
2100
                                SetPendingException(pEnv, x.ToJava());
 
2101
                        }
 
2102
                        catch(Exception x)
 
2103
                        {
 
2104
                                SetPendingException(pEnv, x);
 
2105
                        }
 
2106
                        return IntPtr.Zero;
 
2107
                }
 
2108
 
 
2109
                internal static jmethodID GetMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
 
2110
                {
 
2111
                        return FindMethodID(pEnv, clazz, name, sig, false);
 
2112
                }
 
2113
 
 
2114
                internal static jobject CallObjectMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2115
                {
 
2116
                        return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, false));
 
2117
                }
 
2118
 
 
2119
                internal static jboolean CallBooleanMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2120
                {
 
2121
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2122
                        if(o != null)
 
2123
                        {
 
2124
                                return ((bool)o) ? JNI_TRUE : JNI_FALSE;
 
2125
                        }
 
2126
                        return JNI_FALSE;
 
2127
                }
 
2128
 
 
2129
                internal static jbyte CallByteMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2130
                {
 
2131
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2132
                        if(o != null)
 
2133
                        {
 
2134
                                return (jbyte)(byte)o;
 
2135
                        }
 
2136
                        return 0;
 
2137
                }
 
2138
 
 
2139
                internal static jchar CallCharMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2140
                {
 
2141
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2142
                        if(o != null)
 
2143
                        {
 
2144
                                return (jchar)(char)o;
 
2145
                        }
 
2146
                        return 0;
 
2147
                }
 
2148
 
 
2149
                internal static jshort CallShortMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2150
                {
 
2151
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2152
                        if(o != null)
 
2153
                        {
 
2154
                                return (jshort)(short)o;
 
2155
                        }
 
2156
                        return 0;
 
2157
                }
 
2158
 
 
2159
                internal static jint CallIntMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2160
                {
 
2161
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2162
                        if(o != null)
 
2163
                        {
 
2164
                                return (jint)(int)o;
 
2165
                        }
 
2166
                        return 0;
 
2167
                }
 
2168
 
 
2169
                internal static jlong CallLongMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2170
                {
 
2171
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2172
                        if(o != null)
 
2173
                        {
 
2174
                                return (jlong)(long)o;
 
2175
                        }
 
2176
                        return 0;
 
2177
                }
 
2178
 
 
2179
                internal static jfloat CallFloatMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2180
                {
 
2181
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2182
                        if(o != null)
 
2183
                        {
 
2184
                                return (jfloat)(float)o;
 
2185
                        }
 
2186
                        return 0;
 
2187
                }
 
2188
 
 
2189
                internal static jdouble CallDoubleMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
 
2190
                {
 
2191
                        object o = InvokeHelper(pEnv, obj, methodID, args, false);
 
2192
                        if(o != null)
 
2193
                        {
 
2194
                                return (jdouble)(double)o;
 
2195
                        }
 
2196
                        return 0;
 
2197
                }
 
2198
 
 
2199
                internal static void CallVoidMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue*  args)
 
2200
                {
 
2201
                        InvokeHelper(pEnv, obj, methodID, args, false);
 
2202
                }
 
2203
 
 
2204
                internal static jobject CallNonvirtualObjectMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue*  args)
 
2205
                {
 
2206
                        return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, true));
 
2207
                }
 
2208
 
 
2209
                internal static jboolean CallNonvirtualBooleanMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue*  args)
 
2210
                {
 
2211
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2212
                        if(o != null)
 
2213
                        {
 
2214
                                return ((bool)o) ? JNI_TRUE : JNI_FALSE;
 
2215
                        }
 
2216
                        return JNI_FALSE;
 
2217
                }
 
2218
 
 
2219
                internal static jbyte CallNonvirtualByteMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2220
                {
 
2221
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2222
                        if(o != null)
 
2223
                        {
 
2224
                                return (jbyte)(byte)o;
 
2225
                        }
 
2226
                        return 0;
 
2227
                }
 
2228
 
 
2229
                internal static jchar CallNonvirtualCharMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2230
                {
 
2231
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2232
                        if(o != null)
 
2233
                        {
 
2234
                                return (jchar)(char)o;
 
2235
                        }
 
2236
                        return 0;
 
2237
                }
 
2238
 
 
2239
                internal static jshort CallNonvirtualShortMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2240
                {
 
2241
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2242
                        if(o != null)
 
2243
                        {
 
2244
                                return (jshort)(short)o;
 
2245
                        }
 
2246
                        return 0;
 
2247
                }
 
2248
 
 
2249
                internal static jint CallNonvirtualIntMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2250
                {
 
2251
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2252
                        if(o != null)
 
2253
                        {
 
2254
                                return (jint)(int)o;
 
2255
                        }
 
2256
                        return 0;
 
2257
                }
 
2258
 
 
2259
                internal static jlong CallNonvirtualLongMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2260
                {
 
2261
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2262
                        if(o != null)
 
2263
                        {
 
2264
                                return (jlong)(long)o;
 
2265
                        }
 
2266
                        return 0;
 
2267
                }
 
2268
 
 
2269
                internal static jfloat CallNonvirtualFloatMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2270
                {
 
2271
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2272
                        if(o != null)
 
2273
                        {
 
2274
                                return (jfloat)(float)o;
 
2275
                        }
 
2276
                        return 0;
 
2277
                }
 
2278
 
 
2279
                internal static jdouble CallNonvirtualDoubleMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2280
                {
 
2281
                        object o = InvokeHelper(pEnv, obj, methodID, args, true);
 
2282
                        if(o != null)
 
2283
                        {
 
2284
                                return (jdouble)(double)o;
 
2285
                        }
 
2286
                        return 0;
 
2287
                }
 
2288
 
 
2289
                internal static void CallNonvirtualVoidMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
 
2290
                {
 
2291
                        InvokeHelper(pEnv, obj, methodID, args, true);
 
2292
                }
 
2293
 
 
2294
                private static FieldWrapper GetFieldImpl(TypeWrapper tw, string name, string sig)
 
2295
                {
 
2296
                        for(;;)
 
2297
                        {
 
2298
                                FieldWrapper fw = tw.GetFieldWrapper(name, sig);
 
2299
                                if(fw == null || !fw.IsHideFromReflection)
 
2300
                                {
 
2301
                                        return fw;
 
2302
                                }
 
2303
                                tw = fw.DeclaringType.BaseTypeWrapper;
 
2304
                                if(tw == null)
 
2305
                                {
 
2306
                                        return null;
 
2307
                                }
 
2308
                        }
 
2309
                }
 
2310
 
 
2311
                private static jfieldID FindFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
 
2312
                {
 
2313
                        try
 
2314
                        {
 
2315
                                TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
 
2316
                                wrapper.Finish();
 
2317
                                string fieldsig = StringFromUTF8(sig);
 
2318
                                // don't allow dotted names!
 
2319
                                if(fieldsig.IndexOf('.') < 0)
 
2320
                                {
 
2321
                                        FieldWrapper fw = GetFieldImpl(wrapper, StringFromUTF8(name), fieldsig.Replace('/', '.'));
 
2322
                                        if(fw != null)
 
2323
                                        {
 
2324
                                                if(fw.IsStatic == isstatic)
 
2325
                                                {
 
2326
                                                        return fw.Cookie;
 
2327
                                                }
 
2328
                                        }
 
2329
                                }
 
2330
                                SetPendingException(pEnv, new java.lang.NoSuchFieldError((isstatic ? "Static" : "Instance") + " field '" + StringFromUTF8(name) + "' with signature '" + fieldsig + "' not found in class '" + wrapper.Name + "'"));
 
2331
                        }
 
2332
                        catch(RetargetableJavaException x)
 
2333
                        {
 
2334
                                SetPendingException(pEnv, x.ToJava());
 
2335
                        }
 
2336
                        catch(Exception x)
 
2337
                        {
 
2338
                                SetPendingException(pEnv, x);
 
2339
                        }
 
2340
                        return IntPtr.Zero;
 
2341
                }
 
2342
 
 
2343
                internal static jfieldID GetFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
 
2344
                {
 
2345
                        return FindFieldID(pEnv, clazz, name, sig, false);
 
2346
                }
 
2347
 
 
2348
                private static sun.reflect.FieldAccessor GetFieldAccessor(jfieldID cookie)
 
2349
                {
 
2350
                        return (sun.reflect.FieldAccessor)FieldWrapper.FromCookie(cookie).GetFieldAccessorJNI();
 
2351
                }
 
2352
 
 
2353
                internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2354
                {
 
2355
                        return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(pEnv->UnwrapRef(obj)));
 
2356
                }
 
2357
 
 
2358
                internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2359
                {
 
2360
                        return GetFieldAccessor(fieldID).getBoolean(pEnv->UnwrapRef(obj)) ? JNI_TRUE : JNI_FALSE;
 
2361
                }
 
2362
 
 
2363
                internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2364
                {
 
2365
                        return (jbyte)GetFieldAccessor(fieldID).getByte(pEnv->UnwrapRef(obj));
 
2366
                }
 
2367
 
 
2368
                internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2369
                {
 
2370
                        return (jchar)GetFieldAccessor(fieldID).getChar(pEnv->UnwrapRef(obj));
 
2371
                }
 
2372
 
 
2373
                internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2374
                {
 
2375
                        return (jshort)GetFieldAccessor(fieldID).getShort(pEnv->UnwrapRef(obj));
 
2376
                }
 
2377
 
 
2378
                internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2379
                {
 
2380
                        return (jint)GetFieldAccessor(fieldID).getInt(pEnv->UnwrapRef(obj));
 
2381
                }
 
2382
 
 
2383
                internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2384
                {
 
2385
                        return (jlong)GetFieldAccessor(fieldID).getLong(pEnv->UnwrapRef(obj));
 
2386
                }
 
2387
 
 
2388
                internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2389
                {
 
2390
                        return (jfloat)GetFieldAccessor(fieldID).getFloat(pEnv->UnwrapRef(obj));
 
2391
                }
 
2392
 
 
2393
                internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
 
2394
                {
 
2395
                        return (jdouble)GetFieldAccessor(fieldID).getDouble(pEnv->UnwrapRef(obj));
 
2396
                }
 
2397
 
 
2398
                internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val)
 
2399
                {
 
2400
                        GetFieldAccessor(fieldID).set(pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val));
 
2401
                }
 
2402
 
 
2403
                internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val)
 
2404
                {
 
2405
                        GetFieldAccessor(fieldID).setBoolean(pEnv->UnwrapRef(obj), val != JNI_FALSE);
 
2406
                }
 
2407
 
 
2408
                internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val)
 
2409
                {
 
2410
                        GetFieldAccessor(fieldID).setByte(pEnv->UnwrapRef(obj), (byte)val);
 
2411
                }
 
2412
 
 
2413
                internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val)
 
2414
                {
 
2415
                        GetFieldAccessor(fieldID).setChar(pEnv->UnwrapRef(obj), (char)val);
 
2416
                }
 
2417
 
 
2418
                internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val)
 
2419
                {
 
2420
                        GetFieldAccessor(fieldID).setShort(pEnv->UnwrapRef(obj), (short)val);
 
2421
                }
 
2422
 
 
2423
                internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val)
 
2424
                {
 
2425
                        GetFieldAccessor(fieldID).setInt(pEnv->UnwrapRef(obj), (int)val);
 
2426
                }
 
2427
 
 
2428
                internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val)
 
2429
                {
 
2430
                        GetFieldAccessor(fieldID).setLong(pEnv->UnwrapRef(obj), (long)val);
 
2431
                }
 
2432
 
 
2433
                internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val)
 
2434
                {
 
2435
                        GetFieldAccessor(fieldID).setFloat(pEnv->UnwrapRef(obj), (float)val);
 
2436
                }
 
2437
 
 
2438
                internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val)
 
2439
                {
 
2440
                        GetFieldAccessor(fieldID).setDouble(pEnv->UnwrapRef(obj), (double)val);
 
2441
                }
 
2442
 
 
2443
                internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
 
2444
                {
 
2445
                        return FindMethodID(pEnv, clazz, name, sig, true);
 
2446
                }
 
2447
 
 
2448
                internal static jobject CallStaticObjectMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2449
                {
 
2450
                        return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
 
2451
                }
 
2452
 
 
2453
                internal static jboolean CallStaticBooleanMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2454
                {
 
2455
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2456
                        if(o != null)
 
2457
                        {
 
2458
                                return ((bool)o) ? JNI_TRUE : JNI_FALSE;
 
2459
                        }
 
2460
                        return JNI_FALSE;
 
2461
                }
 
2462
 
 
2463
                internal static jbyte CallStaticByteMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2464
                {
 
2465
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2466
                        if(o != null)
 
2467
                        {
 
2468
                                return (jbyte)(byte)o;
 
2469
                        }
 
2470
                        return 0;
 
2471
                }
 
2472
 
 
2473
                internal static jchar CallStaticCharMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2474
                {
 
2475
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2476
                        if(o != null)
 
2477
                        {
 
2478
                                return (jchar)(char)o;
 
2479
                        }
 
2480
                        return 0;
 
2481
                }
 
2482
 
 
2483
                internal static jshort CallStaticShortMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2484
                {
 
2485
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2486
                        if(o != null)
 
2487
                        {
 
2488
                                return (jshort)(short)o;
 
2489
                        }
 
2490
                        return 0;
 
2491
                }
 
2492
 
 
2493
                internal static jint CallStaticIntMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2494
                {
 
2495
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2496
                        if(o != null)
 
2497
                        {
 
2498
                                return (jint)(int)o;
 
2499
                        }
 
2500
                        return 0;
 
2501
                }
 
2502
 
 
2503
                internal static jlong CallStaticLongMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2504
                {
 
2505
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2506
                        if(o != null)
 
2507
                        {
 
2508
                                return (jlong)(long)o;
 
2509
                        }
 
2510
                        return 0;
 
2511
                }
 
2512
 
 
2513
                internal static jfloat CallStaticFloatMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2514
                {
 
2515
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2516
                        if(o != null)
 
2517
                        {
 
2518
                                return (jfloat)(float)o;
 
2519
                        }
 
2520
                        return 0;
 
2521
                }
 
2522
 
 
2523
                internal static jdouble CallStaticDoubleMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
 
2524
                {
 
2525
                        object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2526
                        if(o != null)
 
2527
                        {
 
2528
                                return (jdouble)(double)o;
 
2529
                        }
 
2530
                        return 0;
 
2531
                }
 
2532
 
 
2533
                internal static void CallStaticVoidMethodA(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args)
 
2534
                {
 
2535
                        InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
 
2536
                }
 
2537
 
 
2538
                internal static jfieldID GetStaticFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
 
2539
                {
 
2540
                        return FindFieldID(pEnv, clazz, name, sig, true);
 
2541
                }
 
2542
 
 
2543
                internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2544
                {
 
2545
                        return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(null));
 
2546
                }
 
2547
 
 
2548
                internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2549
                {
 
2550
                        return GetFieldAccessor(fieldID).getBoolean(null) ? JNI_TRUE : JNI_FALSE;
 
2551
                }
 
2552
 
 
2553
                internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2554
                {
 
2555
                        return (jbyte)GetFieldAccessor(fieldID).getByte(null);
 
2556
                }
 
2557
 
 
2558
                internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2559
                {
 
2560
                        return (jchar)GetFieldAccessor(fieldID).getChar(null);
 
2561
                }
 
2562
 
 
2563
                internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2564
                {
 
2565
                        return (jshort)GetFieldAccessor(fieldID).getShort(null);
 
2566
                }
 
2567
 
 
2568
                internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2569
                {
 
2570
                        return (jint)GetFieldAccessor(fieldID).getInt(null);
 
2571
                }
 
2572
 
 
2573
                internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2574
                {
 
2575
                        return (jlong)GetFieldAccessor(fieldID).getLong(null);
 
2576
                }
 
2577
 
 
2578
                internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2579
                {
 
2580
                        return (jfloat)GetFieldAccessor(fieldID).getFloat(null);
 
2581
                }
 
2582
 
 
2583
                internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
 
2584
                {
 
2585
                        return (jdouble)GetFieldAccessor(fieldID).getDouble(null);
 
2586
                }
 
2587
 
 
2588
                internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val)
 
2589
                {
 
2590
                        GetFieldAccessor(fieldID).set(null, pEnv->UnwrapRef(val));
 
2591
                }
 
2592
 
 
2593
                internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val)
 
2594
                {
 
2595
                        GetFieldAccessor(fieldID).setBoolean(null, val != JNI_FALSE);
 
2596
                }
 
2597
 
 
2598
                internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val)
 
2599
                {
 
2600
                        GetFieldAccessor(fieldID).setByte(null, (byte)val);
 
2601
                }
 
2602
 
 
2603
                internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val)
 
2604
                {
 
2605
                        GetFieldAccessor(fieldID).setChar(null, (char)val);
 
2606
                }
 
2607
 
 
2608
                internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val)
 
2609
                {
 
2610
                        GetFieldAccessor(fieldID).setShort(null, (short)val);
 
2611
                }
 
2612
 
 
2613
                internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val)
 
2614
                {
 
2615
                        GetFieldAccessor(fieldID).setInt(null, (int)val);
 
2616
                }
 
2617
 
 
2618
                internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val)
 
2619
                {
 
2620
                        GetFieldAccessor(fieldID).setLong(null, (long)val);
 
2621
                }
 
2622
 
 
2623
                internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val)
 
2624
                {
 
2625
                        GetFieldAccessor(fieldID).setFloat(null, (float)val);
 
2626
                }
 
2627
 
 
2628
                internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val)
 
2629
                {
 
2630
                        GetFieldAccessor(fieldID).setDouble(null, (double)val);
 
2631
                }
 
2632
 
 
2633
                internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len)
 
2634
                {
 
2635
                        return pEnv->MakeLocalRef(new String((char*)unicode, 0, len));
 
2636
                }
 
2637
 
 
2638
                internal static jint GetStringLength(JNIEnv* pEnv, jstring str)
 
2639
                {
 
2640
                        return ((string)pEnv->UnwrapRef(str)).Length;
 
2641
                }
 
2642
 
 
2643
                internal static jchar* GetStringChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
 
2644
                {
 
2645
                        string s = (string)pEnv->UnwrapRef(str);
 
2646
                        if(isCopy != null)
 
2647
                        {
 
2648
                                *isCopy = JNI_TRUE;
 
2649
                        }
 
2650
                        return (jchar*)(void*)Marshal.StringToHGlobalUni(s);
 
2651
                }
 
2652
 
 
2653
                internal static void ReleaseStringChars(JNIEnv* pEnv, jstring str, jchar* chars)
 
2654
                {
 
2655
                        Marshal.FreeHGlobal((IntPtr)(void*)chars);
 
2656
                }
 
2657
 
 
2658
                internal static jobject NewStringUTF(JNIEnv* pEnv, byte* psz)
 
2659
                {
 
2660
                        return pEnv->MakeLocalRef(StringFromUTF8(psz));
 
2661
                }
 
2662
 
 
2663
                internal static jint GetStringUTFLength(JNIEnv* pEnv, jstring str)
 
2664
                {
 
2665
                        return StringUTF8Length((string)pEnv->UnwrapRef(str));
 
2666
                }
 
2667
 
 
2668
                internal static byte* GetStringUTFChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
 
2669
                {
 
2670
                        string s = (string)pEnv->UnwrapRef(str);
 
2671
                        byte* buf = (byte*)JniMem.Alloc(StringUTF8Length(s) + 1);
 
2672
                        int j = 0;
 
2673
                        for(int i = 0; i < s.Length; i++)
 
2674
                        {
 
2675
                                char ch = s[i];
 
2676
                                if((ch != 0) && (ch <= 0x7F))
 
2677
                                {
 
2678
                                        buf[j++] = (byte)ch;
 
2679
                                }
 
2680
                                else if(ch <= 0x7FF)
 
2681
                                {
 
2682
                                        buf[j++] = (byte)((ch >> 6) | 0xC0);
 
2683
                                        buf[j++] = (byte)((ch & 0x3F) | 0x80);
 
2684
                                }
 
2685
                                else
 
2686
                                {
 
2687
                                        buf[j++] = (byte)((ch >> 12) | 0xE0);
 
2688
                                        buf[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80);
 
2689
                                        buf[j++] = (byte)((ch & 0x3F) | 0x80);
 
2690
                                }
 
2691
                        }
 
2692
                        buf[j] = 0;
 
2693
                        if(isCopy != null)
 
2694
                        {
 
2695
                                *isCopy = JNI_TRUE;
 
2696
                        }
 
2697
                        return buf;
 
2698
                }
 
2699
 
 
2700
                internal static void ReleaseStringUTFChars(JNIEnv* pEnv, jstring str, byte* chars)
 
2701
                {
 
2702
                        JniMem.Free((IntPtr)(void*)chars);
 
2703
                }
 
2704
 
 
2705
                internal static jsize GetArrayLength(JNIEnv* pEnv, jarray array)
 
2706
                {
 
2707
                        return ((Array)pEnv->UnwrapRef(array)).Length;
 
2708
                }
 
2709
 
 
2710
                internal static jobject NewObjectArray(JNIEnv* pEnv, jsize len, jclass clazz, jobject init)
 
2711
                {
 
2712
                        try
 
2713
                        {
 
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);
 
2717
                                if(o != null)
 
2718
                                {
 
2719
                                        for(int i = 0; i < array.Length; i++)
 
2720
                                        {
 
2721
                                                array.SetValue(o, i);
 
2722
                                        }
 
2723
                                }
 
2724
                                return pEnv->MakeLocalRef(array);
 
2725
                        }
 
2726
                        catch(ArgumentOutOfRangeException)
 
2727
                        {
 
2728
                                SetPendingException(pEnv, new java.lang.NegativeArraySizeException());
 
2729
                                return IntPtr.Zero;
 
2730
                        }
 
2731
                        catch(Exception x)
 
2732
                        {
 
2733
                                SetPendingException(pEnv, x);
 
2734
                                return IntPtr.Zero;
 
2735
                        }
 
2736
                }
 
2737
 
 
2738
                internal static jobject GetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index)
 
2739
                {
 
2740
                        try
 
2741
                        {
 
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));
 
2744
                        }
 
2745
                        catch(IndexOutOfRangeException)
 
2746
                        {
 
2747
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
2748
                                return IntPtr.Zero;
 
2749
                        }
 
2750
                }
 
2751
 
 
2752
                internal static void SetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index, jobject val)
 
2753
                {
 
2754
                        try
 
2755
                        {
 
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);
 
2758
                        }
 
2759
                        catch(IndexOutOfRangeException)
 
2760
                        {
 
2761
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
2762
                        }
 
2763
                }
 
2764
 
 
2765
                internal static jbooleanArray NewBooleanArray(JNIEnv* pEnv, jsize len)
 
2766
                {
 
2767
                        try
 
2768
                        {
 
2769
                                return pEnv->MakeLocalRef(new bool[len]);
 
2770
                        }
 
2771
                        catch(Exception x)
 
2772
                        {
 
2773
                                SetPendingException(pEnv, x);
 
2774
                                return IntPtr.Zero;
 
2775
                        }
 
2776
                }
 
2777
 
 
2778
                internal static jbyteArray NewByteArray(JNIEnv* pEnv, jsize len)
 
2779
                {
 
2780
                        try
 
2781
                        {
 
2782
                                return pEnv->MakeLocalRef(new byte[len]);
 
2783
                        }
 
2784
                        catch(Exception x)
 
2785
                        {
 
2786
                                SetPendingException(pEnv, x);
 
2787
                                return IntPtr.Zero;
 
2788
                        }
 
2789
                }
 
2790
 
 
2791
                internal static jcharArray NewCharArray(JNIEnv* pEnv, jsize len)
 
2792
                {
 
2793
                        try
 
2794
                        {
 
2795
                                return pEnv->MakeLocalRef(new char[len]);
 
2796
                        }
 
2797
                        catch(Exception x)
 
2798
                        {
 
2799
                                SetPendingException(pEnv, x);
 
2800
                                return IntPtr.Zero;
 
2801
                        }
 
2802
                }
 
2803
 
 
2804
                internal static jshortArray NewShortArray(JNIEnv* pEnv, jsize len)
 
2805
                {
 
2806
                        try
 
2807
                        {
 
2808
                                return pEnv->MakeLocalRef(new short[len]);
 
2809
                        }
 
2810
                        catch(Exception x)
 
2811
                        {
 
2812
                                SetPendingException(pEnv, x);
 
2813
                                return IntPtr.Zero;
 
2814
                        }
 
2815
                }
 
2816
 
 
2817
                internal static jintArray NewIntArray(JNIEnv* pEnv, jsize len)
 
2818
                {
 
2819
                        try
 
2820
                        {
 
2821
                                return pEnv->MakeLocalRef(new int[len]);
 
2822
                        }
 
2823
                        catch(Exception x)
 
2824
                        {
 
2825
                                SetPendingException(pEnv, x);
 
2826
                                return IntPtr.Zero;
 
2827
                        }
 
2828
                }
 
2829
 
 
2830
                internal static jlongArray NewLongArray(JNIEnv* pEnv, jsize len)
 
2831
                {
 
2832
                        try
 
2833
                        {
 
2834
                                return pEnv->MakeLocalRef(new long[len]);
 
2835
                        }
 
2836
                        catch(Exception x)
 
2837
                        {
 
2838
                                SetPendingException(pEnv, x);
 
2839
                                return IntPtr.Zero;
 
2840
                        }
 
2841
                }
 
2842
 
 
2843
                internal static jfloatArray NewFloatArray(JNIEnv* pEnv, jsize len)
 
2844
                {
 
2845
                        try
 
2846
                        {
 
2847
                                return pEnv->MakeLocalRef(new float[len]);
 
2848
                        }
 
2849
                        catch(Exception x)
 
2850
                        {
 
2851
                                SetPendingException(pEnv, x);
 
2852
                                return IntPtr.Zero;
 
2853
                        }
 
2854
                }
 
2855
 
 
2856
                internal static jdoubleArray NewDoubleArray(JNIEnv* pEnv, jsize len)
 
2857
                {
 
2858
                        try
 
2859
                        {
 
2860
                                return pEnv->MakeLocalRef(new double[len]);
 
2861
                        }
 
2862
                        catch(Exception x)
 
2863
                        {
 
2864
                                SetPendingException(pEnv, x);
 
2865
                                return IntPtr.Zero;
 
2866
                        }
 
2867
                }
 
2868
 
 
2869
                internal static jboolean* GetBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* isCopy)
 
2870
                {
 
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++)
 
2874
                        {
 
2875
                                p[i] = b[i] ? JNI_TRUE : JNI_FALSE;
 
2876
                        }
 
2877
                        if(isCopy != null)
 
2878
                        {
 
2879
                                *isCopy = JNI_TRUE;
 
2880
                        }
 
2881
                        return p;
 
2882
                }
 
2883
 
 
2884
                internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy)
 
2885
                {
 
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++)
 
2889
                        {
 
2890
                                p[i] = (jbyte)b[i];
 
2891
                        }
 
2892
                        if(isCopy != null)
 
2893
                        {
 
2894
                                *isCopy = JNI_TRUE;
 
2895
                        }
 
2896
                        return p;
 
2897
                }
 
2898
 
 
2899
                internal static jchar* GetCharArrayElements(JNIEnv* pEnv, jcharArray array, jboolean* isCopy)
 
2900
                {
 
2901
                        char[] b = (char[])pEnv->UnwrapRef(array);
 
2902
                        IntPtr buf = JniMem.Alloc(b.Length * 2);
 
2903
                        Marshal.Copy(b, 0, buf, b.Length);
 
2904
                        if(isCopy != null)
 
2905
                        {
 
2906
                                *isCopy = JNI_TRUE;
 
2907
                        }
 
2908
                        return (jchar*)(void*)buf;
 
2909
                }
 
2910
 
 
2911
                internal static jshort* GetShortArrayElements(JNIEnv* pEnv, jshortArray array, jboolean* isCopy)
 
2912
                {
 
2913
                        short[] b = (short[])pEnv->UnwrapRef(array);
 
2914
                        IntPtr buf = JniMem.Alloc(b.Length * 2);
 
2915
                        Marshal.Copy(b, 0, buf, b.Length);
 
2916
                        if(isCopy != null)
 
2917
                        {
 
2918
                                *isCopy = JNI_TRUE;
 
2919
                        }
 
2920
                        return (jshort*)(void*)buf;
 
2921
                }
 
2922
 
 
2923
                internal static jint* GetIntArrayElements(JNIEnv* pEnv, jintArray array, jboolean* isCopy)
 
2924
                {
 
2925
                        int[] b = (int[])pEnv->UnwrapRef(array);
 
2926
                        IntPtr buf = JniMem.Alloc(b.Length * 4);
 
2927
                        Marshal.Copy(b, 0, buf, b.Length);
 
2928
                        if(isCopy != null)
 
2929
                        {
 
2930
                                *isCopy = JNI_TRUE;
 
2931
                        }
 
2932
                        return (jint*)(void*)buf;
 
2933
                }
 
2934
 
 
2935
                internal static jlong* GetLongArrayElements(JNIEnv* pEnv, jlongArray array, jboolean* isCopy)
 
2936
                {
 
2937
                        long[] b = (long[])pEnv->UnwrapRef(array);
 
2938
                        IntPtr buf = JniMem.Alloc(b.Length * 8);
 
2939
                        Marshal.Copy(b, 0, buf, b.Length);
 
2940
                        if(isCopy != null)
 
2941
                        {
 
2942
                                *isCopy = JNI_TRUE;
 
2943
                        }
 
2944
                        return (jlong*)(void*)buf;
 
2945
                }
 
2946
 
 
2947
                internal static jfloat* GetFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jboolean* isCopy)
 
2948
                {
 
2949
                        float[] b = (float[])pEnv->UnwrapRef(array);
 
2950
                        IntPtr buf = JniMem.Alloc(b.Length * 4);
 
2951
                        Marshal.Copy(b, 0, buf, b.Length);
 
2952
                        if(isCopy != null)
 
2953
                        {
 
2954
                                *isCopy = JNI_TRUE;
 
2955
                        }
 
2956
                        return (jfloat*)(void*)buf;
 
2957
                }
 
2958
 
 
2959
                internal static jdouble* GetDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jboolean* isCopy)
 
2960
                {
 
2961
                        double[] b = (double[])pEnv->UnwrapRef(array);
 
2962
                        IntPtr buf = JniMem.Alloc(b.Length * 8);
 
2963
                        Marshal.Copy(b, 0, buf, b.Length);
 
2964
                        if(isCopy != null)
 
2965
                        {
 
2966
                                *isCopy = JNI_TRUE;
 
2967
                        }
 
2968
                        return (jdouble*)(void*)buf;
 
2969
                }
 
2970
 
 
2971
                internal static void ReleaseBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* elems, jint mode)
 
2972
                {
 
2973
                        if(mode == 0 || mode == JNI_COMMIT)
 
2974
                        {
 
2975
                                bool[] b = (bool[])pEnv->UnwrapRef(array);
 
2976
                                for(int i = 0; i < b.Length; i++)
 
2977
                                {
 
2978
                                        b[i] = elems[i] != JNI_FALSE;
 
2979
                                }
 
2980
                        }
 
2981
                        if(mode == 0 || mode == JNI_ABORT)
 
2982
                        {
 
2983
                                JniMem.Free((IntPtr)(void*)elems);
 
2984
                        }
 
2985
                }
 
2986
 
 
2987
                internal static void ReleaseByteArrayElements(JNIEnv* pEnv, jbyteArray array, jbyte* elems, jint mode)
 
2988
                {
 
2989
                        if(mode == 0 || mode == JNI_COMMIT)
 
2990
                        {
 
2991
                                byte[] b = (byte[])pEnv->UnwrapRef(array);
 
2992
                                for(int i = 0; i < b.Length; i++)
 
2993
                                {
 
2994
                                        b[i] = (byte)elems[i];
 
2995
                                }
 
2996
                        }
 
2997
                        if(mode == 0 || mode == JNI_ABORT)
 
2998
                        {
 
2999
                                JniMem.Free((IntPtr)(void*)elems);
 
3000
                        }
 
3001
                }
 
3002
 
 
3003
                internal static void ReleaseCharArrayElements(JNIEnv* pEnv, jcharArray array, jchar* elems, jint mode)
 
3004
                {
 
3005
                        if(mode == 0 || mode == JNI_COMMIT)
 
3006
                        {
 
3007
                                char[] b = (char[])pEnv->UnwrapRef(array);
 
3008
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3009
                        }
 
3010
                        if(mode == 0 || mode == JNI_ABORT)
 
3011
                        {
 
3012
                                JniMem.Free((IntPtr)(void*)elems);
 
3013
                        }
 
3014
                }
 
3015
 
 
3016
                internal static void ReleaseShortArrayElements(JNIEnv* pEnv, jshortArray array, jshort* elems, jint mode)
 
3017
                {
 
3018
                        if(mode == 0 || mode == JNI_COMMIT)
 
3019
                        {
 
3020
                                short[] b = (short[])pEnv->UnwrapRef(array);
 
3021
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3022
                        }
 
3023
                        if(mode == 0 || mode == JNI_ABORT)
 
3024
                        {
 
3025
                                JniMem.Free((IntPtr)(void*)elems);
 
3026
                        }
 
3027
                }
 
3028
 
 
3029
                internal static void ReleaseIntArrayElements(JNIEnv* pEnv, jintArray array, jint* elems, jint mode)
 
3030
                {
 
3031
                        if(mode == 0 || mode == JNI_COMMIT)
 
3032
                        {
 
3033
                                int[] b = (int[])pEnv->UnwrapRef(array);
 
3034
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3035
                        }
 
3036
                        if(mode == 0 || mode == JNI_ABORT)
 
3037
                        {
 
3038
                                JniMem.Free((IntPtr)(void*)elems);
 
3039
                        }
 
3040
                }
 
3041
 
 
3042
                internal static void ReleaseLongArrayElements(JNIEnv* pEnv, jlongArray array, jlong* elems, jint mode)
 
3043
                {
 
3044
                        if(mode == 0 || mode == JNI_COMMIT)
 
3045
                        {
 
3046
                                long[] b = (long[])pEnv->UnwrapRef(array);
 
3047
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3048
                        }
 
3049
                        if(mode == 0 || mode == JNI_ABORT)
 
3050
                        {
 
3051
                                JniMem.Free((IntPtr)(void*)elems);
 
3052
                        }
 
3053
                }
 
3054
 
 
3055
                internal static void ReleaseFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jfloat* elems, jint mode)
 
3056
                {
 
3057
                        if(mode == 0 || mode == JNI_COMMIT)
 
3058
                        {
 
3059
                                float[] b = (float[])pEnv->UnwrapRef(array);
 
3060
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3061
                        }
 
3062
                        if(mode == 0 || mode == JNI_ABORT)
 
3063
                        {
 
3064
                                JniMem.Free((IntPtr)(void*)elems);
 
3065
                        }
 
3066
                }
 
3067
 
 
3068
                internal static void ReleaseDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jdouble* elems, jint mode)
 
3069
                {
 
3070
                        if(mode == 0 || mode == JNI_COMMIT)
 
3071
                        {
 
3072
                                double[] b = (double[])pEnv->UnwrapRef(array);
 
3073
                                Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
 
3074
                        }
 
3075
                        if(mode == 0 || mode == JNI_ABORT)
 
3076
                        {
 
3077
                                JniMem.Free((IntPtr)(void*)elems);
 
3078
                        }
 
3079
                }
 
3080
 
 
3081
                internal static void GetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3082
                {
 
3083
                        try
 
3084
                        {
 
3085
                                bool[] b = (bool[])pEnv->UnwrapRef(array);
 
3086
                                sbyte* p = (sbyte*)(void*)buf;
 
3087
                                for(int i = 0; i < len; i++)
 
3088
                                {
 
3089
                                        *p++ = b[start + i] ? JNI_TRUE : JNI_FALSE;
 
3090
                                }
 
3091
                        }
 
3092
                        catch(IndexOutOfRangeException)
 
3093
                        {
 
3094
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3095
                        }
 
3096
                }
 
3097
 
 
3098
                internal static void GetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3099
                {
 
3100
                        try
 
3101
                        {
 
3102
                                byte[] b = (byte[])pEnv->UnwrapRef(array);
 
3103
                                byte* p = (byte*)(void*)buf;
 
3104
                                for(int i = 0; i < len; i++)
 
3105
                                {
 
3106
                                        *p++ = b[start + i];
 
3107
                                }
 
3108
                        }
 
3109
                        catch(IndexOutOfRangeException)
 
3110
                        {
 
3111
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3112
                        }
 
3113
                }
 
3114
 
 
3115
                internal static void GetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3116
                {
 
3117
                        try
 
3118
                        {
 
3119
                                char[] b = (char[])pEnv->UnwrapRef(array);
 
3120
                                Marshal.Copy(b, start, buf, len);
 
3121
                        }
 
3122
                        catch(ArgumentOutOfRangeException)
 
3123
                        {
 
3124
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3125
                        }
 
3126
                }
 
3127
 
 
3128
                internal static void GetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3129
                {
 
3130
                        try
 
3131
                        {
 
3132
                                short[] b = (short[])pEnv->UnwrapRef(array);
 
3133
                                Marshal.Copy(b, start, buf, len);
 
3134
                        }
 
3135
                        catch(ArgumentOutOfRangeException)
 
3136
                        {
 
3137
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3138
                        }
 
3139
                }
 
3140
 
 
3141
                internal static void GetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3142
                {
 
3143
                        try
 
3144
                        {
 
3145
                                int[] b = (int[])pEnv->UnwrapRef(array);
 
3146
                                Marshal.Copy(b, start, buf, len);
 
3147
                        }
 
3148
                        catch(ArgumentOutOfRangeException)
 
3149
                        {
 
3150
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3151
                        }
 
3152
                }
 
3153
 
 
3154
                internal static void GetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3155
                {
 
3156
                        try
 
3157
                        {
 
3158
                                long[] b = (long[])pEnv->UnwrapRef(array);
 
3159
                                Marshal.Copy(b, start, buf, len);
 
3160
                        }
 
3161
                        catch(ArgumentOutOfRangeException)
 
3162
                        {
 
3163
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3164
                        }
 
3165
                }
 
3166
 
 
3167
                internal static void GetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3168
                {
 
3169
                        try
 
3170
                        {
 
3171
                                float[] b = (float[])pEnv->UnwrapRef(array);
 
3172
                                Marshal.Copy(b, start, buf, len);
 
3173
                        }
 
3174
                        catch(ArgumentOutOfRangeException)
 
3175
                        {
 
3176
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3177
                        }
 
3178
                }
 
3179
 
 
3180
                internal static void GetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3181
                {
 
3182
                        try
 
3183
                        {
 
3184
                                double[] b = (double[])pEnv->UnwrapRef(array);
 
3185
                                Marshal.Copy(b, start, buf, len);
 
3186
                        }
 
3187
                        catch(ArgumentOutOfRangeException)
 
3188
                        {
 
3189
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3190
                        }
 
3191
                }
 
3192
 
 
3193
                internal static void SetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3194
                {
 
3195
                        try
 
3196
                        {
 
3197
                                bool[] b = (bool[])pEnv->UnwrapRef(array);
 
3198
                                sbyte* p = (sbyte*)(void*)buf;
 
3199
                                for(int i = 0; i < len; i++)
 
3200
                                {
 
3201
                                        b[start + i] = *p++ != JNI_FALSE;
 
3202
                                }
 
3203
                        }
 
3204
                        catch(IndexOutOfRangeException)
 
3205
                        {
 
3206
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3207
                        }
 
3208
                }
 
3209
 
 
3210
                internal static void SetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3211
                {
 
3212
                        try
 
3213
                        {
 
3214
                                byte[] b = (byte[])pEnv->UnwrapRef(array);
 
3215
                                byte* p = (byte*)(void*)buf;
 
3216
                                for(int i = 0; i < len; i++)
 
3217
                                {
 
3218
                                        b[start + i] = *p++;
 
3219
                                }
 
3220
                        }
 
3221
                        catch(IndexOutOfRangeException)
 
3222
                        {
 
3223
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3224
                        }
 
3225
                }
 
3226
 
 
3227
                internal static void SetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3228
                {
 
3229
                        try
 
3230
                        {
 
3231
                                char[] b = (char[])pEnv->UnwrapRef(array);
 
3232
                                Marshal.Copy(buf, b, start, len);
 
3233
                        }
 
3234
                        catch(ArgumentOutOfRangeException)
 
3235
                        {
 
3236
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3237
                        }
 
3238
                }
 
3239
 
 
3240
                internal static void SetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3241
                {
 
3242
                        try
 
3243
                        {
 
3244
                                short[] b = (short[])pEnv->UnwrapRef(array);
 
3245
                                Marshal.Copy(buf, b, start, len);
 
3246
                        }
 
3247
                        catch(ArgumentOutOfRangeException)
 
3248
                        {
 
3249
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3250
                        }
 
3251
                }
 
3252
 
 
3253
                internal static void SetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3254
                {
 
3255
                        try
 
3256
                        {
 
3257
                                int[] b = (int[])pEnv->UnwrapRef(array);
 
3258
                                Marshal.Copy(buf, b, start, len);
 
3259
                        }
 
3260
                        catch(ArgumentOutOfRangeException)
 
3261
                        {
 
3262
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3263
                        }
 
3264
                }
 
3265
 
 
3266
                internal static void SetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3267
                {
 
3268
                        try
 
3269
                        {
 
3270
                                long[] b = (long[])pEnv->UnwrapRef(array);
 
3271
                                Marshal.Copy(buf, b, start, len);
 
3272
                        }
 
3273
                        catch(ArgumentOutOfRangeException)
 
3274
                        {
 
3275
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3276
                        }
 
3277
                }
 
3278
 
 
3279
                internal static void SetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3280
                {
 
3281
                        try
 
3282
                        {
 
3283
                                float[] b = (float[])pEnv->UnwrapRef(array);
 
3284
                                Marshal.Copy(buf, b, start, len);
 
3285
                        }
 
3286
                        catch(ArgumentOutOfRangeException)
 
3287
                        {
 
3288
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3289
                        }
 
3290
                }
 
3291
 
 
3292
                internal static void SetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
 
3293
                {
 
3294
                        try
 
3295
                        {
 
3296
                                double[] b = (double[])pEnv->UnwrapRef(array);
 
3297
                                Marshal.Copy(buf, b, start, len);
 
3298
                        }
 
3299
                        catch(ArgumentOutOfRangeException)
 
3300
                        {
 
3301
                                SetPendingException(pEnv, new java.lang.ArrayIndexOutOfBoundsException());
 
3302
                        }
 
3303
                }
 
3304
 
 
3305
                [StructLayout(LayoutKind.Sequential)]
 
3306
                unsafe internal struct JNINativeMethod
 
3307
                {
 
3308
                        public byte* name;
 
3309
                        public byte* signature;
 
3310
                        public void* fnPtr;
 
3311
                }
 
3312
 
 
3313
                internal static int RegisterNatives(JNIEnv* pEnv, IntPtr clazz, JNINativeMethod* methods, int nMethods)
 
3314
                {
 
3315
                        try
 
3316
                        {
 
3317
                                TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
 
3318
                                wrapper.Finish();
 
3319
                                for(int i = 0; i < nMethods; i++)
 
3320
                                {
 
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)
 
3327
                                        {
 
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);
 
3330
                                        }
 
3331
                                        if(fi == null)
 
3332
                                        {
 
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));
 
3335
                                                return JNI_ERR;
 
3336
                                        }
 
3337
                                        fi.SetValue(null, (IntPtr)methods[i].fnPtr);
 
3338
                                }
 
3339
                                return JNI_OK;
 
3340
                        }
 
3341
                        catch(RetargetableJavaException x)
 
3342
                        {
 
3343
                                SetPendingException(pEnv, x.ToJava());
 
3344
                                return JNI_ERR;
 
3345
                        }
 
3346
                        catch(Exception x)
 
3347
                        {
 
3348
                                SetPendingException(pEnv, x);
 
3349
                                return JNI_ERR;
 
3350
                        }
 
3351
                }
 
3352
 
 
3353
                internal static int UnregisterNatives(JNIEnv* pEnv, IntPtr clazz)
 
3354
                {
 
3355
                        try
 
3356
                        {
 
3357
                                TypeWrapper wrapper = TypeWrapper.FromClass((java.lang.Class)pEnv->UnwrapRef(clazz));
 
3358
                                wrapper.Finish();
 
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))
 
3361
                                {
 
3362
                                        string name = fi.Name;
 
3363
                                        if(name.StartsWith(JNI.METHOD_PTR_FIELD_PREFIX))
 
3364
                                        {
 
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);
 
3367
                                        }
 
3368
                                }
 
3369
                                return JNI_OK;
 
3370
                        }
 
3371
                        catch(RetargetableJavaException x)
 
3372
                        {
 
3373
                                SetPendingException(pEnv, x.ToJava());
 
3374
                                return JNI_ERR;
 
3375
                        }
 
3376
                        catch(Exception x)
 
3377
                        {
 
3378
                                SetPendingException(pEnv, x);
 
3379
                                return JNI_ERR;
 
3380
                        }
 
3381
                }
 
3382
 
 
3383
                internal static int MonitorEnter(JNIEnv* pEnv, IntPtr obj)
 
3384
                {
 
3385
                        try
 
3386
                        {
 
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
 
3392
                                return JNI_OK;
 
3393
                        }
 
3394
                        catch(Exception x)
 
3395
                        {
 
3396
                                SetPendingException(pEnv, x);
 
3397
                                return JNI_ERR;
 
3398
                        }
 
3399
                }
 
3400
 
 
3401
                internal static int MonitorExit(JNIEnv* pEnv, IntPtr obj)
 
3402
                {
 
3403
                        try
 
3404
                        {
 
3405
                                System.Threading.Monitor.Exit(pEnv->UnwrapRef(obj));
 
3406
                                return JNI_OK;
 
3407
                        }
 
3408
                        catch(Exception x)
 
3409
                        {
 
3410
                                SetPendingException(pEnv, x);
 
3411
                                return JNI_ERR;
 
3412
                        }
 
3413
                }
 
3414
 
 
3415
                internal static int GetJavaVM(JNIEnv* pEnv, JavaVM **ppJavaVM)
 
3416
                {
 
3417
                        *ppJavaVM = JavaVM.pJavaVM;
 
3418
                        return JNI_OK;
 
3419
                }
 
3420
 
 
3421
                internal static void GetStringRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
 
3422
                {
 
3423
                        string s = (string)pEnv->UnwrapRef(str);
 
3424
                        if(s != null)
 
3425
                        {
 
3426
                                if(start < 0 || start > s.Length || s.Length - start < len)
 
3427
                                {
 
3428
                                        SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException());
 
3429
                                        return;
 
3430
                                }
 
3431
                                else
 
3432
                                {
 
3433
                                        char* p = (char*)(void*)buf;
 
3434
                                        // TODO isn't there a managed memcpy?
 
3435
                                        for(int i = 0; i < len; i++)
 
3436
                                        {
 
3437
                                                *p++ = s[start + i];
 
3438
                                        }
 
3439
                                        return;
 
3440
                                }
 
3441
                        }
 
3442
                        else
 
3443
                        {
 
3444
                                SetPendingException(pEnv, new java.lang.NullPointerException());
 
3445
                        }
 
3446
                }
 
3447
 
 
3448
                internal static void GetStringUTFRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
 
3449
                {
 
3450
                        string s = (string)pEnv->UnwrapRef(str);
 
3451
                        if(s != null)
 
3452
                        {
 
3453
                                if(start < 0 || start > s.Length || s.Length - start < len)
 
3454
                                {
 
3455
                                        SetPendingException(pEnv, new java.lang.StringIndexOutOfBoundsException());
 
3456
                                        return;
 
3457
                                }
 
3458
                                else
 
3459
                                {
 
3460
                                        byte* p = (byte*)(void*)buf;
 
3461
                                        for(int i = 0; i < len; i++)
 
3462
                                        {
 
3463
                                                char ch = s[start + i];
 
3464
                                                if((ch != 0) && (ch <= 0x7F))
 
3465
                                                {
 
3466
                                                        *p++ = (byte)ch;
 
3467
                                                }
 
3468
                                                else if(ch <= 0x7FF)
 
3469
                                                {
 
3470
                                                        *p++ = (byte)((ch >> 6) | 0xC0);
 
3471
                                                        *p++ = (byte)((ch & 0x3F) | 0x80);
 
3472
                                                }
 
3473
                                                else
 
3474
                                                {
 
3475
                                                        *p++ = (byte)((ch >> 12) | 0xE0);
 
3476
                                                        *p++ = (byte)(((ch >> 6) & 0x3F) | 0x80);
 
3477
                                                        *p++ = (byte)((ch & 0x3F) | 0x80);
 
3478
                                                }
 
3479
                                        }
 
3480
                                        return;
 
3481
                                }
 
3482
                        }
 
3483
                        else
 
3484
                        {
 
3485
                                SetPendingException(pEnv, new java.lang.NullPointerException());
 
3486
                        }
 
3487
                }
 
3488
 
 
3489
                private void* PinObject(object obj)
 
3490
                {
 
3491
                        if(pinHandleInUseCount == pinHandleMaxCount)
 
3492
                        {
 
3493
                                int newCount = pinHandleMaxCount + 32;
 
3494
                                GCHandle* pNew = (GCHandle*)JniMem.Alloc(sizeof(GCHandle) * newCount);
 
3495
                                for(int i = 0; i < pinHandleMaxCount; i++)
 
3496
                                {
 
3497
                                        pNew[i] = pinHandles[i];
 
3498
                                }
 
3499
                                for(int i = pinHandleMaxCount; i < newCount; i++)
 
3500
                                {
 
3501
                                        pNew[i] = new GCHandle();
 
3502
                                }
 
3503
                                JniMem.Free((IntPtr)pinHandles);
 
3504
                                pinHandles = pNew;
 
3505
                                pinHandleMaxCount = newCount;
 
3506
                        }
 
3507
                        int index = pinHandleInUseCount++;
 
3508
                        if(!pinHandles[index].IsAllocated)
 
3509
                        {
 
3510
                                pinHandles[index] = GCHandle.Alloc(null, GCHandleType.Pinned);
 
3511
                        }
 
3512
                        pinHandles[index].Target = obj;
 
3513
                        return (void*)pinHandles[index].AddrOfPinnedObject();
 
3514
                }
 
3515
 
 
3516
                private void UnpinObject(object obj)
 
3517
                {
 
3518
                        for(int i = 0; i < pinHandleInUseCount; i++)
 
3519
                        {
 
3520
                                if(pinHandles[i].Target == obj)
 
3521
                                {
 
3522
                                        pinHandles[i].Target = pinHandles[--pinHandleInUseCount].Target;
 
3523
                                        pinHandles[pinHandleInUseCount].Target = null;
 
3524
                                        return;
 
3525
                                }
 
3526
                        }
 
3527
                }
 
3528
 
 
3529
                internal static void* GetPrimitiveArrayCritical(JNIEnv* pEnv, jarray array, jboolean* isCopy)
 
3530
                {
 
3531
                        if(isCopy != null)
 
3532
                        {
 
3533
                                *isCopy = JNI_FALSE;
 
3534
                        }
 
3535
                        return pEnv->PinObject(pEnv->UnwrapRef(array));
 
3536
                }
 
3537
 
 
3538
                internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, jarray array, void* carray, jint mode)
 
3539
                {
 
3540
                        pEnv->UnpinObject(pEnv->UnwrapRef(array));
 
3541
                }
 
3542
 
 
3543
                internal static jchar* GetStringCritical(JNIEnv* pEnv, jstring str, jboolean* isCopy)
 
3544
                {
 
3545
                        if(isCopy != null)
 
3546
                        {
 
3547
                                *isCopy = JNI_FALSE;
 
3548
                        }
 
3549
                        return (jchar*)pEnv->PinObject(pEnv->UnwrapRef(str));
 
3550
                }
 
3551
 
 
3552
                internal static void ReleaseStringCritical(JNIEnv* pEnv, jstring str, jchar* cstring)
 
3553
                {
 
3554
                        pEnv->UnpinObject(pEnv->UnwrapRef(str));
 
3555
                }
 
3556
 
 
3557
                internal static jweak NewWeakGlobalRef(JNIEnv* pEnv, jobject obj)
 
3558
                {
 
3559
                        object o = pEnv->UnwrapRef(obj);
 
3560
                        if(o == null)
 
3561
                        {
 
3562
                                return IntPtr.Zero;
 
3563
                        }
 
3564
                        lock(GlobalRefs.weakRefLock)
 
3565
                        {
 
3566
                                for(int i = 0; i < GlobalRefs.weakRefs.Length; i++)
 
3567
                                {
 
3568
                                        if(!GlobalRefs.weakRefs[i].IsAllocated)
 
3569
                                        {
 
3570
                                                GlobalRefs.weakRefs[i] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
 
3571
                                                return (IntPtr)(- (i | (1 << 30)));
 
3572
                                        }
 
3573
                                }
 
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)));
 
3580
                        }
 
3581
                }
 
3582
 
 
3583
                internal static void DeleteWeakGlobalRef(JNIEnv* pEnv, jweak obj)
 
3584
                {
 
3585
                        int i = obj.ToInt32();
 
3586
                        if(i < 0)
 
3587
                        {
 
3588
                                i = -i;
 
3589
                                i -= (1 << 30);
 
3590
                                lock(GlobalRefs.weakRefLock)
 
3591
                                {
 
3592
                                        GlobalRefs.weakRefs[i].Free();
 
3593
                                }
 
3594
                        }
 
3595
                        if(i > 0)
 
3596
                        {
 
3597
                                Debug.Assert(false, "local ref passed to DeleteWeakGlobalRef");
 
3598
                        }
 
3599
                }
 
3600
 
 
3601
                internal static jboolean ExceptionCheck(JNIEnv* pEnv)
 
3602
                {
 
3603
                        ManagedJNIEnv env = pEnv->GetManagedJNIEnv();
 
3604
                        return env.pendingException != null ? JNI_TRUE : JNI_FALSE;
 
3605
                }
 
3606
 
 
3607
                internal static jobject NewDirectByteBuffer(JNIEnv* pEnv, IntPtr address, jlong capacity)
 
3608
                {
 
3609
                        try
 
3610
                        {
 
3611
                                if(capacity < 0 || capacity > int.MaxValue)
 
3612
                                {
 
3613
                                        SetPendingException(pEnv, new java.lang.IllegalArgumentException("capacity"));
 
3614
                                        return IntPtr.Zero;
 
3615
                                }
 
3616
                                return pEnv->MakeLocalRef(JVM.NewDirectByteBuffer(address.ToInt64(), (int)capacity));
 
3617
                        }
 
3618
                        catch(Exception x)
 
3619
                        {
 
3620
                                SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
 
3621
                                return IntPtr.Zero;
 
3622
                        }
 
3623
                }
 
3624
 
 
3625
                internal static IntPtr GetDirectBufferAddress(JNIEnv* pEnv, jobject buf)
 
3626
                {
 
3627
                        try
 
3628
                        {
 
3629
                                return (IntPtr)((sun.nio.ch.DirectBuffer)pEnv->UnwrapRef(buf)).address();
 
3630
                        }
 
3631
                        catch(Exception x)
 
3632
                        {
 
3633
                                SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
 
3634
                                return IntPtr.Zero;
 
3635
                        }
 
3636
                }
 
3637
                
 
3638
                internal static jlong GetDirectBufferCapacity(JNIEnv* pEnv, jobject buf)
 
3639
                {
 
3640
                        try
 
3641
                        {
 
3642
                                return (jlong)(long)((java.nio.Buffer)pEnv->UnwrapRef(buf)).capacity();
 
3643
                        }
 
3644
                        catch(Exception x)
 
3645
                        {
 
3646
                                SetPendingException(pEnv, ikvm.runtime.Util.mapException(x));
 
3647
                                return 0;
 
3648
                        }
 
3649
                }
 
3650
 
 
3651
                internal static int GetObjectRefType(JNIEnv* pEnv, jobject obj)
 
3652
                {
 
3653
                        int i = obj.ToInt32();
 
3654
                        if(i >= 0)
 
3655
                        {
 
3656
                                return JNILocalRefType;
 
3657
                        }
 
3658
                        i = -i;
 
3659
                        if((i & (1 << 30)) != 0)
 
3660
                        {
 
3661
                                return JNIWeakGlobalRefType;
 
3662
                        }
 
3663
                        else
 
3664
                        {
 
3665
                                return JNIGlobalRefType;
 
3666
                        }
 
3667
                }
 
3668
 
 
3669
                internal IntPtr MakeLocalRef(object obj)
 
3670
                {
 
3671
                        return GetManagedJNIEnv().MakeLocalRef(obj);
 
3672
                }
 
3673
 
 
3674
                internal object UnwrapRef(IntPtr o)
 
3675
                {
 
3676
                        int i = o.ToInt32();
 
3677
                        if(i > 0)
 
3678
                        {
 
3679
                                return GetManagedJNIEnv().UnwrapLocalRef(i);
 
3680
                        }
 
3681
                        if(i < 0)
 
3682
                        {
 
3683
                                return GlobalRefs.Unwrap(i);
 
3684
                        }
 
3685
                        return null;
 
3686
                }
 
3687
 
 
3688
                internal static object UnwrapRef(ManagedJNIEnv env, IntPtr o)
 
3689
                {
 
3690
                        int i = o.ToInt32();
 
3691
                        if(i > 0)
 
3692
                        {
 
3693
                                return env.UnwrapLocalRef(i);
 
3694
                        }
 
3695
                        if(i < 0)
 
3696
                        {
 
3697
                                return GlobalRefs.Unwrap(i);
 
3698
                        }
 
3699
                        return null;
 
3700
                }
 
3701
        }
 
3702
 
 
3703
        static class JniMem
 
3704
        {
 
3705
                internal static IntPtr Alloc(int cb)
 
3706
                {
 
3707
                        return Marshal.AllocHGlobal(cb);
 
3708
                }
 
3709
 
 
3710
                internal static void Free(IntPtr p)
 
3711
                {
 
3712
                        Marshal.FreeHGlobal(p);
 
3713
                }
 
3714
        }
 
3715
 
 
3716
        static class TlsHack
 
3717
        {
 
3718
                [ThreadStatic]
 
3719
                internal static JNIEnv.ManagedJNIEnv ManagedJNIEnv;
 
3720
        }
 
3721
}