OSDN Git Service

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