OSDN Git Service

* include/jni.h (class _Jv_JNIEnv): Added all C++ inline methods.
[pf3gnuchains/gcc-fork.git] / libjava / jni.cc
1 // jni.cc - JNI implementation, including the jump table.
2
3 /* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 // Note: currently we take the approach of not checking most
12 // arguments.  Instead we could do more checking conditionally (e.g.,
13 // if DEBUG is defined).  That might be beneficial in some cases,
14 // though to me it seems that one could just as easily use the
15 // debugger.
16
17 #include <config.h>
18
19 #include <stddef.h>
20 #include <string.h>
21
22 // Define this before including jni.h.
23 #define __GCJ_JNI_IMPL__
24
25 #include <gcj/cni.h>
26 #include <jvm.h>
27 #include <java-assert.h>
28 #include <jni.h>
29
30 #include <java/lang/Class.h>
31 #include <java/lang/ClassLoader.h>
32 #include <java/lang/Throwable.h>
33 #include <java/lang/ArrayIndexOutOfBoundsException.h>
34 #include <java/lang/StringIndexOutOfBoundsException.h>
35 #include <java/lang/InstantiationException.h>
36 #include <java/lang/NoSuchFieldError.h>
37 #include <java/lang/NoSuchMethodError.h>
38 #include <java/lang/reflect/Constructor.h>
39 #include <java/lang/reflect/Method.h>
40 #include <java/lang/reflect/Modifier.h>
41 #include <java/lang/OutOfMemoryError.h>
42 #include <java/util/Hashtable.h>
43 #include <java/lang/Integer.h>
44
45 #include <gcj/method.h>
46 #include <gcj/field.h>
47
48 #define ClassClass _CL_Q34java4lang5Class
49 extern java::lang::Class ClassClass;
50 #define ObjectClass _CL_Q34java4lang6Object
51 extern java::lang::Class ObjectClass;
52
53 #define MethodClass _CL_Q44java4lang7reflect6Method
54 extern java::lang::Class MethodClass;
55
56 // This enum is used to select different template instantiations in
57 // the invocation code.
58 enum invocation_type
59 {
60   normal,
61   nonvirtual,
62   static_type,
63   constructor
64 };
65
66 // Forward declaration.
67 extern struct JNINativeInterface _Jv_JNIFunctions;
68
69 // Number of slots in the default frame.  The VM must allow at least
70 // 16.
71 #define FRAME_SIZE 32
72
73 // This structure is used to keep track of local references.
74 struct _Jv_JNI_LocalFrame
75 {
76   // This is true if this frame object represents a pushed frame (eg
77   // from PushLocalFrame).
78   int marker :  1;
79
80   // Number of elements in frame.
81   int size   : 31;
82
83   // Next frame in chain.
84   _Jv_JNI_LocalFrame *next;
85
86   // The elements.  These are allocated using the C "struct hack".
87   jobject vec[0];
88 };
89
90 // This holds a reference count for all local and global references.
91 static java::util::Hashtable *ref_table;
92
93 \f
94
95 void
96 _Jv_JNI_Init (void)
97 {
98   ref_table = new java::util::Hashtable;
99 }
100
101 // Tell the GC that a certain pointer is live.
102 static void
103 mark_for_gc (jobject obj)
104 {
105   JvSynchronize sync (ref_table);
106
107   using namespace java::lang;
108   Integer *refcount = (Integer *) ref_table->get (obj);
109   jint val = (refcount == NULL) ? 0 : refcount->intValue ();
110   ref_table->put (obj, new Integer (val + 1));
111 }
112
113 // Unmark a pointer.
114 static void
115 unmark_for_gc (jobject obj)
116 {
117   JvSynchronize sync (ref_table);
118
119   using namespace java::lang;
120   Integer *refcount = (Integer *) ref_table->get (obj);
121   JvAssert (refcount);
122   jint val = refcount->intValue () - 1;
123   if (val == 0)
124     ref_table->remove (obj);
125   else
126     ref_table->put (obj, new Integer (val));
127 }
128
129 \f
130
131 static jobject
132 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
133 {
134   mark_for_gc (obj);
135   return obj;
136 }
137
138 static void
139 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
140 {
141   unmark_for_gc (obj);
142 }
143
144 static void
145 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
146 {
147   _Jv_JNI_LocalFrame *frame;
148
149   for (frame = env->locals; frame != NULL; frame = frame->next)
150     {
151       for (int i = 0; i < FRAME_SIZE; ++i)
152         {
153           if (frame->vec[i] == obj)
154             {
155               frame->vec[i] = NULL;
156               unmark_for_gc (obj);
157               return;
158             }
159         }
160
161       // Don't go past a marked frame.
162       JvAssert (! frame->marker);
163     }
164
165   JvAssert (0);
166 }
167
168 static jint
169 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
170 {
171   // It is easier to just always allocate a new frame of the requested
172   // size.  This isn't the most efficient thing, but for now we don't
173   // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
174
175   _Jv_JNI_LocalFrame *frame
176     = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
177                                                   + size * sizeof (jobject));
178   if (frame == NULL)
179     {
180       // FIXME: exception processing.
181       env->ex = new java::lang::OutOfMemoryError;
182       return -1;
183     }
184
185   frame->marker = true;
186   frame->size = size;
187   memset (&frame->vec[0], 0, size * sizeof (jobject));
188   frame->next = env->locals;
189   env->locals = frame;
190
191   return 0;
192 }
193
194 static jint
195 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
196 {
197   jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
198   if (r < 0)
199     return r;
200
201   // The new frame is on top.
202   env->locals->marker = true;
203
204   return 0;
205 }
206
207 static jobject
208 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
209 {
210   // Try to find an open slot somewhere in the topmost frame.
211   _Jv_JNI_LocalFrame *frame = env->locals;
212   bool done = false, set = false;
213   while (frame != NULL && ! done)
214     {
215       for (int i = 0; i < frame->size; ++i)
216         if (frame->vec[i] == NULL)
217           {
218             set = true;
219             done = true;
220             frame->vec[i] = obj;
221             break;
222           }
223     }
224
225   if (! set)
226     {
227       // No slots, so we allocate a new frame.  According to the spec
228       // we could just die here.  FIXME: return value.
229       _Jv_JNI_EnsureLocalCapacity (env, 16);
230       // We know the first element of the new frame will be ok.
231       env->locals->vec[0] = obj;
232     }
233
234   mark_for_gc (obj);
235   return obj;
236 }
237
238 static jobject
239 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
240 {
241   _Jv_JNI_LocalFrame *rf = env->locals;
242
243   bool done = false;
244   while (rf != NULL && ! done)
245     {  
246       for (int i = 0; i < rf->size; ++i)
247         if (rf->vec[i] != NULL)
248           unmark_for_gc (rf->vec[i]);
249
250       // If the frame we just freed is the marker frame, we are done.
251       done = rf->marker;
252
253       _Jv_JNI_LocalFrame *n = rf->next;
254       // When N==NULL, we've reached the stack-allocated frame, and we
255       // must not free it.  However, we must be sure to clear all its
256       // elements, since we might conceivably reuse it.
257       if (n == NULL)
258         {
259           memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
260           break;
261         }
262
263       _Jv_Free (rf);
264       rf = n;
265     }
266
267   return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
268 }
269
270 // This function is used from other template functions.  It wraps the
271 // return value appropriately; we specialize it so that object returns
272 // are turned into local references.
273 template<typename T>
274 static T
275 wrap_value (JNIEnv *, T value)
276 {
277   return value;
278 }
279
280 template<>
281 static jobject
282 wrap_value (JNIEnv *env, jobject value)
283 {
284   return _Jv_JNI_NewLocalRef (env, value);
285 }
286
287 \f
288
289 static jint
290 _Jv_JNI_GetVersion (JNIEnv *)
291 {
292   return JNI_VERSION_1_2;
293 }
294
295 static jclass
296 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader, 
297                      const jbyte *buf, jsize bufLen)
298 {
299   jbyteArray bytes = JvNewByteArray (bufLen);
300   jbyte *elts = elements (bytes);
301   memcpy (elts, buf, bufLen * sizeof (jbyte));
302
303   java::lang::ClassLoader *l
304     = reinterpret_cast<java::lang::ClassLoader *> (loader);
305
306   // FIXME: exception processing.
307   jclass result = l->defineClass (bytes, 0, bufLen);
308   return (jclass) _Jv_JNI_NewLocalRef (env, result);
309 }
310
311 static jclass
312 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
313 {
314   // FIXME: assume that NAME isn't too long.
315   int len = strlen (name);
316   char s[len + 1];
317   for (int i = 0; i <= len; ++i)
318     s[i] = (name[i] == '/') ? '.' : name[i];
319   jstring n = JvNewStringUTF (s);
320
321   java::lang::ClassLoader *loader;
322   if (env->klass == NULL)
323     {
324       // FIXME: should use getBaseClassLoader, but we don't have that
325       // yet.
326       loader = java::lang::ClassLoader::getSystemClassLoader ();
327     }
328   else
329     loader = env->klass->getClassLoader ();
330
331   // FIXME: exception processing.
332   jclass r = loader->findClass (n);
333
334   return (jclass) _Jv_JNI_NewLocalRef (env, r);
335 }
336
337 static jclass
338 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
339 {
340   return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
341 }
342
343 static jboolean
344 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
345 {
346   return clazz1->isAssignableFrom (clazz2);
347 }
348
349 static jint
350 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
351 {
352   env->ex = obj;
353   return 0;
354 }
355
356 static jint
357 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
358 {
359   using namespace java::lang::reflect;
360
361   JArray<jclass> *argtypes
362     = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
363
364   jclass *elts = elements (argtypes);
365   elts[0] = &StringClass;
366
367   // FIXME: exception processing.
368   Constructor *cons = clazz->getConstructor (argtypes);
369
370   jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
371   jobject *velts = elements (values);
372   velts[0] = JvNewStringUTF (message);
373
374   // FIXME: exception processing.
375   jobject obj = cons->newInstance (values);
376
377   env->ex = reinterpret_cast<jthrowable> (obj);
378   return 0;
379 }
380
381 static jthrowable
382 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
383 {
384   return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
385 }
386
387 static void
388 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
389 {
390   if (env->ex != NULL)
391     env->ex->printStackTrace();
392 }
393
394 static void
395 _Jv_JNI_ExceptionClear (JNIEnv *env)
396 {
397   env->ex = NULL;
398 }
399
400 static jboolean
401 _Jv_JNI_ExceptionCheck (JNIEnv *env)
402 {
403   return env->ex != NULL;
404 }
405
406 static void
407 _Jv_JNI_FatalError (JNIEnv *, const char *message)
408 {
409   JvFail (message);
410 }
411
412 \f
413
414 static jboolean
415 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
416 {
417   return obj1 == obj2;
418 }
419
420 static jobject
421 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
422 {
423   jobject obj = NULL;
424   using namespace java::lang::reflect;
425   if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
426     env->ex = new java::lang::InstantiationException ();
427   else
428     {
429       // FIXME: exception processing.
430       // FIXME: will this work for String?
431       obj = JvAllocObject (clazz);
432     }
433
434   return _Jv_JNI_NewLocalRef (env, obj);
435 }
436
437 static jclass
438 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
439 {
440   return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
441 }
442
443 static jboolean
444 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
445 {
446   return clazz->isInstance(obj);
447 }
448
449 \f
450
451 //
452 // This section concerns method invocation.
453 //
454
455 template<jboolean is_static>
456 static jmethodID
457 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
458                         const char *name, const char *sig)
459 {
460   // FIXME: exception processing.
461   _Jv_InitClass (clazz);
462
463   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
464   _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
465
466   JvAssert (! clazz->isPrimitive());
467
468   using namespace java::lang::reflect;
469
470   while (clazz != NULL)
471     {
472       jint count = JvNumMethods (clazz);
473       jmethodID meth = JvGetFirstMethod (clazz);
474
475       for (jint i = 0; i < count; ++i)
476         {
477           if (((is_static && Modifier::isStatic (meth->accflags))
478                || (! is_static && ! Modifier::isStatic (meth->accflags)))
479               && _Jv_equalUtf8Consts (meth->name, name_u)
480               && _Jv_equalUtf8Consts (meth->signature, sig_u))
481             return meth;
482
483           meth = meth->getNextMethod();
484         }
485
486       clazz = clazz->getSuperclass ();
487     }
488
489   env->ex = new java::lang::NoSuchMethodError ();
490   return NULL;
491 }
492
493 // This is a helper function which turns a va_list into an array of
494 // `jvalue's.  It needs signature information in order to do its work.
495 // The array of values must already be allocated.
496 static void
497 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
498 {
499   jclass *arg_elts = elements (arg_types);
500   for (int i = 0; i < arg_types->length; ++i)
501     {
502       if (arg_elts[i] == JvPrimClass (byte))
503         values[i].b = va_arg (vargs, jbyte);
504       else if (arg_elts[i] == JvPrimClass (short))
505         values[i].s = va_arg (vargs, jshort);
506       else if (arg_elts[i] == JvPrimClass (int))
507         values[i].i = va_arg (vargs, jint);
508       else if (arg_elts[i] == JvPrimClass (long))
509         values[i].j = va_arg (vargs, jlong);
510       else if (arg_elts[i] == JvPrimClass (float))
511         values[i].f = va_arg (vargs, jfloat);
512       else if (arg_elts[i] == JvPrimClass (double))
513         values[i].d = va_arg (vargs, jdouble);
514       else if (arg_elts[i] == JvPrimClass (boolean))
515         values[i].z = va_arg (vargs, jboolean);
516       else if (arg_elts[i] == JvPrimClass (char))
517         values[i].c = va_arg (vargs, jchar);
518       else
519         {
520           // An object.
521           values[i].l = va_arg (vargs, jobject);
522         }
523     }
524 }
525
526 // This can call any sort of method: virtual, "nonvirtual", static, or
527 // constructor.
528 template<typename T, invocation_type style>
529 static T
530 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
531                         jmethodID id, va_list vargs)
532 {
533   if (style == normal)
534     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
535
536   jclass decl_class = klass ? klass : obj->getClass ();
537   JvAssert (decl_class != NULL);
538
539   jclass return_type;
540   JArray<jclass> *arg_types;
541   // FIXME: exception processing.
542   _Jv_GetTypesFromSignature (id, decl_class,
543                              &arg_types, &return_type);
544
545   jvalue args[arg_types->length];
546   array_from_valist (args, arg_types, vargs);
547
548   jvalue result;
549   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
550                                       style == constructor,
551                                       arg_types, args, &result);
552
553   if (ex != NULL)
554     env->ex = ex;
555
556   // We cheat a little here.  FIXME.
557   return wrap_value (env, * (T *) &result);
558 }
559
560 template<typename T, invocation_type style>
561 static T
562 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
563                        jmethodID method, ...)
564 {
565   va_list args;
566   T result;
567
568   va_start (args, method);
569   result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
570   va_end (args);
571
572   return result;
573 }
574
575 template<typename T, invocation_type style>
576 static T
577 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
578                         jmethodID id, jvalue *args)
579 {
580   if (style == normal)
581     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
582
583   jclass decl_class = klass ? klass : obj->getClass ();
584   JvAssert (decl_class != NULL);
585
586   jclass return_type;
587   JArray<jclass> *arg_types;
588   // FIXME: exception processing.
589   _Jv_GetTypesFromSignature (id, decl_class,
590                              &arg_types, &return_type);
591
592   jvalue result;
593   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
594                                       style == constructor,
595                                       arg_types, args, &result);
596
597   if (ex != NULL)
598     env->ex = ex;
599
600   // We cheat a little here.  FIXME.
601   return wrap_value (env, * (T *) &result);
602 }
603
604 template<invocation_type style>
605 static void
606 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
607                             jmethodID id, va_list vargs)
608 {
609   if (style == normal)
610     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
611
612   jclass decl_class = klass ? klass : obj->getClass ();
613   JvAssert (decl_class != NULL);
614
615   jclass return_type;
616   JArray<jclass> *arg_types;
617   // FIXME: exception processing.
618   _Jv_GetTypesFromSignature (id, decl_class,
619                              &arg_types, &return_type);
620
621   jvalue args[arg_types->length];
622   array_from_valist (args, arg_types, vargs);
623
624   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
625                                       style == constructor,
626                                       arg_types, args, NULL);
627
628   if (ex != NULL)
629     env->ex = ex;
630 }
631
632 template<invocation_type style>
633 static void
634 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
635                            jmethodID method, ...)
636 {
637   va_list args;
638
639   va_start (args, method);
640   _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
641   va_end (args);
642 }
643
644 template<invocation_type style>
645 static void
646 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
647                             jmethodID id, jvalue *args)
648 {
649   if (style == normal)
650     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
651
652   jclass decl_class = klass ? klass : obj->getClass ();
653   JvAssert (decl_class != NULL);
654
655   jclass return_type;
656   JArray<jclass> *arg_types;
657   // FIXME: exception processing.
658   _Jv_GetTypesFromSignature (id, decl_class,
659                              &arg_types, &return_type);
660
661   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
662                                       style == constructor,
663                                       arg_types, args, NULL);
664
665   if (ex != NULL)
666     env->ex = ex;
667 }
668
669 // Functions with this signature are used to implement functions in
670 // the CallMethod family.
671 template<typename T>
672 static T
673 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
674 {
675   return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
676 }
677
678 // Functions with this signature are used to implement functions in
679 // the CallMethod family.
680 template<typename T>
681 static T
682 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
683 {
684   va_list args;
685   T result;
686
687   va_start (args, id);
688   result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
689   va_end (args);
690
691   return result;
692 }
693
694 // Functions with this signature are used to implement functions in
695 // the CallMethod family.
696 template<typename T>
697 static T
698 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
699 {
700   return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
701 }
702
703 static void
704 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
705 {
706   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
707 }
708
709 static void
710 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
711 {
712   va_list args;
713
714   va_start (args, id);
715   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
716   va_end (args);
717 }
718
719 static void
720 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
721 {
722   _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
723 }
724
725 // Functions with this signature are used to implement functions in
726 // the CallStaticMethod family.
727 template<typename T>
728 static T
729 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
730                            jmethodID id, va_list args)
731 {
732   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
733 }
734
735 // Functions with this signature are used to implement functions in
736 // the CallStaticMethod family.
737 template<typename T>
738 static T
739 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
740 {
741   va_list args;
742   T result;
743
744   va_start (args, id);
745   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
746                                                    id, args);
747   va_end (args);
748
749   return result;
750 }
751
752 // Functions with this signature are used to implement functions in
753 // the CallStaticMethod family.
754 template<typename T>
755 static T
756 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
757                            jvalue *args)
758 {
759   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
760 }
761
762 static void
763 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
764                                va_list args)
765 {
766   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
767 }
768
769 static void
770 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
771 {
772   va_list args;
773
774   va_start (args, id);
775   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
776   va_end (args);
777 }
778
779 static void
780 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
781                                jvalue *args)
782 {
783   _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
784 }
785
786 static jobject
787 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
788                     jmethodID id, va_list args)
789 {
790   return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
791                                                        id, args);
792 }
793
794 static jobject
795 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
796 {
797   va_list args;
798   jobject result;
799
800   va_start (args, id);
801   result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
802                                                          id, args);
803   va_end (args);
804
805   return result;
806 }
807
808 static jobject
809 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
810                     jvalue *args)
811 {
812   return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
813                                                        id, args);
814 }
815
816 \f
817
818 template<typename T>
819 static T
820 _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field) 
821 {
822   T *ptr = (T *) ((char *) obj + field->getOffset ());
823   return wrap_value (env, *ptr);
824 }
825
826 template<typename T>
827 static void
828 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
829 {
830   T *ptr = (T *) ((char *) obj + field->getOffset ());
831   *ptr = value;
832 }
833
834 template<jboolean is_static>
835 static jfieldID
836 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
837                        const char *name, const char *sig)
838 {
839   // FIXME: exception processing.
840   _Jv_InitClass (clazz);
841
842   _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
843
844   jclass field_class = NULL;
845   if (sig[0] == '[')
846     field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
847   else
848     {
849       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
850       field_class = _Jv_FindClass (sig_u, NULL);
851     }
852
853   // FIXME: what if field_class == NULL?
854
855   while (clazz != NULL)
856     {
857       jint count = (is_static
858                     ? JvNumStaticFields (clazz)
859                     : JvNumInstanceFields (clazz));
860       jfieldID field = (is_static
861                         ? JvGetFirstStaticField (clazz)
862                         : JvGetFirstInstanceField (clazz));
863       for (jint i = 0; i < count; ++i)
864         {
865           // The field is resolved as a side effect of class
866           // initialization.
867           JvAssert (field->isResolved ());
868
869           _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
870
871           if (_Jv_equalUtf8Consts (f_name, a_name)
872               && field->getClass() == field_class)
873             return field;
874
875           field = field->getNextField ();
876         }
877
878       clazz = clazz->getSuperclass ();
879     }
880
881   env->ex = new java::lang::NoSuchFieldError ();
882   return NULL;
883 }
884
885 template<typename T>
886 static T
887 _Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
888 {
889   T *ptr = (T *) field->u.addr;
890   return wrap_value (env, *ptr);
891 }
892
893 template<typename T>
894 static void
895 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
896 {
897   T *ptr = (T *) field->u.addr;
898   *ptr = value;
899 }
900
901 static jstring
902 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
903 {
904   // FIXME: exception processing.
905   jstring r = _Jv_NewString (unichars, len);
906   return (jstring) _Jv_JNI_NewLocalRef (env, r);
907 }
908
909 static jsize
910 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
911 {
912   return string->length();
913 }
914
915 static const jchar *
916 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
917 {
918   jchar *result = _Jv_GetStringChars (string);
919   mark_for_gc (string);
920   if (isCopy)
921     *isCopy = false;
922   return (const jchar *) result;
923 }
924
925 static void
926 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
927 {
928   unmark_for_gc (string);
929 }
930
931 static jstring
932 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
933 {
934   // FIXME: exception processing.
935   jstring result = JvNewStringUTF (bytes);
936   return (jstring) _Jv_JNI_NewLocalRef (env, result);
937 }
938
939 static jsize
940 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
941 {
942   return JvGetStringUTFLength (string);
943 }
944
945 static const char *
946 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
947 {
948   jsize len = JvGetStringUTFLength (string);
949   // FIXME: exception processing.
950   char *r = (char *) _Jv_Malloc (len + 1);
951   JvGetStringUTFRegion (string, 0, len, r);
952   r[len] = '\0';
953
954   if (isCopy)
955     *isCopy = true;
956
957   return (const char *) r;
958 }
959
960 static void
961 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
962 {
963   _Jv_Free ((void *) utf);
964 }
965
966 static void
967 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
968                          jchar *buf)
969 {
970   jchar *result = _Jv_GetStringChars (string);
971   if (start < 0 || start > string->length ()
972       || len < 0 || start + len > string->length ())
973     env->ex = new java::lang::StringIndexOutOfBoundsException ();
974   else
975     memcpy (buf, &result[start], len * sizeof (jchar));
976 }
977
978 static void
979 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
980                             jsize len, char *buf)
981 {
982   if (start < 0 || start > str->length ()
983       || len < 0 || start + len > str->length ())
984     env->ex = new java::lang::StringIndexOutOfBoundsException ();
985   else
986     _Jv_GetStringUTFRegion (str, start, len, buf);
987 }
988
989 static const jchar *
990 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
991 {
992   jchar *result = _Jv_GetStringChars (str);
993   if (isCopy)
994     *isCopy = false;
995   return result;
996 }
997
998 static void
999 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1000 {
1001   // Nothing.
1002 }
1003
1004 static jsize
1005 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1006 {
1007   return array->length;
1008 }
1009
1010 static jarray
1011 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1012                         jobject init)
1013 {
1014   // FIXME: exception processing.
1015   jarray result = JvNewObjectArray (length, elementClass, init);
1016   return (jarray) _Jv_JNI_NewLocalRef (env, result);
1017 }
1018
1019 static jobject
1020 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1021 {
1022   jobject *elts = elements (array);
1023   return _Jv_JNI_NewLocalRef (env, elts[index]);
1024 }
1025
1026 static void
1027 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1028                                jobject value)
1029 {
1030   // FIXME: exception processing.
1031   _Jv_CheckArrayStore (array, value);
1032   jobject *elts = elements (array);
1033   elts[index] = value;
1034 }
1035
1036 template<typename T, jclass K>
1037 static JArray<T> *
1038 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1039 {
1040   // FIXME: exception processing.
1041   return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1042                                             _Jv_NewPrimArray (K, length));
1043 }
1044
1045 template<typename T>
1046 static T *
1047 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1048                                    jboolean *isCopy)
1049 {
1050   T *elts = elements (array);
1051   if (isCopy)
1052     {
1053       // We elect never to copy.
1054       *isCopy = false;
1055     }
1056   mark_for_gc (array);
1057   return elts;
1058 }
1059
1060 template<typename T>
1061 static void
1062 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1063                                        T *, jint /* mode */)
1064 {
1065   // Note that we ignore MODE.  We can do this because we never copy
1066   // the array elements.  My reading of the JNI documentation is that
1067   // this is an option for the implementor.
1068   unmark_for_gc (array);
1069 }
1070
1071 template<typename T>
1072 static void
1073 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1074                                  jsize start, jsize len,
1075                                  T *buf)
1076 {
1077   if (start < 0 || len >= array->length || start + len >= array->length)
1078     {
1079       // FIXME: index.
1080       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1081     }
1082   else
1083     {
1084       T *elts = elements (array) + start;
1085       memcpy (buf, elts, len * sizeof (T));
1086     }
1087 }
1088
1089 template<typename T>
1090 static void
1091 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
1092                                  jsize start, jsize len, T *buf)
1093 {
1094   if (start < 0 || len >= array->length || start + len >= array->length)
1095     {
1096       // FIXME: index.
1097       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1098     }
1099   else
1100     {
1101       T *elts = elements (array) + start;
1102       memcpy (elts, buf, len * sizeof (T));
1103     }
1104 }
1105
1106 static void *
1107 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1108                                    jboolean *isCopy)
1109 {
1110   // FIXME: does this work?
1111   jclass klass = array->getClass()->getComponentType();
1112   JvAssert (klass->isPrimitive ());
1113   char *r = _Jv_GetArrayElementFromElementType (array, klass);
1114   if (isCopy)
1115     *isCopy = false;
1116   return r;
1117 }
1118
1119 static void
1120 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1121 {
1122   // Nothing.
1123 }
1124
1125 static jint
1126 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1127 {
1128   // FIXME: exception processing.
1129   jint r = _Jv_MonitorEnter (obj);
1130   return r;
1131 }
1132
1133 static jint
1134 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1135 {
1136   // FIXME: exception processing.
1137   jint r = _Jv_MonitorExit (obj);
1138   return r;
1139 }
1140
1141 // JDK 1.2
1142 jobject
1143 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1144                           jboolean)
1145 {
1146   // FIXME: exception processing.
1147   java::lang::reflect::Field *field = new java::lang::reflect::Field();
1148   field->declaringClass = cls;
1149   field->offset = (char*) fieldID - (char *) cls->fields;
1150   field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1151   return _Jv_JNI_NewLocalRef (env, field);
1152 }
1153
1154 // JDK 1.2
1155 static jfieldID
1156 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1157 {
1158   using namespace java::lang::reflect;
1159
1160   Field *field = reinterpret_cast<Field *> (f);
1161   return _Jv_FromReflectedField (field);
1162 }
1163
1164 jobject
1165 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1166                            jboolean)
1167 {
1168   using namespace java::lang::reflect;
1169
1170   // FIXME.
1171   static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1172
1173   jobject result;
1174   if (_Jv_equalUtf8Consts (id->name, init_name))
1175     {
1176       // A constructor.
1177       Constructor *cons = new Constructor ();
1178       cons->offset = (char *) id - (char *) &klass->methods;
1179       cons->declaringClass = klass;
1180       result = cons;
1181     }
1182   else
1183     {
1184       Method *meth = new Method ();
1185       meth->offset = (char *) id - (char *) &klass->methods;
1186       meth->declaringClass = klass;
1187       result = meth;
1188     }
1189
1190   return _Jv_JNI_NewLocalRef (env, result);
1191 }
1192
1193 static jmethodID
1194 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1195 {
1196   using namespace java::lang::reflect;
1197   if ((&MethodClass)->isInstance (method))
1198     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1199   return
1200     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1201 }
1202
1203 \f
1204
1205 // This function is the stub which is used to turn an ordinary (CNI)
1206 // method call into a JNI call.
1207 #if 0
1208 template<typename T>
1209 static T
1210 _Jv_JNI_conversion_call (fixme)
1211 {
1212   JNIEnv env;
1213   _Jv_JNI_LocalFrame *frame
1214     = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1215                                      + FRAME_SIZE * sizeof (jobject));
1216
1217   env.p = &_Jv_JNIFunctions;
1218   env.ex = NULL;
1219   env.klass = FIXME;
1220   env.locals = frame;
1221
1222   frame->marker = true;
1223   frame->next = NULL;
1224   frame->size = FRAME_SIZE;
1225   for (int i = 0; i < frame->size; ++i)
1226     frame->vec[i] = NULL;
1227
1228   T result = FIXME_ffi_call (args);
1229
1230   do
1231     {
1232       _Jv_JNI_PopLocalFrame (&env, result);
1233     }
1234   while (env.locals != frame);
1235
1236   if (env.ex)
1237     JvThrow (env.ex);
1238
1239   return T;
1240 }
1241 #endif
1242
1243 \f
1244
1245 #define NOT_IMPL NULL
1246 #define RESERVED NULL
1247
1248 struct JNINativeInterface _Jv_JNIFunctions =
1249 {
1250   RESERVED,
1251   RESERVED,
1252   RESERVED,
1253   RESERVED,
1254   _Jv_JNI_GetVersion,
1255   _Jv_JNI_DefineClass,
1256   _Jv_JNI_FindClass,
1257   _Jv_JNI_FromReflectedMethod,
1258   _Jv_JNI_FromReflectedField,
1259   _Jv_JNI_ToReflectedMethod,
1260   _Jv_JNI_GetSuperclass,
1261   _Jv_JNI_IsAssignableFrom,
1262   _Jv_JNI_ToReflectedField,
1263   _Jv_JNI_Throw,
1264   _Jv_JNI_ThrowNew,
1265   _Jv_JNI_ExceptionOccurred,
1266   _Jv_JNI_ExceptionDescribe,
1267   _Jv_JNI_ExceptionClear,
1268   _Jv_JNI_FatalError,
1269
1270   _Jv_JNI_PushLocalFrame,
1271   _Jv_JNI_PopLocalFrame,
1272   _Jv_JNI_NewGlobalRef,
1273   _Jv_JNI_DeleteGlobalRef,
1274   _Jv_JNI_DeleteLocalRef,
1275
1276   _Jv_JNI_IsSameObject,
1277
1278   _Jv_JNI_NewLocalRef,
1279   _Jv_JNI_EnsureLocalCapacity,
1280
1281   _Jv_JNI_AllocObject,
1282   _Jv_JNI_NewObject,
1283   _Jv_JNI_NewObjectV,
1284   _Jv_JNI_NewObjectA,
1285   _Jv_JNI_GetObjectClass,
1286   _Jv_JNI_IsInstanceOf,
1287   _Jv_JNI_GetAnyMethodID<false>,
1288
1289   _Jv_JNI_CallMethod<jobject>,
1290   _Jv_JNI_CallMethodV<jobject>,
1291   _Jv_JNI_CallMethodA<jobject>,
1292   _Jv_JNI_CallMethod<jboolean>,
1293   _Jv_JNI_CallMethodV<jboolean>,
1294   _Jv_JNI_CallMethodA<jboolean>,
1295   _Jv_JNI_CallMethod<jbyte>,
1296   _Jv_JNI_CallMethodV<jbyte>,
1297   _Jv_JNI_CallMethodA<jbyte>,
1298   _Jv_JNI_CallMethod<jchar>,
1299   _Jv_JNI_CallMethodV<jchar>,
1300   _Jv_JNI_CallMethodA<jchar>,
1301   _Jv_JNI_CallMethod<jshort>,
1302   _Jv_JNI_CallMethodV<jshort>,
1303   _Jv_JNI_CallMethodA<jshort>,
1304   _Jv_JNI_CallMethod<jint>,
1305   _Jv_JNI_CallMethodV<jint>,
1306   _Jv_JNI_CallMethodA<jint>,
1307   _Jv_JNI_CallMethod<jlong>,
1308   _Jv_JNI_CallMethodV<jlong>,
1309   _Jv_JNI_CallMethodA<jlong>,
1310   _Jv_JNI_CallMethod<jfloat>,
1311   _Jv_JNI_CallMethodV<jfloat>,
1312   _Jv_JNI_CallMethodA<jfloat>,
1313   _Jv_JNI_CallMethod<jdouble>,
1314   _Jv_JNI_CallMethodV<jdouble>,
1315   _Jv_JNI_CallMethodA<jdouble>,
1316   _Jv_JNI_CallVoidMethod,
1317   _Jv_JNI_CallVoidMethodV,
1318   _Jv_JNI_CallVoidMethodA,
1319
1320   // Nonvirtual method invocation functions follow.
1321   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1322   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1323   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1324   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1325   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1326   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1327   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1328   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1329   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1330   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1331   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1332   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1333   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1334   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1335   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1336   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1337   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1338   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1339   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1340   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1341   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1342   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1343   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1344   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1345   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1346   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1347   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1348   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1349   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1350   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1351
1352   _Jv_JNI_GetAnyFieldID<false>,
1353   _Jv_JNI_GetField<jobject>,
1354   _Jv_JNI_GetField<jboolean>,
1355   _Jv_JNI_GetField<jbyte>,
1356   _Jv_JNI_GetField<jchar>,
1357   _Jv_JNI_GetField<jshort>,
1358   _Jv_JNI_GetField<jint>,
1359   _Jv_JNI_GetField<jlong>,
1360   _Jv_JNI_GetField<jfloat>,
1361   _Jv_JNI_GetField<jdouble>,
1362   _Jv_JNI_SetField,
1363   _Jv_JNI_SetField,
1364   _Jv_JNI_SetField,
1365   _Jv_JNI_SetField,
1366   _Jv_JNI_SetField,
1367   _Jv_JNI_SetField,
1368   _Jv_JNI_SetField,
1369   _Jv_JNI_SetField,
1370   _Jv_JNI_SetField,
1371   _Jv_JNI_GetAnyMethodID<true>,
1372
1373   _Jv_JNI_CallStaticMethod<jobject>,
1374   _Jv_JNI_CallStaticMethodV<jobject>,
1375   _Jv_JNI_CallStaticMethodA<jobject>,
1376   _Jv_JNI_CallStaticMethod<jboolean>,
1377   _Jv_JNI_CallStaticMethodV<jboolean>,
1378   _Jv_JNI_CallStaticMethodA<jboolean>,
1379   _Jv_JNI_CallStaticMethod<jbyte>,
1380   _Jv_JNI_CallStaticMethodV<jbyte>,
1381   _Jv_JNI_CallStaticMethodA<jbyte>,
1382   _Jv_JNI_CallStaticMethod<jchar>,
1383   _Jv_JNI_CallStaticMethodV<jchar>,
1384   _Jv_JNI_CallStaticMethodA<jchar>,
1385   _Jv_JNI_CallStaticMethod<jshort>,
1386   _Jv_JNI_CallStaticMethodV<jshort>,
1387   _Jv_JNI_CallStaticMethodA<jshort>,
1388   _Jv_JNI_CallStaticMethod<jint>,
1389   _Jv_JNI_CallStaticMethodV<jint>,
1390   _Jv_JNI_CallStaticMethodA<jint>,
1391   _Jv_JNI_CallStaticMethod<jlong>,
1392   _Jv_JNI_CallStaticMethodV<jlong>,
1393   _Jv_JNI_CallStaticMethodA<jlong>,
1394   _Jv_JNI_CallStaticMethod<jfloat>,
1395   _Jv_JNI_CallStaticMethodV<jfloat>,
1396   _Jv_JNI_CallStaticMethodA<jfloat>,
1397   _Jv_JNI_CallStaticMethod<jdouble>,
1398   _Jv_JNI_CallStaticMethodV<jdouble>,
1399   _Jv_JNI_CallStaticMethodA<jdouble>,
1400   _Jv_JNI_CallStaticVoidMethod,
1401   _Jv_JNI_CallStaticVoidMethodV,
1402   _Jv_JNI_CallStaticVoidMethodA,
1403
1404   _Jv_JNI_GetAnyFieldID<true>,
1405   _Jv_JNI_GetStaticField<jobject>,
1406   _Jv_JNI_GetStaticField<jboolean>,
1407   _Jv_JNI_GetStaticField<jbyte>,
1408   _Jv_JNI_GetStaticField<jchar>,
1409   _Jv_JNI_GetStaticField<jshort>,
1410   _Jv_JNI_GetStaticField<jint>,
1411   _Jv_JNI_GetStaticField<jlong>,
1412   _Jv_JNI_GetStaticField<jfloat>,
1413   _Jv_JNI_GetStaticField<jdouble>,
1414   _Jv_JNI_SetStaticField,
1415   _Jv_JNI_SetStaticField,
1416   _Jv_JNI_SetStaticField,
1417   _Jv_JNI_SetStaticField,
1418   _Jv_JNI_SetStaticField,
1419   _Jv_JNI_SetStaticField,
1420   _Jv_JNI_SetStaticField,
1421   _Jv_JNI_SetStaticField,
1422   _Jv_JNI_SetStaticField,
1423   _Jv_JNI_NewString,
1424   _Jv_JNI_GetStringLength,
1425   _Jv_JNI_GetStringChars,
1426   _Jv_JNI_ReleaseStringChars,
1427   _Jv_JNI_NewStringUTF,
1428   _Jv_JNI_GetStringUTFLength,
1429   _Jv_JNI_GetStringUTFChars,
1430   _Jv_JNI_ReleaseStringUTFChars,
1431   _Jv_JNI_GetArrayLength,
1432   _Jv_JNI_NewObjectArray,
1433   _Jv_JNI_GetObjectArrayElement,
1434   _Jv_JNI_SetObjectArrayElement,
1435   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1436   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1437   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1438   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1439   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1440   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1441   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1442   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1443   _Jv_JNI_GetPrimitiveArrayElements,
1444   _Jv_JNI_GetPrimitiveArrayElements,
1445   _Jv_JNI_GetPrimitiveArrayElements,
1446   _Jv_JNI_GetPrimitiveArrayElements,
1447   _Jv_JNI_GetPrimitiveArrayElements,
1448   _Jv_JNI_GetPrimitiveArrayElements,
1449   _Jv_JNI_GetPrimitiveArrayElements,
1450   _Jv_JNI_GetPrimitiveArrayElements,
1451   _Jv_JNI_ReleasePrimitiveArrayElements,
1452   _Jv_JNI_ReleasePrimitiveArrayElements,
1453   _Jv_JNI_ReleasePrimitiveArrayElements,
1454   _Jv_JNI_ReleasePrimitiveArrayElements,
1455   _Jv_JNI_ReleasePrimitiveArrayElements,
1456   _Jv_JNI_ReleasePrimitiveArrayElements,
1457   _Jv_JNI_ReleasePrimitiveArrayElements,
1458   _Jv_JNI_ReleasePrimitiveArrayElements,
1459   _Jv_JNI_GetPrimitiveArrayRegion,
1460   _Jv_JNI_GetPrimitiveArrayRegion,
1461   _Jv_JNI_GetPrimitiveArrayRegion,
1462   _Jv_JNI_GetPrimitiveArrayRegion,
1463   _Jv_JNI_GetPrimitiveArrayRegion,
1464   _Jv_JNI_GetPrimitiveArrayRegion,
1465   _Jv_JNI_GetPrimitiveArrayRegion,
1466   _Jv_JNI_GetPrimitiveArrayRegion,
1467   _Jv_JNI_SetPrimitiveArrayRegion,
1468   _Jv_JNI_SetPrimitiveArrayRegion,
1469   _Jv_JNI_SetPrimitiveArrayRegion,
1470   _Jv_JNI_SetPrimitiveArrayRegion,
1471   _Jv_JNI_SetPrimitiveArrayRegion,
1472   _Jv_JNI_SetPrimitiveArrayRegion,
1473   _Jv_JNI_SetPrimitiveArrayRegion,
1474   _Jv_JNI_SetPrimitiveArrayRegion,
1475   NOT_IMPL /* RegisterNatives */,
1476   NOT_IMPL /* UnregisterNatives */,
1477   _Jv_JNI_MonitorEnter,
1478   _Jv_JNI_MonitorExit,
1479   NOT_IMPL /* GetJavaVM */,
1480
1481   _Jv_JNI_GetStringRegion,
1482   _Jv_JNI_GetStringUTFRegion,
1483   _Jv_JNI_GetPrimitiveArrayCritical,
1484   _Jv_JNI_ReleasePrimitiveArrayCritical,
1485   _Jv_JNI_GetStringCritical,
1486   _Jv_JNI_ReleaseStringCritical,
1487
1488   NOT_IMPL /* newweakglobalref */,
1489   NOT_IMPL /* deleteweakglobalref */,
1490
1491   _Jv_JNI_ExceptionCheck
1492 };