OSDN Git Service

* jni.cc (_Jv_JNI_GetField): Specialize for jobject.
[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 template<typename T>
815 static T
816 _Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field) 
817 {
818   T *ptr = (T *) ((char *) obj + field->getOffset ());
819   return *ptr;
820 }
821
822 template<>
823 static jobject
824 _Jv_JNI_GetField<jobject> (JNIEnv *env, jobject obj, jfieldID field)
825 {
826   jobject *ptr = (jobject *) ((char *) obj + field->getOffset ());
827   return _Jv_JNI_NewLocalRef (env, *ptr);
828 }
829
830 template<typename T>
831 static void
832 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
833 {
834   T *ptr = (T *) ((char *) obj + field->getOffset ());
835   *ptr = value;
836 }
837
838 template<jboolean is_static>
839 static jfieldID
840 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
841                        const char *name, const char *sig)
842 {
843   // FIXME: exception processing.
844   _Jv_InitClass (clazz);
845
846   _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
847
848   jclass field_class = NULL;
849   if (sig[0] == '[')
850     field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
851   else
852     {
853       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
854       field_class = _Jv_FindClass (sig_u, NULL);
855     }
856
857   // FIXME: what if field_class == NULL?
858
859   while (clazz != NULL)
860     {
861       jint count = (is_static
862                     ? JvNumStaticFields (clazz)
863                     : JvNumInstanceFields (clazz));
864       jfieldID field = (is_static
865                         ? JvGetFirstStaticField (clazz)
866                         : JvGetFirstInstanceField (clazz));
867       for (jint i = 0; i < count; ++i)
868         {
869           // The field is resolved as a side effect of class
870           // initialization.
871           JvAssert (field->isResolved ());
872
873           _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
874
875           if (_Jv_equalUtf8Consts (f_name, a_name)
876               && field->getClass() == field_class)
877             return field;
878
879           field = field->getNextField ();
880         }
881
882       clazz = clazz->getSuperclass ();
883     }
884
885   env->ex = new java::lang::NoSuchFieldError ();
886   return NULL;
887 }
888
889 // FIXME: local reference
890 template<typename T>
891 static T
892 _Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
893 {
894   T *ptr = (T *) field->u.addr;
895   return *ptr;
896 }
897
898 template<>
899 static jobject
900 _Jv_JNI_GetStaticField<jobject> (JNIEnv *env, jclass, jfieldID field)
901 {
902   jobject *ptr = (jobject *) field->u.addr;
903   return _Jv_JNI_NewLocalRef (env, *ptr);
904 }
905
906 template<typename T>
907 static void
908 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
909 {
910   T *ptr = (T *) field->u.addr;
911   *ptr = value;
912 }
913
914 static jstring
915 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
916 {
917   // FIXME: exception processing.
918   jstring r = _Jv_NewString (unichars, len);
919   return (jstring) _Jv_JNI_NewLocalRef (env, r);
920 }
921
922 static jsize
923 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
924 {
925   return string->length();
926 }
927
928 static const jchar *
929 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
930 {
931   jchar *result = _Jv_GetStringChars (string);
932   mark_for_gc (string);
933   if (isCopy)
934     *isCopy = false;
935   return (const jchar *) result;
936 }
937
938 static void
939 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
940 {
941   unmark_for_gc (string);
942 }
943
944 static jstring
945 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
946 {
947   // FIXME: exception processing.
948   jstring result = JvNewStringUTF (bytes);
949   return (jstring) _Jv_JNI_NewLocalRef (env, result);
950 }
951
952 static jsize
953 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
954 {
955   return JvGetStringUTFLength (string);
956 }
957
958 static const char *
959 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
960 {
961   jsize len = JvGetStringUTFLength (string);
962   // FIXME: exception processing.
963   char *r = (char *) _Jv_Malloc (len + 1);
964   JvGetStringUTFRegion (string, 0, len, r);
965   r[len] = '\0';
966
967   if (isCopy)
968     *isCopy = true;
969
970   return (const char *) r;
971 }
972
973 static void
974 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
975 {
976   _Jv_Free ((void *) utf);
977 }
978
979 static void
980 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
981                          jchar *buf)
982 {
983   jchar *result = _Jv_GetStringChars (string);
984   if (start < 0 || start > string->length ()
985       || len < 0 || start + len > string->length ())
986     env->ex = new java::lang::StringIndexOutOfBoundsException ();
987   else
988     memcpy (buf, &result[start], len * sizeof (jchar));
989 }
990
991 static void
992 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
993                             jsize len, char *buf)
994 {
995   if (start < 0 || start > str->length ()
996       || len < 0 || start + len > str->length ())
997     env->ex = new java::lang::StringIndexOutOfBoundsException ();
998   else
999     _Jv_GetStringUTFRegion (str, start, len, buf);
1000 }
1001
1002 static const jchar *
1003 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
1004 {
1005   jchar *result = _Jv_GetStringChars (str);
1006   if (isCopy)
1007     *isCopy = false;
1008   return result;
1009 }
1010
1011 static void
1012 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1013 {
1014   // Nothing.
1015 }
1016
1017 static jsize
1018 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1019 {
1020   return array->length;
1021 }
1022
1023 static jarray
1024 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1025                         jobject init)
1026 {
1027   // FIXME: exception processing.
1028   jarray result = JvNewObjectArray (length, elementClass, init);
1029   return (jarray) _Jv_JNI_NewLocalRef (env, result);
1030 }
1031
1032 static jobject
1033 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1034 {
1035   jobject *elts = elements (array);
1036   return _Jv_JNI_NewLocalRef (env, elts[index]);
1037 }
1038
1039 static void
1040 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1041                                jobject value)
1042 {
1043   // FIXME: exception processing.
1044   _Jv_CheckArrayStore (array, value);
1045   jobject *elts = elements (array);
1046   elts[index] = value;
1047 }
1048
1049 template<typename T, jclass K>
1050 static JArray<T> *
1051 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1052 {
1053   // FIXME: exception processing.
1054   return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1055                                             _Jv_NewPrimArray (K, length));
1056 }
1057
1058 template<typename T>
1059 static T *
1060 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1061                                    jboolean *isCopy)
1062 {
1063   T *elts = elements (array);
1064   if (isCopy)
1065     {
1066       // We elect never to copy.
1067       *isCopy = false;
1068     }
1069   mark_for_gc (array);
1070   return elts;
1071 }
1072
1073 template<typename T>
1074 static void
1075 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1076                                        T *, jint /* mode */)
1077 {
1078   // Note that we ignore MODE.  We can do this because we never copy
1079   // the array elements.  My reading of the JNI documentation is that
1080   // this is an option for the implementor.
1081   unmark_for_gc (array);
1082 }
1083
1084 template<typename T>
1085 static void
1086 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1087                                  jsize start, jsize len,
1088                                  T *buf)
1089 {
1090   if (start < 0 || len >= array->length || start + len >= array->length)
1091     {
1092       // FIXME: index.
1093       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1094     }
1095   else
1096     {
1097       T *elts = elements (array) + start;
1098       memcpy (buf, elts, len * sizeof (T));
1099     }
1100 }
1101
1102 template<typename T>
1103 static void
1104 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
1105                                  jsize start, jsize len, T *buf)
1106 {
1107   if (start < 0 || len >= array->length || start + len >= array->length)
1108     {
1109       // FIXME: index.
1110       env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1111     }
1112   else
1113     {
1114       T *elts = elements (array) + start;
1115       memcpy (elts, buf, len * sizeof (T));
1116     }
1117 }
1118
1119 static void *
1120 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1121                                    jboolean *isCopy)
1122 {
1123   // FIXME: does this work?
1124   jclass klass = array->getClass()->getComponentType();
1125   JvAssert (klass->isPrimitive ());
1126   char *r = _Jv_GetArrayElementFromElementType (array, klass);
1127   if (isCopy)
1128     *isCopy = false;
1129   return r;
1130 }
1131
1132 static void
1133 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1134 {
1135   // Nothing.
1136 }
1137
1138 static jint
1139 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1140 {
1141   // FIXME: exception processing.
1142   jint r = _Jv_MonitorEnter (obj);
1143   return r;
1144 }
1145
1146 static jint
1147 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1148 {
1149   // FIXME: exception processing.
1150   jint r = _Jv_MonitorExit (obj);
1151   return r;
1152 }
1153
1154 // JDK 1.2
1155 jobject
1156 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1157                           jboolean)
1158 {
1159   // FIXME: exception processing.
1160   java::lang::reflect::Field *field = new java::lang::reflect::Field();
1161   field->declaringClass = cls;
1162   field->offset = (char*) fieldID - (char *) cls->fields;
1163   field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1164   return _Jv_JNI_NewLocalRef (env, field);
1165 }
1166
1167 // JDK 1.2
1168 static jfieldID
1169 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1170 {
1171   using namespace java::lang::reflect;
1172
1173   Field *field = reinterpret_cast<Field *> (f);
1174   return _Jv_FromReflectedField (field);
1175 }
1176
1177 jobject
1178 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1179                            jboolean)
1180 {
1181   using namespace java::lang::reflect;
1182
1183   // FIXME.
1184   static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1185
1186   jobject result;
1187   if (_Jv_equalUtf8Consts (id->name, init_name))
1188     {
1189       // A constructor.
1190       Constructor *cons = new Constructor ();
1191       cons->offset = (char *) id - (char *) &klass->methods;
1192       cons->declaringClass = klass;
1193       result = cons;
1194     }
1195   else
1196     {
1197       Method *meth = new Method ();
1198       meth->offset = (char *) id - (char *) &klass->methods;
1199       meth->declaringClass = klass;
1200       result = meth;
1201     }
1202
1203   return _Jv_JNI_NewLocalRef (env, result);
1204 }
1205
1206 static jmethodID
1207 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1208 {
1209   using namespace java::lang::reflect;
1210   if ((&MethodClass)->isInstance (method))
1211     return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1212   return
1213     _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1214 }
1215
1216 \f
1217
1218 // This function is the stub which is used to turn an ordinary (CNI)
1219 // method call into a JNI call.
1220 #if 0
1221 template<typename T>
1222 static T
1223 _Jv_JNI_conversion_call (fixme)
1224 {
1225   JNIEnv env;
1226   _Jv_JNI_LocalFrame *frame
1227     = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1228                                      + FRAME_SIZE * sizeof (jobject));
1229
1230   env.p = &_Jv_JNIFunctions;
1231   env.ex = NULL;
1232   env.klass = FIXME;
1233   env.locals = frame;
1234
1235   frame->marker = true;
1236   frame->next = NULL;
1237   frame->size = FRAME_SIZE;
1238   for (int i = 0; i < frame->size; ++i)
1239     frame->vec[i] = NULL;
1240
1241   T result = FIXME_ffi_call (args);
1242
1243   while (env.locals != NULL)
1244     _Jv_JNI_PopLocalFrame (&env, result);
1245
1246   if (env.ex)
1247     JvThrow (env.ex);
1248
1249   return T;
1250 }
1251 #endif
1252
1253 \f
1254
1255 #define NOT_IMPL NULL
1256 #define RESERVED NULL
1257
1258 struct JNINativeInterface _Jv_JNIFunctions =
1259 {
1260   RESERVED,
1261   RESERVED,
1262   RESERVED,
1263   RESERVED,
1264   _Jv_JNI_GetVersion,
1265   _Jv_JNI_DefineClass,
1266   _Jv_JNI_FindClass,
1267   _Jv_JNI_FromReflectedMethod,
1268   _Jv_JNI_FromReflectedField,
1269   _Jv_JNI_ToReflectedMethod,
1270   _Jv_JNI_GetSuperclass,
1271   _Jv_JNI_IsAssignableFrom,
1272   _Jv_JNI_ToReflectedField,
1273   _Jv_JNI_Throw,
1274   _Jv_JNI_ThrowNew,
1275   _Jv_JNI_ExceptionOccurred,
1276   _Jv_JNI_ExceptionDescribe,
1277   _Jv_JNI_ExceptionClear,
1278   _Jv_JNI_FatalError,
1279
1280   _Jv_JNI_PushLocalFrame,
1281   _Jv_JNI_PopLocalFrame,
1282   _Jv_JNI_NewGlobalRef,
1283   _Jv_JNI_DeleteGlobalRef,
1284   _Jv_JNI_DeleteLocalRef,
1285
1286   _Jv_JNI_IsSameObject,
1287
1288   _Jv_JNI_NewLocalRef,
1289   _Jv_JNI_EnsureLocalCapacity,
1290
1291   _Jv_JNI_AllocObject,
1292   _Jv_JNI_NewObject,
1293   _Jv_JNI_NewObjectV,
1294   _Jv_JNI_NewObjectA,
1295   _Jv_JNI_GetObjectClass,
1296   _Jv_JNI_IsInstanceOf,
1297   _Jv_JNI_GetAnyMethodID<false>,
1298
1299   _Jv_JNI_CallMethod<jobject>,
1300   _Jv_JNI_CallMethodV<jobject>,
1301   _Jv_JNI_CallMethodA<jobject>,
1302   _Jv_JNI_CallMethod<jboolean>,
1303   _Jv_JNI_CallMethodV<jboolean>,
1304   _Jv_JNI_CallMethodA<jboolean>,
1305   _Jv_JNI_CallMethod<jbyte>,
1306   _Jv_JNI_CallMethodV<jbyte>,
1307   _Jv_JNI_CallMethodA<jbyte>,
1308   _Jv_JNI_CallMethod<jchar>,
1309   _Jv_JNI_CallMethodV<jchar>,
1310   _Jv_JNI_CallMethodA<jchar>,
1311   _Jv_JNI_CallMethod<jshort>,
1312   _Jv_JNI_CallMethodV<jshort>,
1313   _Jv_JNI_CallMethodA<jshort>,
1314   _Jv_JNI_CallMethod<jint>,
1315   _Jv_JNI_CallMethodV<jint>,
1316   _Jv_JNI_CallMethodA<jint>,
1317   _Jv_JNI_CallMethod<jlong>,
1318   _Jv_JNI_CallMethodV<jlong>,
1319   _Jv_JNI_CallMethodA<jlong>,
1320   _Jv_JNI_CallMethod<jfloat>,
1321   _Jv_JNI_CallMethodV<jfloat>,
1322   _Jv_JNI_CallMethodA<jfloat>,
1323   _Jv_JNI_CallMethod<jdouble>,
1324   _Jv_JNI_CallMethodV<jdouble>,
1325   _Jv_JNI_CallMethodA<jdouble>,
1326   _Jv_JNI_CallVoidMethod,
1327   _Jv_JNI_CallVoidMethodV,
1328   _Jv_JNI_CallVoidMethodA,
1329
1330   // Nonvirtual method invocation functions follow.
1331   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1332   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1333   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1334   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1335   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1336   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1337   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1338   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1339   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1340   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1341   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1342   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1343   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1344   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1345   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1346   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1347   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1348   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1349   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1350   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1351   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1352   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1353   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1354   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1355   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1356   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1357   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1358   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1359   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1360   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1361
1362   _Jv_JNI_GetAnyFieldID<false>,
1363   _Jv_JNI_GetField<jobject>,
1364   _Jv_JNI_GetField<jboolean>,
1365   _Jv_JNI_GetField<jbyte>,
1366   _Jv_JNI_GetField<jchar>,
1367   _Jv_JNI_GetField<jshort>,
1368   _Jv_JNI_GetField<jint>,
1369   _Jv_JNI_GetField<jlong>,
1370   _Jv_JNI_GetField<jfloat>,
1371   _Jv_JNI_GetField<jdouble>,
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_SetField,
1381   _Jv_JNI_GetAnyMethodID<true>,
1382
1383   _Jv_JNI_CallStaticMethod<jobject>,
1384   _Jv_JNI_CallStaticMethodV<jobject>,
1385   _Jv_JNI_CallStaticMethodA<jobject>,
1386   _Jv_JNI_CallStaticMethod<jboolean>,
1387   _Jv_JNI_CallStaticMethodV<jboolean>,
1388   _Jv_JNI_CallStaticMethodA<jboolean>,
1389   _Jv_JNI_CallStaticMethod<jbyte>,
1390   _Jv_JNI_CallStaticMethodV<jbyte>,
1391   _Jv_JNI_CallStaticMethodA<jbyte>,
1392   _Jv_JNI_CallStaticMethod<jchar>,
1393   _Jv_JNI_CallStaticMethodV<jchar>,
1394   _Jv_JNI_CallStaticMethodA<jchar>,
1395   _Jv_JNI_CallStaticMethod<jshort>,
1396   _Jv_JNI_CallStaticMethodV<jshort>,
1397   _Jv_JNI_CallStaticMethodA<jshort>,
1398   _Jv_JNI_CallStaticMethod<jint>,
1399   _Jv_JNI_CallStaticMethodV<jint>,
1400   _Jv_JNI_CallStaticMethodA<jint>,
1401   _Jv_JNI_CallStaticMethod<jlong>,
1402   _Jv_JNI_CallStaticMethodV<jlong>,
1403   _Jv_JNI_CallStaticMethodA<jlong>,
1404   _Jv_JNI_CallStaticMethod<jfloat>,
1405   _Jv_JNI_CallStaticMethodV<jfloat>,
1406   _Jv_JNI_CallStaticMethodA<jfloat>,
1407   _Jv_JNI_CallStaticMethod<jdouble>,
1408   _Jv_JNI_CallStaticMethodV<jdouble>,
1409   _Jv_JNI_CallStaticMethodA<jdouble>,
1410   _Jv_JNI_CallStaticVoidMethod,
1411   _Jv_JNI_CallStaticVoidMethodV,
1412   _Jv_JNI_CallStaticVoidMethodA,
1413
1414   _Jv_JNI_GetAnyFieldID<true>,
1415   _Jv_JNI_GetStaticField<jobject>,
1416   _Jv_JNI_GetStaticField<jboolean>,
1417   _Jv_JNI_GetStaticField<jbyte>,
1418   _Jv_JNI_GetStaticField<jchar>,
1419   _Jv_JNI_GetStaticField<jshort>,
1420   _Jv_JNI_GetStaticField<jint>,
1421   _Jv_JNI_GetStaticField<jlong>,
1422   _Jv_JNI_GetStaticField<jfloat>,
1423   _Jv_JNI_GetStaticField<jdouble>,
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_SetStaticField,
1433   _Jv_JNI_NewString,
1434   _Jv_JNI_GetStringLength,
1435   _Jv_JNI_GetStringChars,
1436   _Jv_JNI_ReleaseStringChars,
1437   _Jv_JNI_NewStringUTF,
1438   _Jv_JNI_GetStringUTFLength,
1439   _Jv_JNI_GetStringUTFChars,
1440   _Jv_JNI_ReleaseStringUTFChars,
1441   _Jv_JNI_GetArrayLength,
1442   _Jv_JNI_NewObjectArray,
1443   _Jv_JNI_GetObjectArrayElement,
1444   _Jv_JNI_SetObjectArrayElement,
1445   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1446   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1447   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1448   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1449   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1450   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1451   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1452   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
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_GetPrimitiveArrayElements,
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_ReleasePrimitiveArrayElements,
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_GetPrimitiveArrayRegion,
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   _Jv_JNI_SetPrimitiveArrayRegion,
1485   NOT_IMPL /* RegisterNatives */,
1486   NOT_IMPL /* UnregisterNatives */,
1487   _Jv_JNI_MonitorEnter,
1488   _Jv_JNI_MonitorExit,
1489   NOT_IMPL /* GetJavaVM */,
1490
1491   _Jv_JNI_GetStringRegion,
1492   _Jv_JNI_GetStringUTFRegion,
1493   _Jv_JNI_GetPrimitiveArrayCritical,
1494   _Jv_JNI_ReleasePrimitiveArrayCritical,
1495   _Jv_JNI_GetStringCritical,
1496   _Jv_JNI_ReleaseStringCritical,
1497
1498   NOT_IMPL /* newweakglobalref */,
1499   NOT_IMPL /* deleteweakglobalref */,
1500
1501   _Jv_JNI_ExceptionCheck
1502 };