natConstructor.cc (newInstance): Use _Jv_CallAnyMethodA.
[platform/upstream/gcc.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
21 // Must define this before jni.h.
22 #define GCJ_JV_JNIENV_FRIEND \
23     friend jthrowable &get_throwable (JNIEnv *)
24
25 #include <gcj/cni.h>
26 #include <jvm.h>
27 #include <java-assert.h>
28 #include <jni.h>
29 #include <gcj/field.h>
30 #include <java/lang/Throwable.h>
31 #include <java/lang/ArrayIndexOutOfBoundsException.h>
32 #include <java/lang/InstantiationException.h>
33 #include <java/lang/NoSuchFieldError.h>
34 #include <java/lang/NoSuchMethodError.h>
35 #include <java/lang/reflect/Constructor.h>
36 #include <java/lang/reflect/Modifier.h>
37
38 #define ClassClass _CL_Q34java4lang5Class
39 extern java::lang::Class ClassClass;
40 #define ObjectClass _CL_Q34java4lang6Object
41 extern java::lang::Class ObjectClass;
42
43 // This enum is used to select different template instantiations in
44 // the invocation code.
45 enum invocation_type
46 {
47   normal,
48   nonvirtual,
49   static_type,
50   constructor
51 };
52
53 \f
54
55 // Tell the GC that a certain pointer is live.
56 static void
57 mark_for_gc (void *)
58 {
59   // FIXME.
60 }
61
62 // Unmark a pointer.
63 static void
64 unmark_for_gc (void *)
65 {
66   // FIXME.
67 }
68
69 // Return throwable in env.
70 jthrowable &
71 get_throwable (JNIEnv *env)
72 {
73   return env->ex;
74 }
75
76 \f
77
78 static jint
79 _Jv_JNI_GetVersion (JNIEnv *)
80 {
81   return JNI_VERSION_1_2;
82 }
83
84 static jclass
85 _Jv_JNI_GetSuperclass (JNIEnv *, jclass clazz)
86 {
87   return clazz->getSuperclass ();
88 }
89
90 static jboolean
91 IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
92 {
93   return clazz1->isAssignableFrom (clazz2);
94 }
95
96 static jint
97 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
98 {
99   get_throwable (env) = obj;
100   return 0;
101 }
102
103 static jint
104 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
105 {
106   using namespace java::lang::reflect;
107
108   JArray<jclass> *argtypes
109     = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
110
111   jclass *elts = elements (argtypes);
112   elts[0] = &StringClass;
113
114   // FIXME: exception processing.
115   Constructor *cons = clazz->getConstructor (argtypes);
116
117   jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
118   jobject *velts = elements (values);
119   velts[0] = JvNewStringUTF (message);
120
121   // FIXME: exception processing.
122   jobject obj = cons->newInstance (values);
123
124   get_throwable (env) = reinterpret_cast<jthrowable> (obj);
125   return 0;
126 }
127
128 static jthrowable
129 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
130 {
131   return get_throwable (env);
132 }
133
134 static void
135 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
136 {
137   if (get_throwable (env) != NULL)
138     get_throwable (env)->printStackTrace();
139 }
140
141 static void
142 _Jv_JNI_ExceptionClear (JNIEnv *env)
143 {
144   get_throwable (env) = NULL;
145 }
146
147 static void
148 _Jv_JNI_FatalError (JNIEnv *, const char *message)
149 {
150   JvFail (message);
151 }
152
153 static jboolean
154 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
155 {
156   return obj1 == obj2;
157 }
158
159 static jobject
160 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
161 {
162   jobject obj = NULL;
163   using namespace java::lang::reflect;
164   if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
165     get_throwable (env) = new java::lang::InstantiationException ();
166   else
167     {
168       // FIXME: exception processing.
169       // FIXME: will this work for String?
170       obj = JvAllocObject (clazz);
171     }
172
173   return obj;
174 }
175
176 static jclass
177 _Jv_JNI_GetObjectClass (JNIEnv *, jobject obj)
178 {
179   return obj->getClass();
180 }
181
182 static jboolean
183 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
184 {
185   return clazz->isInstance(obj);
186 }
187
188 \f
189
190 //
191 // This section concerns method invocation.
192 //
193
194 template<jboolean is_static>
195 static jmethodID
196 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
197                         const char *name, const char *sig)
198 {
199   // FIXME: exception processing.
200   _Jv_InitClass (clazz);
201
202   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
203   _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
204
205   JvAssert (! clazz->isPrimitive());
206
207   using namespace java::lang::reflect;
208
209   while (clazz != NULL)
210     {
211       jint count = JvNumMethods (clazz);
212       jmethodID meth = JvGetFirstMethod (clazz);
213
214       for (jint i = 0; i < count; ++i)
215         {
216           if (((is_static && Modifier::isStatic (meth->accflags))
217                || (! is_static && ! Modifier::isStatic (meth->accflags)))
218               && _Jv_equalUtf8Consts (meth->name, name_u)
219               && _Jv_equalUtf8Consts (meth->signature, sig_u))
220             return meth;
221
222           meth = meth->getNextMethod();
223         }
224
225       clazz = clazz->getSuperclass ();
226     }
227
228   get_throwable (env) = new java::lang::NoSuchMethodError ();
229   return NULL;
230 }
231
232 // This is a helper function which turns a va_list into an array of
233 // `jvalue's.  It needs signature information in order to do its work.
234 // The array of values must already be allocated.
235 static void
236 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
237 {
238   jclass *arg_elts = elements (arg_types);
239   for (int i = 0; i < arg_types->length; ++i)
240     {
241       if (arg_elts[i] == JvPrimClass (byte))
242         values[i].b = va_arg (vargs, jbyte);
243       else if (arg_elts[i] == JvPrimClass (short))
244         values[i].s = va_arg (vargs, jshort);
245       else if (arg_elts[i] == JvPrimClass (int))
246         values[i].i = va_arg (vargs, jint);
247       else if (arg_elts[i] == JvPrimClass (long))
248         values[i].j = va_arg (vargs, jlong);
249       else if (arg_elts[i] == JvPrimClass (float))
250         values[i].f = va_arg (vargs, jfloat);
251       else if (arg_elts[i] == JvPrimClass (double))
252         values[i].d = va_arg (vargs, jdouble);
253       else if (arg_elts[i] == JvPrimClass (boolean))
254         values[i].z = va_arg (vargs, jboolean);
255       else if (arg_elts[i] == JvPrimClass (char))
256         values[i].c = va_arg (vargs, jchar);
257       else
258         {
259           // An object.
260           values[i].l = va_arg (vargs, jobject);
261         }
262     }
263 }
264
265 // This can call any sort of method: virtual, "nonvirtual", static, or
266 // constructor.
267 template<typename T, invocation_type style>
268 static T
269 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
270                         jmethodID id, va_list vargs)
271 {
272   if (style == normal)
273     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
274
275   jclass decl_class = klass ? klass : obj->getClass ();
276   JvAssert (decl_class != NULL);
277
278   jclass return_type;
279   JArray<jclass> *arg_types;
280   // FIXME: exception processing.
281   _Jv_GetTypesFromSignature (id, decl_class,
282                              &arg_types, &return_type);
283
284   jvalue args[arg_types->length];
285   array_from_valist (args, arg_types, vargs);
286
287   jvalue result;
288   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
289                                       style == constructor,
290                                       arg_types, args, &result);
291
292   if (ex != NULL)
293     get_throwable (env) = ex;
294
295   // We cheat a little here.  FIXME.
296   return * (T *) &result;
297 }
298
299 template<typename T, invocation_type style>
300 static T
301 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
302                        jmethodID method, ...)
303 {
304   va_list args;
305   T result;
306
307   va_start (args, method);
308   result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
309   va_end (args);
310
311   return result;
312 }
313
314 template<typename T, invocation_type style>
315 static T
316 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
317                         jmethodID id, jvalue *args)
318 {
319   if (style == normal)
320     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
321
322   jclass decl_class = klass ? klass : obj->getClass ();
323   JvAssert (decl_class != NULL);
324
325   jclass return_type;
326   JArray<jclass> *arg_types;
327   // FIXME: exception processing.
328   _Jv_GetTypesFromSignature (id, decl_class,
329                              &arg_types, &return_type);
330
331   jvalue result;
332   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
333                                       style == constructor,
334                                       arg_types, args, &result);
335
336   if (ex != NULL)
337     get_throwable (env) = ex;
338
339   // We cheat a little here.  FIXME.
340   return * (T *) &result;
341 }
342
343 template<invocation_type style>
344 static void
345 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
346                             jmethodID id, va_list vargs)
347 {
348   if (style == normal)
349     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
350
351   jclass decl_class = klass ? klass : obj->getClass ();
352   JvAssert (decl_class != NULL);
353
354   jclass return_type;
355   JArray<jclass> *arg_types;
356   // FIXME: exception processing.
357   _Jv_GetTypesFromSignature (id, decl_class,
358                              &arg_types, &return_type);
359
360   jvalue args[arg_types->length];
361   array_from_valist (args, arg_types, vargs);
362
363   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
364                                       style == constructor,
365                                       arg_types, args, NULL);
366
367   if (ex != NULL)
368     get_throwable (env) = ex;
369 }
370
371 template<invocation_type style>
372 static void
373 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
374                            jmethodID method, ...)
375 {
376   va_list args;
377
378   va_start (args, method);
379   _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
380   va_end (args);
381 }
382
383 template<invocation_type style>
384 static void
385 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
386                             jmethodID id, jvalue *args)
387 {
388   if (style == normal)
389     id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
390
391   jclass decl_class = klass ? klass : obj->getClass ();
392   JvAssert (decl_class != NULL);
393
394   jclass return_type;
395   JArray<jclass> *arg_types;
396   // FIXME: exception processing.
397   _Jv_GetTypesFromSignature (id, decl_class,
398                              &arg_types, &return_type);
399
400   jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
401                                       style == constructor,
402                                       arg_types, args, NULL);
403
404   if (ex != NULL)
405     get_throwable (env) = ex;
406 }
407
408 // Functions with this signature are used to implement functions in
409 // the CallMethod family.
410 template<typename T>
411 static T
412 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
413 {
414   return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
415 }
416
417 // Functions with this signature are used to implement functions in
418 // the CallMethod family.
419 template<typename T>
420 static T
421 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
422 {
423   va_list args;
424   T result;
425
426   va_start (args, id);
427   result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
428   va_end (args);
429
430   return result;
431 }
432
433 // Functions with this signature are used to implement functions in
434 // the CallMethod family.
435 template<typename T>
436 static T
437 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
438 {
439   return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
440 }
441
442 static void
443 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
444 {
445   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
446 }
447
448 static void
449 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
450 {
451   va_list args;
452
453   va_start (args, id);
454   _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
455   va_end (args);
456 }
457
458 static void
459 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
460 {
461   _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
462 }
463
464 // Functions with this signature are used to implement functions in
465 // the CallStaticMethod family.
466 template<typename T>
467 static T
468 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
469                            jmethodID id, va_list args)
470 {
471   return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
472 }
473
474 // Functions with this signature are used to implement functions in
475 // the CallStaticMethod family.
476 template<typename T>
477 static T
478 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
479 {
480   va_list args;
481   T result;
482
483   va_start (args, id);
484   result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
485                                                    id, args);
486   va_end (args);
487
488   return result;
489 }
490
491 // Functions with this signature are used to implement functions in
492 // the CallStaticMethod family.
493 template<typename T>
494 static T
495 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
496                            jvalue *args)
497 {
498   return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
499 }
500
501 static void
502 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
503                                va_list args)
504 {
505   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
506 }
507
508 static void
509 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
510 {
511   va_list args;
512
513   va_start (args, id);
514   _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
515   va_end (args);
516 }
517
518 static void
519 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
520                                jvalue *args)
521 {
522   _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
523 }
524
525 static jobject
526 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
527                     jmethodID id, va_list args)
528 {
529   return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
530                                                        id, args);
531 }
532
533 static jobject
534 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
535 {
536   va_list args;
537   jobject result;
538
539   va_start (args, id);
540   result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
541                                                          id, args);
542   va_end (args);
543
544   return result;
545 }
546
547 static jobject
548 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
549                     jvalue *args)
550 {
551   return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
552                                                        id, args);
553 }
554
555 \f
556
557 template<typename T>
558 static T
559 _Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field) 
560 {
561   T *ptr = (T *) ((char *) obj + field->getOffset ());
562   return *ptr;
563 }
564
565 template<typename T>
566 static void
567 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
568 {
569   T *ptr = (T *) ((char *) obj + field->getOffset ());
570   *ptr = value;
571 }
572
573 template<jboolean is_static>
574 static jfieldID
575 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
576                        const char *name, const char *sig)
577 {
578   // FIXME: exception processing.
579   _Jv_InitClass (clazz);
580
581   _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
582
583   jclass field_class = NULL;
584   if (sig[0] == '[')
585     field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
586   else
587     {
588       _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
589       field_class = _Jv_FindClass (sig_u, NULL);
590     }
591
592   // FIXME: what if field_class == NULL?
593
594   while (clazz != NULL)
595     {
596       jint count = (is_static
597                     ? JvNumStaticFields (clazz)
598                     : JvNumInstanceFields (clazz));
599       jfieldID field = (is_static
600                         ? JvGetFirstStaticField (clazz)
601                         : JvGetFirstInstanceField (clazz));
602       for (jint i = 0; i < count; ++i)
603         {
604           // The field is resolved as a side effect of class
605           // initialization.
606           JvAssert (field->isResolved ());
607
608           _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
609
610           if (_Jv_equalUtf8Consts (f_name, a_name)
611               && field->getClass() == field_class)
612             return field;
613
614           field = field->getNextField ();
615         }
616
617       clazz = clazz->getSuperclass ();
618     }
619
620   get_throwable (env) = new java::lang::NoSuchFieldError ();
621   return NULL;
622 }
623
624 template<typename T>
625 static T
626 _Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
627 {
628   T *ptr = (T *) field->u.addr;
629   return *ptr;
630 }
631
632 template<typename T>
633 static void
634 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
635 {
636   T *ptr = (T *) field->u.addr;
637   *ptr = value;
638 }
639
640 static jstring
641 _Jv_JNI_NewString (JNIEnv *, const jchar *unichars, jsize len)
642 {
643   // FIXME: exception processing.
644   jstring r = _Jv_NewString (unichars, len);
645   return r;
646 }
647
648 static jsize
649 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
650 {
651   return string->length();
652 }
653
654 static const jchar *
655 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
656 {
657   jchar *result = _Jv_GetStringChars (string);
658   mark_for_gc (result);
659   if (isCopy)
660     *isCopy = false;
661   return (const jchar *) result;
662 }
663
664 static void
665 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring, const jchar *chars)
666 {
667   unmark_for_gc ((void *) chars);
668 }
669
670 static jstring
671 _Jv_JNI_NewStringUTF (JNIEnv *, const char *bytes)
672 {
673   // FIXME: exception processing.
674   jstring r = JvNewStringUTF (bytes);
675   return r;
676 }
677
678 static jsize
679 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
680 {
681   return JvGetStringUTFLength (string);
682 }
683
684 static const char *
685 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
686 {
687   jsize len = JvGetStringUTFLength (string);
688   // FIXME: exception processing.
689   char *r = (char *) _Jv_Malloc (len + 1);
690   JvGetStringUTFRegion (string, 0, len, r);
691   r[len] = '\0';
692
693   if (isCopy)
694     *isCopy = true;
695
696   return (const char *) r;
697 }
698
699 static void
700 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
701 {
702   _Jv_Free ((void *) utf);
703 }
704
705 static jsize
706 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
707 {
708   return array->length;
709 }
710
711 static jarray
712 _Jv_JNI_NewObjectArray (JNIEnv *, jsize length, jclass elementClass,
713                         jobject init)
714 {
715   // FIXME: exception processing.
716   jarray result = JvNewObjectArray (length, elementClass, init);
717   return result;
718 }
719
720 static jobject
721 _Jv_JNI_GetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index)
722 {
723   jobject *elts = elements (array);
724   return elts[index];
725 }
726
727 static void
728 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
729                                jobject value)
730 {
731   // FIXME: exception processing.
732   _Jv_CheckArrayStore (array, value);
733   jobject *elts = elements (array);
734   elts[index] = value;
735 }
736
737 template<typename T, jclass K>
738 static JArray<T> *
739 _Jv_JNI_NewPrimitiveArray (JNIEnv *, jsize length)
740 {
741   return (JArray<T> *) _Jv_NewPrimArray (K, length);
742 }
743
744 template<typename T>
745 static T *
746 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
747                                    jboolean *isCopy)
748 {
749   T *elts = elements (array);
750   if (isCopy)
751     {
752       // We elect never to copy.
753       *isCopy = false;
754     }
755   mark_for_gc (elts);
756   return elts;
757 }
758
759 template<typename T>
760 static void
761 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *,
762                                        T *elems, jint /* mode */)
763 {
764   // Note that we ignore MODE.  We can do this because we never copy
765   // the array elements.  My reading of the JNI documentation is that
766   // this is an option for the implementor.
767   unmark_for_gc (elems);
768 }
769
770 template<typename T>
771 static void
772 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
773                                  jsize start, jsize len,
774                                  T *buf)
775 {
776   if (start < 0 || len >= array->length || start + len >= array->length)
777     {
778       // FIXME: index.
779       get_throwable (env) = new java::lang::ArrayIndexOutOfBoundsException ();
780     }
781   else
782     {
783       T *elts = elements (array) + start;
784       memcpy (buf, elts, len * sizeof (T));
785     }
786 }
787
788 template<typename T>
789 static void
790 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
791                                  jsize start, jsize len, T *buf)
792 {
793   if (start < 0 || len >= array->length || start + len >= array->length)
794     {
795       // FIXME: index.
796       get_throwable (env) = new java::lang::ArrayIndexOutOfBoundsException ();
797     }
798   else
799     {
800       T *elts = elements (array) + start;
801       memcpy (elts, buf, len * sizeof (T));
802     }
803 }
804
805 static jint
806 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
807 {
808   // FIXME: exception processing.
809   jint r = _Jv_MonitorEnter (obj);
810   return r;
811 }
812
813 static jint
814 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
815 {
816   // FIXME: exception processing.
817   jint r = _Jv_MonitorExit (obj);
818   return r;
819 }
820
821 // JDK 1.2
822 jobject
823 _Jv_JNI_ToReflectedField (JNIEnv *, jclass cls, jfieldID fieldID)
824 {
825   java::lang::reflect::Field *field = new java::lang::reflect::Field();
826   field->declaringClass = cls;
827   field->offset = (char*) fieldID - (char *) cls->fields;
828   field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
829   return field;
830 }
831
832 // JDK 1.2
833 jfieldID
834 _Jv_JNI_FromReflectedField (JNIEnv *, java::lang::reflect::Field *field)
835 {
836   return _Jv_FromReflectedField (field);
837 }
838
839 #define NOT_IMPL NULL
840 #define RESERVED NULL
841
842 struct JNINativeInterface _Jv_JNIFunctions =
843 {
844   RESERVED,
845   RESERVED,
846   RESERVED,
847   RESERVED,
848   _Jv_JNI_GetVersion,
849   NOT_IMPL /* DefineClass */,
850   NOT_IMPL /* FindClass */,
851   RESERVED,
852   RESERVED,
853   RESERVED,
854   _Jv_JNI_GetSuperclass,
855   IsAssignableFrom,
856   RESERVED,
857   _Jv_JNI_Throw,
858   _Jv_JNI_ThrowNew,
859   _Jv_JNI_ExceptionOccurred,
860   _Jv_JNI_ExceptionDescribe,
861   _Jv_JNI_ExceptionClear,
862   _Jv_JNI_FatalError,
863   RESERVED,
864   RESERVED,
865   NOT_IMPL /* NewGlobalRef */,
866   NOT_IMPL /* DeleteGlobalRef */,
867   NOT_IMPL /* DeleteLocalRef */,
868   _Jv_JNI_IsSameObject,
869   RESERVED,
870   RESERVED,
871   _Jv_JNI_AllocObject,
872   _Jv_JNI_NewObject,
873   _Jv_JNI_NewObjectV,
874   _Jv_JNI_NewObjectA,
875   _Jv_JNI_GetObjectClass,
876   _Jv_JNI_IsInstanceOf,
877   _Jv_JNI_GetAnyMethodID<false>,
878
879   _Jv_JNI_CallMethod<jobject>,
880   _Jv_JNI_CallMethodV<jobject>,
881   _Jv_JNI_CallMethodA<jobject>,
882   _Jv_JNI_CallMethod<jboolean>,
883   _Jv_JNI_CallMethodV<jboolean>,
884   _Jv_JNI_CallMethodA<jboolean>,
885   _Jv_JNI_CallMethod<jbyte>,
886   _Jv_JNI_CallMethodV<jbyte>,
887   _Jv_JNI_CallMethodA<jbyte>,
888   _Jv_JNI_CallMethod<jchar>,
889   _Jv_JNI_CallMethodV<jchar>,
890   _Jv_JNI_CallMethodA<jchar>,
891   _Jv_JNI_CallMethod<jshort>,
892   _Jv_JNI_CallMethodV<jshort>,
893   _Jv_JNI_CallMethodA<jshort>,
894   _Jv_JNI_CallMethod<jint>,
895   _Jv_JNI_CallMethodV<jint>,
896   _Jv_JNI_CallMethodA<jint>,
897   _Jv_JNI_CallMethod<jlong>,
898   _Jv_JNI_CallMethodV<jlong>,
899   _Jv_JNI_CallMethodA<jlong>,
900   _Jv_JNI_CallMethod<jfloat>,
901   _Jv_JNI_CallMethodV<jfloat>,
902   _Jv_JNI_CallMethodA<jfloat>,
903   _Jv_JNI_CallMethod<jdouble>,
904   _Jv_JNI_CallMethodV<jdouble>,
905   _Jv_JNI_CallMethodA<jdouble>,
906   _Jv_JNI_CallVoidMethod,
907   _Jv_JNI_CallVoidMethodV,
908   _Jv_JNI_CallVoidMethodA,
909
910   // Nonvirtual method invocation functions follow.
911   _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
912   _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
913   _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
914   _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
915   _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
916   _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
917   _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
918   _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
919   _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
920   _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
921   _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
922   _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
923   _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
924   _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
925   _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
926   _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
927   _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
928   _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
929   _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
930   _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
931   _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
932   _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
933   _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
934   _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
935   _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
936   _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
937   _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
938   _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
939   _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
940   _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
941
942   _Jv_JNI_GetAnyFieldID<false>,
943   _Jv_JNI_GetField<jobject>,
944   _Jv_JNI_GetField<jboolean>,
945   _Jv_JNI_GetField<jbyte>,
946   _Jv_JNI_GetField<jchar>,
947   _Jv_JNI_GetField<jshort>,
948   _Jv_JNI_GetField<jint>,
949   _Jv_JNI_GetField<jlong>,
950   _Jv_JNI_GetField<jfloat>,
951   _Jv_JNI_GetField<jdouble>,
952   _Jv_JNI_SetField,
953   _Jv_JNI_SetField,
954   _Jv_JNI_SetField,
955   _Jv_JNI_SetField,
956   _Jv_JNI_SetField,
957   _Jv_JNI_SetField,
958   _Jv_JNI_SetField,
959   _Jv_JNI_SetField,
960   _Jv_JNI_SetField,
961   _Jv_JNI_GetAnyMethodID<true>,
962
963   _Jv_JNI_CallStaticMethod<jobject>,
964   _Jv_JNI_CallStaticMethodV<jobject>,
965   _Jv_JNI_CallStaticMethodA<jobject>,
966   _Jv_JNI_CallStaticMethod<jboolean>,
967   _Jv_JNI_CallStaticMethodV<jboolean>,
968   _Jv_JNI_CallStaticMethodA<jboolean>,
969   _Jv_JNI_CallStaticMethod<jbyte>,
970   _Jv_JNI_CallStaticMethodV<jbyte>,
971   _Jv_JNI_CallStaticMethodA<jbyte>,
972   _Jv_JNI_CallStaticMethod<jchar>,
973   _Jv_JNI_CallStaticMethodV<jchar>,
974   _Jv_JNI_CallStaticMethodA<jchar>,
975   _Jv_JNI_CallStaticMethod<jshort>,
976   _Jv_JNI_CallStaticMethodV<jshort>,
977   _Jv_JNI_CallStaticMethodA<jshort>,
978   _Jv_JNI_CallStaticMethod<jint>,
979   _Jv_JNI_CallStaticMethodV<jint>,
980   _Jv_JNI_CallStaticMethodA<jint>,
981   _Jv_JNI_CallStaticMethod<jlong>,
982   _Jv_JNI_CallStaticMethodV<jlong>,
983   _Jv_JNI_CallStaticMethodA<jlong>,
984   _Jv_JNI_CallStaticMethod<jfloat>,
985   _Jv_JNI_CallStaticMethodV<jfloat>,
986   _Jv_JNI_CallStaticMethodA<jfloat>,
987   _Jv_JNI_CallStaticMethod<jdouble>,
988   _Jv_JNI_CallStaticMethodV<jdouble>,
989   _Jv_JNI_CallStaticMethodA<jdouble>,
990   _Jv_JNI_CallStaticVoidMethod,
991   _Jv_JNI_CallStaticVoidMethodV,
992   _Jv_JNI_CallStaticVoidMethodA,
993
994   _Jv_JNI_GetAnyFieldID<true>,
995   _Jv_JNI_GetStaticField<jobject>,
996   _Jv_JNI_GetStaticField<jboolean>,
997   _Jv_JNI_GetStaticField<jbyte>,
998   _Jv_JNI_GetStaticField<jchar>,
999   _Jv_JNI_GetStaticField<jshort>,
1000   _Jv_JNI_GetStaticField<jint>,
1001   _Jv_JNI_GetStaticField<jlong>,
1002   _Jv_JNI_GetStaticField<jfloat>,
1003   _Jv_JNI_GetStaticField<jdouble>,
1004   _Jv_JNI_SetStaticField,
1005   _Jv_JNI_SetStaticField,
1006   _Jv_JNI_SetStaticField,
1007   _Jv_JNI_SetStaticField,
1008   _Jv_JNI_SetStaticField,
1009   _Jv_JNI_SetStaticField,
1010   _Jv_JNI_SetStaticField,
1011   _Jv_JNI_SetStaticField,
1012   _Jv_JNI_SetStaticField,
1013   _Jv_JNI_NewString,
1014   _Jv_JNI_GetStringLength,
1015   _Jv_JNI_GetStringChars,
1016   _Jv_JNI_ReleaseStringChars,
1017   _Jv_JNI_NewStringUTF,
1018   _Jv_JNI_GetStringUTFLength,
1019   _Jv_JNI_GetStringUTFChars,
1020   _Jv_JNI_ReleaseStringUTFChars,
1021   _Jv_JNI_GetArrayLength,
1022   _Jv_JNI_NewObjectArray,
1023   _Jv_JNI_GetObjectArrayElement,
1024   _Jv_JNI_SetObjectArrayElement,
1025   _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1026   _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1027   _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1028   _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1029   _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1030   _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1031   _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1032   _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1033   _Jv_JNI_GetPrimitiveArrayElements,
1034   _Jv_JNI_GetPrimitiveArrayElements,
1035   _Jv_JNI_GetPrimitiveArrayElements,
1036   _Jv_JNI_GetPrimitiveArrayElements,
1037   _Jv_JNI_GetPrimitiveArrayElements,
1038   _Jv_JNI_GetPrimitiveArrayElements,
1039   _Jv_JNI_GetPrimitiveArrayElements,
1040   _Jv_JNI_GetPrimitiveArrayElements,
1041   _Jv_JNI_ReleasePrimitiveArrayElements,
1042   _Jv_JNI_ReleasePrimitiveArrayElements,
1043   _Jv_JNI_ReleasePrimitiveArrayElements,
1044   _Jv_JNI_ReleasePrimitiveArrayElements,
1045   _Jv_JNI_ReleasePrimitiveArrayElements,
1046   _Jv_JNI_ReleasePrimitiveArrayElements,
1047   _Jv_JNI_ReleasePrimitiveArrayElements,
1048   _Jv_JNI_ReleasePrimitiveArrayElements,
1049   _Jv_JNI_GetPrimitiveArrayRegion,
1050   _Jv_JNI_GetPrimitiveArrayRegion,
1051   _Jv_JNI_GetPrimitiveArrayRegion,
1052   _Jv_JNI_GetPrimitiveArrayRegion,
1053   _Jv_JNI_GetPrimitiveArrayRegion,
1054   _Jv_JNI_GetPrimitiveArrayRegion,
1055   _Jv_JNI_GetPrimitiveArrayRegion,
1056   _Jv_JNI_GetPrimitiveArrayRegion,
1057   _Jv_JNI_SetPrimitiveArrayRegion,
1058   _Jv_JNI_SetPrimitiveArrayRegion,
1059   _Jv_JNI_SetPrimitiveArrayRegion,
1060   _Jv_JNI_SetPrimitiveArrayRegion,
1061   _Jv_JNI_SetPrimitiveArrayRegion,
1062   _Jv_JNI_SetPrimitiveArrayRegion,
1063   _Jv_JNI_SetPrimitiveArrayRegion,
1064   _Jv_JNI_SetPrimitiveArrayRegion,
1065   NOT_IMPL /* RegisterNatives */,
1066   NOT_IMPL /* UnregisterNatives */,
1067   _Jv_JNI_MonitorEnter,
1068   _Jv_JNI_MonitorExit,
1069   NOT_IMPL /* GetJavaVM */,
1070 };