OSDN Git Service

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