* src/native/jni.hpp (JNI_VERSION_CACAO): Added to be able to reveal ourselves.
[cacao.git] / src / native / jni.cpp
1 /* src/native/jni.cpp - implementation of the Java Native Interface functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <string.h>
31
32 #include "vm/types.h"
33
34 #include "mm/gc.hpp"
35 #include "mm/memory.hpp"
36
37 #include "native/jni.hpp"
38 #include "native/llni.h"
39 #include "native/localref.hpp"
40 #include "native/native.hpp"
41
42 #if defined(ENABLE_JVMTI)
43 # include "native/jvmti/cacaodbg.h"
44 #endif
45
46 #include "threads/lock.hpp"
47 #include "threads/mutex.hpp"
48 #include "threads/thread.hpp"
49
50 #include "toolbox/logging.hpp"
51
52 #include "vm/array.hpp"
53 #include "vm/jit/builtin.hpp"
54 #include "vm/exceptions.hpp"
55 #include "vm/global.h"
56 #include "vm/globals.hpp"
57 #include "vm/initialize.hpp"
58 #include "vm/javaobjects.hpp"
59 #include "vm/loader.hpp"
60 #include "vm/options.h"
61 #include "vm/primitive.hpp"
62 #include "vm/resolve.hpp"
63 #include "vm/statistics.h"
64 #include "vm/string.hpp"
65 #include "vm/vm.hpp"
66
67 #include "vm/jit/asmpart.h"
68 #include "vm/jit/jit.hpp"
69 #include "vm/jit/stacktrace.hpp"
70
71
72 /* debug **********************************************************************/
73
74 #if !defined(NDEBUG)
75
76 # define TRACEJNICALLS(x)                                               \
77     do {                                                                                \
78         if (opt_TraceJNICalls) {                                \
79             log_println x;                                              \
80         }                                                                               \
81     } while (0)
82
83 # define TRACEJNICALLSENTER(x)                                                                  \
84     do {                                                                                                                \
85         if (opt_TraceJNICalls) {                                                                \
86                         log_start();                                                                            \
87             log_print x;                                                                                \
88         }                                                                                                               \
89     } while (0)
90
91 # define TRACEJNICALLSEXIT(x)                                                                   \
92     do {                                                                                                                \
93         if (opt_TraceJNICalls) {                                                                \
94                         log_print x;                                                                            \
95                         log_finish();                                                                           \
96         }                                                                                                               \
97     } while (0)
98
99 #else
100
101 # define TRACEJNICALLS(x)
102 # define TRACEJNICALLSENTER(x)
103 # define TRACEJNICALLSEXIT(x)
104
105 #endif
106
107
108 /* global variables ***********************************************************/
109
110 /* global reference table *****************************************************/
111
112 /* hashsize must be power of 2 */
113
114 #define HASHTABLE_GLOBAL_REF_SIZE    64 /* initial size of globalref-hash     */
115
116 static hashtable *hashtable_global_ref; /* hashtable for globalrefs           */
117
118
119 /* direct buffer stuff ********************************************************/
120
121 #if defined(ENABLE_JAVASE)
122 static classinfo *class_java_nio_Buffer;
123
124 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
125
126 static classinfo *class_java_nio_DirectByteBufferImpl;
127 static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
128
129 #  if SIZEOF_VOID_P == 8
130 static classinfo *class_gnu_classpath_Pointer64;
131 #  else
132 static classinfo *class_gnu_classpath_Pointer32;
133 #  endif
134
135 static methodinfo *dbbirw_init;
136
137 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
138
139 static classinfo *class_sun_nio_ch_DirectBuffer;
140 static classinfo *class_java_nio_DirectByteBuffer;
141
142 static methodinfo *dbb_init;
143
144 # endif
145 #endif
146
147
148 /* some forward declarations **************************************************/
149
150 extern "C" {
151 jobject jni_NewLocalRef(JNIEnv *env, jobject ref);
152 }
153
154
155 /* jni_init ********************************************************************
156
157    Initialize the JNI subsystem.
158
159 *******************************************************************************/
160
161 bool jni_init(void)
162 {
163         TRACESUBSYSTEMINITIALIZATION("jni_init");
164
165         /* create global ref hashtable */
166
167         hashtable_global_ref = NEW(hashtable);
168
169         hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
170
171
172 #if defined(ENABLE_JAVASE)
173         /* Direct buffer stuff. */
174
175         if (!(class_java_nio_Buffer =
176                   load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
177                 !link_class(class_java_nio_Buffer))
178                 return false;
179
180 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
181
182         if (!(class_java_nio_DirectByteBufferImpl =
183                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
184                 !link_class(class_java_nio_DirectByteBufferImpl))
185                 return false;
186
187         if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
188                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
189                 !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
190                 return false;
191
192         if (!(dbbirw_init =
193                 class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
194                                                         utf_init,
195                                                         utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
196                 return false;
197
198 #  if SIZEOF_VOID_P == 8
199         if (!(class_gnu_classpath_Pointer64 =
200                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
201                 !link_class(class_gnu_classpath_Pointer64))
202                 return false;
203 #  else
204         if (!(class_gnu_classpath_Pointer32 =
205                   load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
206                 !link_class(class_gnu_classpath_Pointer32))
207                 return false;
208 #  endif
209
210 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
211
212         if (!(class_sun_nio_ch_DirectBuffer =
213                   load_class_bootstrap(utf_new_char("sun/nio/ch/DirectBuffer"))))
214                 vm_abort("jni_init: loading sun/nio/ch/DirectBuffer failed");
215
216         if (!link_class(class_sun_nio_ch_DirectBuffer))
217                 vm_abort("jni_init: linking sun/nio/ch/DirectBuffer failed");
218
219         if (!(class_java_nio_DirectByteBuffer =
220                   load_class_bootstrap(utf_new_char("java/nio/DirectByteBuffer"))))
221                 vm_abort("jni_init: loading java/nio/DirectByteBuffer failed");
222
223         if (!link_class(class_java_nio_DirectByteBuffer))
224                 vm_abort("jni_init: linking java/nio/DirectByteBuffer failed");
225
226         if (!(dbb_init =
227                   class_resolvemethod(class_java_nio_DirectByteBuffer,
228                                                           utf_init,
229                                                           utf_new_char("(JI)V"))))
230                 vm_abort("jni_init: resolving java/nio/DirectByteBuffer.init(JI)V failed");
231
232 # endif
233
234 #endif /* defined(ENABLE_JAVASE) */
235
236         return true;
237 }
238
239
240 /* jni_version_check ***********************************************************
241
242    Check if the given JNI version is supported.
243
244    IN:
245        version....JNI version to check
246
247    RETURN VALUE:
248        true.......supported
249        false......not supported
250
251 *******************************************************************************/
252
253 bool jni_version_check(int version)
254 {
255         switch (version) {
256         case JNI_VERSION_1_1:
257         case JNI_VERSION_1_2:
258         case JNI_VERSION_1_4:
259         case JNI_VERSION_1_6:
260                 return true;
261         default:
262                 return false;
263         }
264 }
265
266
267 /* _Jv_jni_CallObjectMethod ****************************************************
268
269    Internal function to call Java Object methods.
270
271 *******************************************************************************/
272
273 static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
274                                                                                            vftbl_t *vftbl,
275                                                                                            methodinfo *m, va_list ap)
276 {
277         methodinfo    *resm;
278         java_handle_t *ro;
279
280         STATISTICS(jniinvokation());
281
282         if (m == NULL) {
283                 exceptions_throw_nullpointerexception();
284                 return NULL;
285         }
286
287         /* Class initialization is done by the JIT compiler.  This is ok
288            since a static method always belongs to the declaring class. */
289
290         if (m->flags & ACC_STATIC) {
291                 /* For static methods we reset the object. */
292
293                 if (o != NULL)
294                         o = NULL;
295
296                 /* for convenience */
297
298                 resm = m;
299
300         } else {
301                 /* For instance methods we make a virtual function table lookup. */
302
303                 resm = method_vftbl_lookup(vftbl, m);
304         }
305
306         STATISTICS(jnicallXmethodnvokation());
307
308         ro = vm_call_method_valist(resm, o, ap);
309
310         return ro;
311 }
312
313
314 /* _Jv_jni_CallObjectMethodA ***************************************************
315
316    Internal function to call Java Object methods.
317
318 *******************************************************************************/
319
320 static java_handle_t *_Jv_jni_CallObjectMethodA(java_handle_t *o,
321                                                                                                 vftbl_t *vftbl,
322                                                                                                 methodinfo *m,
323                                                                                                 const jvalue *args)
324 {
325         methodinfo    *resm;
326         java_handle_t *ro;
327
328         STATISTICS(jniinvokation());
329
330         if (m == NULL) {
331                 exceptions_throw_nullpointerexception();
332                 return NULL;
333         }
334
335         /* Class initialization is done by the JIT compiler.  This is ok
336            since a static method always belongs to the declaring class. */
337
338         if (m->flags & ACC_STATIC) {
339                 /* For static methods we reset the object. */
340
341                 if (o != NULL)
342                         o = NULL;
343
344                 /* for convenience */
345
346                 resm = m;
347
348         } else {
349                 /* For instance methods we make a virtual function table lookup. */
350
351                 resm = method_vftbl_lookup(vftbl, m);
352         }
353
354         STATISTICS(jnicallXmethodnvokation());
355
356         ro = vm_call_method_jvalue(resm, o, args);
357
358         return ro;
359 }
360
361
362 /* _Jv_jni_CallIntMethod *******************************************************
363
364    Internal function to call Java integer class methods (boolean,
365    byte, char, short, int).
366
367 *******************************************************************************/
368
369 static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
370                                                                   methodinfo *m, va_list ap)
371 {
372         methodinfo *resm;
373         jint        i;
374
375         STATISTICS(jniinvokation());
376
377         if (m == NULL) {
378                 exceptions_throw_nullpointerexception();
379                 return 0;
380         }
381         
382         /* Class initialization is done by the JIT compiler.  This is ok
383            since a static method always belongs to the declaring class. */
384
385         if (m->flags & ACC_STATIC) {
386                 /* For static methods we reset the object. */
387
388                 if (o != NULL)
389                         o = NULL;
390
391                 /* for convenience */
392
393                 resm = m;
394
395         } else {
396                 /* For instance methods we make a virtual function table lookup. */
397
398                 resm = method_vftbl_lookup(vftbl, m);
399         }
400
401         STATISTICS(jnicallXmethodnvokation());
402
403         i = vm_call_method_int_valist(resm, o, ap);
404
405         return i;
406 }
407
408
409 /* _Jv_jni_CallIntMethodA ******************************************************
410
411    Internal function to call Java integer class methods (boolean,
412    byte, char, short, int).
413
414 *******************************************************************************/
415
416 static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
417                                                                    methodinfo *m, const jvalue *args)
418 {
419         methodinfo *resm;
420         jint        i;
421
422         STATISTICS(jniinvokation());
423
424         if (m == NULL) {
425                 exceptions_throw_nullpointerexception();
426                 return 0;
427         }
428         
429         /* Class initialization is done by the JIT compiler.  This is ok
430            since a static method always belongs to the declaring class. */
431
432         if (m->flags & ACC_STATIC) {
433                 /* For static methods we reset the object. */
434
435                 if (o != NULL)
436                         o = NULL;
437
438                 /* for convenience */
439
440                 resm = m;
441
442         } else {
443                 /* For instance methods we make a virtual function table lookup. */
444
445                 resm = method_vftbl_lookup(vftbl, m);
446         }
447
448         STATISTICS(jnicallXmethodnvokation());
449
450         i = vm_call_method_int_jvalue(resm, o, args);
451
452         return i;
453 }
454
455
456 /* _Jv_jni_CallLongMethod ******************************************************
457
458    Internal function to call Java long methods.
459
460 *******************************************************************************/
461
462 static jlong _Jv_jni_CallLongMethod(java_handle_t *o, vftbl_t *vftbl,
463                                                                         methodinfo *m, va_list ap)
464 {
465         methodinfo *resm;
466         jlong       l;
467
468         STATISTICS(jniinvokation());
469
470         if (m == NULL) {
471                 exceptions_throw_nullpointerexception();
472                 return 0;
473         }
474
475         /* Class initialization is done by the JIT compiler.  This is ok
476            since a static method always belongs to the declaring class. */
477
478         if (m->flags & ACC_STATIC) {
479                 /* For static methods we reset the object. */
480
481                 if (o != NULL)
482                         o = NULL;
483
484                 /* for convenience */
485
486                 resm = m;
487
488         } else {
489                 /* For instance methods we make a virtual function table lookup. */
490
491                 resm = method_vftbl_lookup(vftbl, m);
492         }
493
494         STATISTICS(jnicallXmethodnvokation());
495
496         l = vm_call_method_long_valist(resm, o, ap);
497
498         return l;
499 }
500
501
502 /* _Jv_jni_CallLongMethodA *****************************************************
503
504    Internal function to call Java long methods.
505
506 *******************************************************************************/
507
508 static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
509                                                                          methodinfo *m, const jvalue *args)
510 {
511         methodinfo *resm;
512         jlong       l;
513
514         STATISTICS(jniinvokation());
515
516         if (m == NULL) {
517                 exceptions_throw_nullpointerexception();
518                 return 0;
519         }
520
521         /* Class initialization is done by the JIT compiler.  This is ok
522            since a static method always belongs to the declaring class. */
523
524         if (m->flags & ACC_STATIC) {
525                 /* For static methods we reset the object. */
526
527                 if (o != NULL)
528                         o = NULL;
529
530                 /* for convenience */
531
532                 resm = m;
533         }
534         else {
535                 /* For instance methods we make a virtual function table lookup. */
536
537                 resm = method_vftbl_lookup(vftbl, m);
538         }
539
540         STATISTICS(jnicallXmethodnvokation());
541
542         l = vm_call_method_long_jvalue(resm, o, args);
543
544         return l;
545 }
546
547
548 /* _Jv_jni_CallFloatMethod *****************************************************
549
550    Internal function to call Java float methods.
551
552 *******************************************************************************/
553
554 static jfloat _Jv_jni_CallFloatMethod(java_handle_t *o, vftbl_t *vftbl,
555                                                                           methodinfo *m, va_list ap)
556 {
557         methodinfo *resm;
558         jfloat      f;
559
560         /* Class initialization is done by the JIT compiler.  This is ok
561            since a static method always belongs to the declaring class. */
562
563         if (m->flags & ACC_STATIC) {
564                 /* For static methods we reset the object. */
565
566                 if (o != NULL)
567                         o = NULL;
568
569                 /* for convenience */
570
571                 resm = m;
572
573         } else {
574                 /* For instance methods we make a virtual function table lookup. */
575
576                 resm = method_vftbl_lookup(vftbl, m);
577         }
578
579         STATISTICS(jnicallXmethodnvokation());
580
581         f = vm_call_method_float_valist(resm, o, ap);
582
583         return f;
584 }
585
586
587 /* _Jv_jni_CallFloatMethodA ****************************************************
588
589    Internal function to call Java float methods.
590
591 *******************************************************************************/
592
593 static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
594                                                                            methodinfo *m, const jvalue *args)
595 {
596         methodinfo *resm;
597         jfloat      f;
598
599         /* Class initialization is done by the JIT compiler.  This is ok
600            since a static method always belongs to the declaring class. */
601
602         if (m->flags & ACC_STATIC) {
603                 /* For static methods we reset the object. */
604
605                 if (o != NULL)
606                         o = NULL;
607
608                 /* for convenience */
609
610                 resm = m;
611         }
612         else {
613                 /* For instance methods we make a virtual function table lookup. */
614
615                 resm = method_vftbl_lookup(vftbl, m);
616         }
617
618         STATISTICS(jnicallXmethodnvokation());
619
620         f = vm_call_method_float_jvalue(resm, o, args);
621
622         return f;
623 }
624
625
626 /* _Jv_jni_CallDoubleMethod ****************************************************
627
628    Internal function to call Java double methods.
629
630 *******************************************************************************/
631
632 static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *o, vftbl_t *vftbl,
633                                                                                 methodinfo *m, va_list ap)
634 {
635         methodinfo *resm;
636         jdouble     d;
637
638         /* Class initialization is done by the JIT compiler.  This is ok
639            since a static method always belongs to the declaring class. */
640
641         if (m->flags & ACC_STATIC) {
642                 /* For static methods we reset the object. */
643
644                 if (o != NULL)
645                         o = NULL;
646
647                 /* for convenience */
648
649                 resm = m;
650
651         } else {
652                 /* For instance methods we make a virtual function table lookup. */
653
654                 resm = method_vftbl_lookup(vftbl, m);
655         }
656
657         d = vm_call_method_double_valist(resm, o, ap);
658
659         return d;
660 }
661
662
663 /* _Jv_jni_CallDoubleMethodA ***************************************************
664
665    Internal function to call Java double methods.
666
667 *******************************************************************************/
668
669 static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
670                                                                                  methodinfo *m, const jvalue *args)
671 {
672         methodinfo *resm;
673         jdouble     d;
674
675         /* Class initialization is done by the JIT compiler.  This is ok
676            since a static method always belongs to the declaring class. */
677
678         if (m->flags & ACC_STATIC) {
679                 /* For static methods we reset the object. */
680
681                 if (o != NULL)
682                         o = NULL;
683
684                 /* for convenience */
685
686                 resm = m;
687         }
688         else {
689                 /* For instance methods we make a virtual function table lookup. */
690
691                 resm = method_vftbl_lookup(vftbl, m);
692         }
693
694         d = vm_call_method_double_jvalue(resm, o, args);
695
696         return d;
697 }
698
699
700 /* _Jv_jni_CallVoidMethod ******************************************************
701
702    Internal function to call Java void methods.
703
704 *******************************************************************************/
705
706 static void _Jv_jni_CallVoidMethod(java_handle_t *o, vftbl_t *vftbl,
707                                                                    methodinfo *m, va_list ap)
708 {       
709         methodinfo *resm;
710
711         if (m == NULL) {
712                 exceptions_throw_nullpointerexception();
713                 return;
714         }
715
716         /* Class initialization is done by the JIT compiler.  This is ok
717            since a static method always belongs to the declaring class. */
718
719         if (m->flags & ACC_STATIC) {
720                 /* For static methods we reset the object. */
721
722                 if (o != NULL)
723                         o = NULL;
724
725                 /* for convenience */
726
727                 resm = m;
728
729         } else {
730                 /* For instance methods we make a virtual function table lookup. */
731
732                 resm = method_vftbl_lookup(vftbl, m);
733         }
734
735         STATISTICS(jnicallXmethodnvokation());
736
737         (void) vm_call_method_valist(resm, o, ap);
738 }
739
740
741 /* _Jv_jni_CallVoidMethodA *****************************************************
742
743    Internal function to call Java void methods.
744
745 *******************************************************************************/
746
747 static void _Jv_jni_CallVoidMethodA(java_handle_t *o, vftbl_t *vftbl,
748                                                                         methodinfo *m, const jvalue *args)
749 {       
750         methodinfo *resm;
751
752         if (m == NULL) {
753                 exceptions_throw_nullpointerexception();
754                 return;
755         }
756
757         /* Class initialization is done by the JIT compiler.  This is ok
758            since a static method always belongs to the declaring class. */
759
760         if (m->flags & ACC_STATIC) {
761                 /* For static methods we reset the object. */
762
763                 if (o != NULL)
764                         o = NULL;
765
766                 /* for convenience */
767
768                 resm = m;
769
770         } else {
771                 /* For instance methods we make a virtual function table lookup. */
772
773                 resm = method_vftbl_lookup(vftbl, m);
774         }
775
776         STATISTICS(jnicallXmethodnvokation());
777
778         (void) vm_call_method_jvalue(resm, o, args);
779 }
780
781
782 // JNI functions are exported as C functions.
783 extern "C" {
784
785 /* GetVersion ******************************************************************
786
787    Returns the major version number in the higher 16 bits and the
788    minor version number in the lower 16 bits.
789
790 *******************************************************************************/
791
792 jint _Jv_JNI_GetVersion(JNIEnv *env)
793 {
794         TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
795
796         return JNI_VERSION_SUPPORTED;
797 }
798
799
800 /* Class Operations ***********************************************************/
801
802 /* DefineClass *****************************************************************
803
804    Loads a class from a buffer of raw class data. The buffer
805    containing the raw class data is not referenced by the VM after the
806    DefineClass call returns, and it may be discarded if desired.
807
808 *******************************************************************************/
809
810 jclass jni_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen)
811 {
812 #if defined(ENABLE_JAVASE)
813         utf           *u;
814         classloader_t *cl;
815         classinfo     *c;
816         java_handle_t* h;
817
818         TRACEJNICALLS(("jni_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
819
820         u  = utf_new_char(name);
821         cl = loader_hashtable_classloader_add((java_handle_t *) loader);
822
823         c = class_define(u, cl, bufLen, (uint8_t *) buf, NULL);
824
825         h = LLNI_classinfo_wrap(c);
826
827         return (jclass) jni_NewLocalRef(env, (jobject) h);
828 #else
829         vm_abort("jni_DefineClass: Not implemented in this configuration");
830
831         // Keep compiler happy.
832
833         return 0;
834 #endif
835 }
836
837
838 /* FindClass *******************************************************************
839
840    This function loads a locally-defined class. It searches the
841    directories and zip files specified by the CLASSPATH environment
842    variable for the class with the specified name.
843
844 *******************************************************************************/
845
846 jclass jni_FindClass(JNIEnv *env, const char *name)
847 {
848 #if defined(ENABLE_JAVASE)
849
850         utf*       u;    
851         classinfo* cc;
852         classinfo* c;
853         java_handle_t* h;
854
855         TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
856
857         /* FIXME If name is NULL we have a problem here. */
858
859         u = utf_new_char_classname((char *) name);
860
861         if ((u == NULL) /*|| (int)strlen(name) > symbolOopDesc::max_length() */) {
862                 exceptions_throw_noclassdeffounderror(u);
863                 return NULL;
864         }
865
866         /* Check stacktrace for classloader, if one found use it,
867            otherwise use the system classloader. */
868
869         /* Quote from the JNI documentation:
870          
871            In the Java 2 Platform, FindClass locates the class loader
872            associated with the current native method.  If the native code
873            belongs to a system class, no class loader will be
874            involved. Otherwise, the proper class loader will be invoked to
875            load and link the named class. When FindClass is called through
876            the Invocation Interface, there is no current native method or
877            its associated class loader. In that case, the result of
878            ClassLoader.getBaseClassLoader is used." */
879
880         cc = stacktrace_get_current_class();
881
882         if (cc == NULL)
883                 c = load_class_from_sysloader(u);
884         else
885                 c = load_class_from_classloader(u, cc->classloader);
886
887         if (c == NULL) {
888                 resolve_handle_pending_exception(true);
889                 return NULL;
890         }
891
892         if (!link_class(c))
893                 return NULL;
894
895         h = LLNI_classinfo_wrap(c);
896
897         return (jclass) jni_NewLocalRef(env, (jobject) h);
898
899 #elif defined(ENABLE_JAVAME_CLDC1_1)
900
901         utf       *u;
902         classinfo *c;
903
904         TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
905
906         u = utf_new_char_classname((char *) name);
907         c = load_class_bootstrap(u);
908
909         if (c == NULL) {
910                 resolve_handle_pending_exception(true);
911                 return NULL;
912         }
913
914         if (!link_class(c))
915                 return NULL;
916
917         return (jclass) jni_NewLocalRef(env, (jobject) c);
918         
919 #else
920         vm_abort("jni_FindClass: not implemented in this configuration");
921
922         /* keep compiler happy */
923
924         return NULL;
925 #endif
926 }
927   
928
929 /* GetSuperclass ***************************************************************
930
931    If clazz represents any class other than the class Object, then
932    this function returns the object that represents the superclass of
933    the class specified by clazz.
934
935 *******************************************************************************/
936  
937 jclass jni_GetSuperclass(JNIEnv *env, jclass sub)
938 {
939         classinfo* c;
940         classinfo* super;
941
942         TRACEJNICALLS(("jni_GetSuperclass(env=%p, sub=%p)", env, sub));
943
944         c = LLNI_classinfo_unwrap(sub);
945
946         if (c == NULL)
947                 return NULL;
948
949         super = class_get_superclass(c);
950
951         java_handle_t* h = LLNI_classinfo_wrap(super);
952
953         return (jclass) jni_NewLocalRef(env, (jobject) h);
954 }
955   
956  
957 /* IsAssignableFrom ************************************************************
958
959    Determines whether an object of sub can be safely cast to sup.
960
961 *******************************************************************************/
962
963 jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
964 {
965         classinfo *to;
966         classinfo *from;
967
968         TRACEJNICALLS(("_Jv_JNI_IsAssignableFrom(env=%p, sub=%p, sup=%p)", env, sub, sup));
969
970         to   = (classinfo *) sup;
971         from = (classinfo *) sub;
972
973         return class_is_assignable_from(to, from);
974 }
975
976
977 /* Throw ***********************************************************************
978
979    Causes a java.lang.Throwable object to be thrown.
980
981 *******************************************************************************/
982
983 jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
984 {
985         java_handle_t *o;
986
987         STATISTICS(jniinvokation());
988
989         o = (java_handle_t *) obj;
990
991         exceptions_set_exception(o);
992
993         return JNI_OK;
994 }
995
996
997 /* ThrowNew ********************************************************************
998
999    Constructs an exception object from the specified class with the
1000    message specified by message and causes that exception to be
1001    thrown.
1002
1003 *******************************************************************************/
1004
1005 jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg) 
1006 {
1007         classinfo     *c;
1008         java_handle_t *o;
1009         java_handle_t *s;
1010
1011         STATISTICS(jniinvokation());
1012
1013         c = LLNI_classinfo_unwrap(clazz);
1014         if (msg == NULL)
1015                 msg = "";
1016         s = javastring_new_from_utf_string(msg);
1017
1018         /* instantiate exception object */
1019
1020         o = native_new_and_init_string(c, s);
1021
1022         if (o == NULL)
1023                 return -1;
1024
1025         exceptions_set_exception(o);
1026
1027         return 0;
1028 }
1029
1030
1031 /* ExceptionOccurred ***********************************************************
1032
1033    Determines if an exception is being thrown. The exception stays
1034    being thrown until either the native code calls ExceptionClear(),
1035    or the Java code handles the exception.
1036
1037 *******************************************************************************/
1038
1039 jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
1040 {
1041         java_handle_t *o;
1042
1043         TRACEJNICALLS(("_Jv_JNI_ExceptionOccurred(env=%p)", env));
1044
1045         o = exceptions_get_exception();
1046
1047         return (jthrowable) jni_NewLocalRef(env, (jthrowable) o);
1048 }
1049
1050
1051 /* ExceptionDescribe ***********************************************************
1052
1053    Prints an exception and a backtrace of the stack to a system
1054    error-reporting channel, such as stderr. This is a convenience
1055    routine provided for debugging.
1056
1057 *******************************************************************************/
1058
1059 void jni_ExceptionDescribe(JNIEnv *env)
1060 {
1061         TRACEJNICALLS(("jni_ExceptionDescribe(env=%p)", env));
1062
1063         exceptions_print_stacktrace();
1064 }
1065
1066
1067 /* ExceptionClear **************************************************************
1068
1069    Clears any exception that is currently being thrown. If no
1070    exception is currently being thrown, this routine has no effect.
1071
1072 *******************************************************************************/
1073
1074 void jni_ExceptionClear(JNIEnv *env)
1075 {
1076         TRACEJNICALLS(("jni_ExceptionClear(env=%p)", env));
1077
1078         exceptions_clear_exception();
1079 }
1080
1081
1082 /* FatalError ******************************************************************
1083
1084    Raises a fatal error and does not expect the VM to recover. This
1085    function does not return.
1086
1087 *******************************************************************************/
1088
1089 void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
1090 {
1091         STATISTICS(jniinvokation());
1092
1093         /* this seems to be the best way */
1094
1095         vm_abort("JNI Fatal error: %s", msg);
1096 }
1097
1098
1099 /* PushLocalFrame **************************************************************
1100
1101    Creates a new local reference frame, in which at least a given
1102    number of local references can be created.
1103
1104 *******************************************************************************/
1105
1106 jint jni_PushLocalFrame(JNIEnv* env, jint capacity)
1107 {
1108         TRACEJNICALLS(("jni_PushLocalFrame(env=%p, capacity=%d)", env, capacity));
1109
1110         if (capacity <= 0)
1111                 return -1;
1112
1113         /* add new local reference frame to current table */
1114
1115         if (!localref_frame_push(capacity))
1116                 return -1;
1117
1118         return 0;
1119 }
1120
1121
1122 /* PopLocalFrame ***************************************************************
1123
1124    Pops off the current local reference frame, frees all the local
1125    references, and returns a local reference in the previous local
1126    reference frame for the given result object.
1127
1128 *******************************************************************************/
1129
1130 jobject jni_PopLocalFrame(JNIEnv* env, jobject result)
1131 {
1132         TRACEJNICALLS(("jni_PopLocalFrame(env=%p, result=%p)", env, result));
1133
1134         /* release all current local frames */
1135
1136         localref_frame_pop_all();
1137
1138         /* add local reference and return the value */
1139
1140         return jni_NewLocalRef(env, result);
1141 }
1142
1143
1144 /* DeleteLocalRef **************************************************************
1145
1146    Deletes the local reference pointed to by localRef.
1147
1148 *******************************************************************************/
1149
1150 void jni_DeleteLocalRef(JNIEnv *env, jobject localRef)
1151 {
1152         java_handle_t *o;
1153
1154         TRACEJNICALLS(("jni_DeleteLocalRef(env=%p, ref=%p)", env, localRef));
1155
1156         o = (java_handle_t *) localRef;
1157
1158         if (o == NULL)
1159                 return;
1160
1161         /* delete the reference */
1162
1163         localref_del(o);
1164 }
1165
1166
1167 /* IsSameObject ****************************************************************
1168
1169    Tests whether two references refer to the same Java object.
1170
1171 *******************************************************************************/
1172
1173 jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
1174 {
1175         java_handle_t *o1;
1176         java_handle_t *o2;
1177         jboolean       result;
1178
1179         STATISTICS(jniinvokation());
1180
1181         o1 = (java_handle_t *) ref1;
1182         o2 = (java_handle_t *) ref2;
1183
1184         LLNI_CRITICAL_START;
1185
1186         if (LLNI_UNWRAP(o1) == LLNI_UNWRAP(o2))
1187                 result = JNI_TRUE;
1188         else
1189                 result = JNI_FALSE;
1190
1191         LLNI_CRITICAL_END;
1192
1193         return result;
1194 }
1195
1196
1197 /* NewLocalRef *****************************************************************
1198
1199    Creates a new local reference that refers to the same object as ref.
1200
1201 *******************************************************************************/
1202
1203 jobject jni_NewLocalRef(JNIEnv *env, jobject ref)
1204 {
1205         java_handle_t *o;
1206         java_handle_t *localref;
1207
1208         TRACEJNICALLS(("jni_NewLocalRef(env=%p, ref=%p)", env, ref));
1209
1210         o = (java_handle_t *) ref;
1211
1212         if (o == NULL)
1213                 return NULL;
1214
1215         /* insert the reference */
1216
1217         localref = localref_add(LLNI_DIRECT(o));
1218
1219         return (jobject) localref;
1220 }
1221
1222
1223 /* EnsureLocalCapacity *********************************************************
1224
1225    Ensures that at least a given number of local references can be
1226    created in the current thread
1227
1228 *******************************************************************************/
1229
1230 jint jni_EnsureLocalCapacity(JNIEnv* env, jint capacity)
1231 {
1232         localref_table *lrt;
1233
1234         TRACEJNICALLS(("jni_EnsureLocalCapacity(env=%p, capacity=%d)", env, capacity));
1235
1236         /* get local reference table (thread specific) */
1237
1238         lrt = LOCALREFTABLE;
1239
1240         /* check if capacity elements are available in the local references table */
1241
1242         if ((lrt->used + capacity) > lrt->capacity)
1243                 return jni_PushLocalFrame(env, capacity);
1244
1245         return 0;
1246 }
1247
1248
1249 /* AllocObject *****************************************************************
1250
1251    Allocates a new Java object without invoking any of the
1252    constructors for the object. Returns a reference to the object.
1253
1254 *******************************************************************************/
1255
1256 jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
1257 {
1258         classinfo     *c;
1259         java_handle_t *o;
1260
1261         STATISTICS(jniinvokation());
1262
1263         c = LLNI_classinfo_unwrap(clazz);
1264
1265         if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
1266                 exceptions_throw_instantiationexception(c);
1267                 return NULL;
1268         }
1269                 
1270         o = builtin_new(c);
1271
1272         return jni_NewLocalRef(env, (jobject) o);
1273 }
1274
1275
1276 /* NewObject *******************************************************************
1277
1278    Programmers place all arguments that are to be passed to the
1279    constructor immediately following the methodID
1280    argument. NewObject() accepts these arguments and passes them to
1281    the Java method that the programmer wishes to invoke.
1282
1283 *******************************************************************************/
1284
1285 jobject jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
1286 {
1287         java_handle_t *o;
1288         classinfo     *c;
1289         methodinfo    *m;
1290         va_list        ap;
1291
1292         TRACEJNICALLSENTER(("jni_NewObject(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
1293
1294         c = LLNI_classinfo_unwrap(clazz);
1295         m = (methodinfo *) methodID;
1296
1297         /* create object */
1298
1299         o = builtin_new(c);
1300         
1301         if (o == NULL)
1302                 return NULL;
1303
1304         /* call constructor */
1305
1306         va_start(ap, methodID);
1307         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
1308         va_end(ap);
1309
1310         TRACEJNICALLSEXIT(("->%p", o));
1311
1312         return jni_NewLocalRef(env, (jobject) o);
1313 }
1314
1315
1316 /* NewObjectV ******************************************************************
1317
1318    Programmers place all arguments that are to be passed to the
1319    constructor in an args argument of type va_list that immediately
1320    follows the methodID argument. NewObjectV() accepts these
1321    arguments, and, in turn, passes them to the Java method that the
1322    programmer wishes to invoke.
1323
1324 *******************************************************************************/
1325
1326 jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1327                                                    va_list args)
1328 {
1329         java_handle_t *o;
1330         classinfo     *c;
1331         methodinfo    *m;
1332
1333         STATISTICS(jniinvokation());
1334
1335         c = LLNI_classinfo_unwrap(clazz);
1336         m = (methodinfo *) methodID;
1337
1338         /* create object */
1339
1340         o = builtin_new(c);
1341         
1342         if (o == NULL)
1343                 return NULL;
1344
1345         /* call constructor */
1346
1347         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
1348
1349         return jni_NewLocalRef(env, (jobject) o);
1350 }
1351
1352
1353 /* NewObjectA ***************************************************************** 
1354
1355    Programmers place all arguments that are to be passed to the
1356    constructor in an args array of jvalues that immediately follows
1357    the methodID argument. NewObjectA() accepts the arguments in this
1358    array, and, in turn, passes them to the Java method that the
1359    programmer wishes to invoke.
1360
1361 *******************************************************************************/
1362
1363 jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1364                                                    const jvalue *args)
1365 {
1366         java_handle_t *o;
1367         classinfo     *c;
1368         methodinfo    *m;
1369
1370         STATISTICS(jniinvokation());
1371
1372         c = LLNI_classinfo_unwrap(clazz);
1373         m = (methodinfo *) methodID;
1374
1375         /* create object */
1376
1377         o = builtin_new(c);
1378         
1379         if (o == NULL)
1380                 return NULL;
1381
1382         /* call constructor */
1383
1384         _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
1385
1386         return jni_NewLocalRef(env, (jobject) o);
1387 }
1388
1389
1390 /* GetObjectClass **************************************************************
1391
1392  Returns the class of an object.
1393
1394 *******************************************************************************/
1395
1396 jclass jni_GetObjectClass(JNIEnv *env, jobject obj)
1397 {
1398         java_handle_t* o;
1399         classinfo*     c;
1400
1401         TRACEJNICALLS(("jni_GetObjectClass(env=%p, obj=%p)", env, obj));
1402
1403         o = (java_handle_t *) obj;
1404
1405         if ((o == NULL) || (LLNI_vftbl_direct(o) == NULL))
1406                 return NULL;
1407
1408         LLNI_class_get(o, c);
1409
1410         java_handle_t* h = LLNI_classinfo_wrap(c);
1411
1412         return (jclass) jni_NewLocalRef(env, (jobject) h);
1413 }
1414
1415
1416 /* IsInstanceOf ****************************************************************
1417
1418    Tests whether an object is an instance of a class.
1419
1420 *******************************************************************************/
1421
1422 jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
1423 {
1424         classinfo     *c;
1425         java_handle_t *h;
1426
1427         TRACEJNICALLS(("_Jv_JNI_IsInstanceOf(env=%p, obj=%p, clazz=%p)", env, obj, clazz));
1428
1429         /* XXX Is this correct? */
1430         c = LLNI_classinfo_unwrap(clazz);
1431         h = (java_handle_t *) obj;
1432
1433         return class_is_instance(c, h);
1434 }
1435
1436
1437 /* Reflection Support *********************************************************/
1438
1439 /* FromReflectedMethod *********************************************************
1440
1441    Converts java.lang.reflect.Method or java.lang.reflect.Constructor
1442    object to a method ID.
1443   
1444 *******************************************************************************/
1445   
1446 jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
1447 {
1448 #if defined(ENABLE_JAVASE)
1449         methodinfo*    m;
1450
1451         TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
1452
1453         java_lang_Object o(method);
1454
1455         if (o.is_null())
1456                 return NULL;
1457
1458         if (o.get_Class() == class_java_lang_reflect_Constructor) {
1459                 java_lang_reflect_Constructor rc(method);
1460                 m = rc.get_method();
1461         }
1462         else {
1463                 assert(o.get_Class() == class_java_lang_reflect_Method);
1464
1465                 java_lang_reflect_Method rm(method);
1466                 m = rm.get_method();
1467         }
1468
1469         return (jmethodID) m;
1470 #else
1471         vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
1472
1473         // Keep compiler happy.
1474         return NULL;
1475 #endif
1476 }
1477
1478
1479 /* FromReflectedField **********************************************************
1480
1481    Converts a java.lang.reflect.Field to a field ID.
1482
1483 *******************************************************************************/
1484  
1485 jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
1486 {
1487 #if defined(ENABLE_JAVASE)
1488
1489         TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
1490
1491         java_lang_reflect_Field rf(field);
1492
1493         if (rf.is_null())
1494                 return NULL;
1495
1496         fieldinfo* f = rf.get_field();
1497
1498         return (jfieldID) f;
1499 #else
1500         vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
1501
1502         // Keep compiler happy.
1503         return NULL;
1504 #endif
1505 }
1506
1507
1508 /* ToReflectedMethod ***********************************************************
1509
1510    Converts a method ID derived from cls to an instance of the
1511    java.lang.reflect.Method class or to an instance of the
1512    java.lang.reflect.Constructor class.
1513
1514 *******************************************************************************/
1515
1516 jobject jni_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
1517 {
1518 #if defined(ENABLE_JAVASE)
1519         TRACEJNICALLS(("jni_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
1520
1521         methodinfo* m = (methodinfo *) methodID;
1522
1523         /* HotSpot does the same assert. */
1524
1525         assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
1526
1527         java_handle_t* h;
1528
1529         if (m->name == utf_init) {
1530                 h = java_lang_reflect_Constructor(m).get_handle();
1531         }
1532         else {
1533                 h = java_lang_reflect_Method(m).get_handle();
1534         }
1535
1536         return (jobject) h;
1537 #else
1538         vm_abort("jni_ToReflectedMethod: Not implemented in this configuration.");
1539
1540         /* keep compiler happy */
1541
1542         return NULL;
1543 #endif
1544 }
1545
1546
1547 /* ToReflectedField ************************************************************
1548
1549    Converts a field ID derived from cls to an instance of the
1550    java.lang.reflect.Field class.
1551
1552 *******************************************************************************/
1553
1554 jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1555                                                                  jboolean isStatic)
1556 {
1557         STATISTICS(jniinvokation());
1558
1559         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
1560
1561         return NULL;
1562 }
1563
1564
1565 /* Calling Instance Methods ***************************************************/
1566
1567 /* GetMethodID *****************************************************************
1568
1569    Returns the method ID for an instance (nonstatic) method of a class
1570    or interface. The method may be defined in one of the clazz's
1571    superclasses and inherited by clazz. The method is determined by
1572    its name and signature.
1573
1574    GetMethodID() causes an uninitialized class to be initialized.
1575
1576 *******************************************************************************/
1577
1578 jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
1579                                                           const char *sig)
1580 {
1581         classinfo  *c;
1582         utf        *uname;
1583         utf        *udesc;
1584         methodinfo *m;
1585
1586         STATISTICS(jniinvokation());
1587
1588         c = LLNI_classinfo_unwrap(clazz);
1589
1590         if (c == NULL)
1591                 return NULL;
1592
1593         if (!(c->state & CLASS_INITIALIZED))
1594                 if (!initialize_class(c))
1595                         return NULL;
1596
1597         /* try to get the method of the class or one of it's superclasses */
1598
1599         uname = utf_new_char((char *) name);
1600         udesc = utf_new_char((char *) sig);
1601
1602         m = class_resolvemethod(c, uname, udesc);
1603
1604         if ((m == NULL) || (m->flags & ACC_STATIC)) {
1605                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
1606
1607                 return NULL;
1608         }
1609
1610         return (jmethodID) m;
1611 }
1612
1613
1614 /* JNI-functions for calling instance methods *********************************/
1615
1616 #define JNI_CALL_VIRTUAL_METHOD(name, type, intern)         \
1617 type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj,   \
1618                                                                 jmethodID methodID, ...)    \
1619 {                                                           \
1620         java_handle_t *o;                                       \
1621         methodinfo    *m;                                       \
1622         va_list        ap;                                      \
1623         type           ret;                                     \
1624                                                             \
1625         o = (java_handle_t *) obj;                              \
1626         m = (methodinfo *) methodID;                            \
1627                                                             \
1628         va_start(ap, methodID);                                 \
1629         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, ap); \
1630         va_end(ap);                                             \
1631                                                             \
1632         return ret;                                             \
1633 }
1634
1635 JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
1636 JNI_CALL_VIRTUAL_METHOD(Byte,    jbyte,    Int)
1637 JNI_CALL_VIRTUAL_METHOD(Char,    jchar,    Int)
1638 JNI_CALL_VIRTUAL_METHOD(Short,   jshort,   Int)
1639 JNI_CALL_VIRTUAL_METHOD(Int,     jint,     Int)
1640 JNI_CALL_VIRTUAL_METHOD(Long,    jlong,    Long)
1641 JNI_CALL_VIRTUAL_METHOD(Float,   jfloat,   Float)
1642 JNI_CALL_VIRTUAL_METHOD(Double,  jdouble,  Double)
1643
1644
1645 #define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern)              \
1646 type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj,         \
1647                                                                  jmethodID methodID, va_list args) \
1648 {                                                                  \
1649         java_handle_t *o;                                              \
1650         methodinfo    *m;                                              \
1651         type           ret;                                            \
1652                                                                    \
1653         o = (java_handle_t *) obj;                                     \
1654         m = (methodinfo *) methodID;                                   \
1655                                                                    \
1656         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, args);      \
1657                                                                    \
1658         return ret;                                                    \
1659 }
1660
1661 JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
1662 JNI_CALL_VIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1663 JNI_CALL_VIRTUAL_METHOD_V(Char,    jchar,    Int)
1664 JNI_CALL_VIRTUAL_METHOD_V(Short,   jshort,   Int)
1665 JNI_CALL_VIRTUAL_METHOD_V(Int,     jint,     Int)
1666 JNI_CALL_VIRTUAL_METHOD_V(Long,    jlong,    Long)
1667 JNI_CALL_VIRTUAL_METHOD_V(Float,   jfloat,   Float)
1668 JNI_CALL_VIRTUAL_METHOD_V(Double,  jdouble,  Double)
1669
1670
1671 #define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern)          \
1672 type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj,     \
1673                                                                  jmethodID methodID,           \
1674                                                                  const jvalue *args)           \
1675 {                                                              \
1676         java_handle_t *o;                                          \
1677         methodinfo    *m;                                          \
1678         type           ret;                                        \
1679                                                                \
1680         o = (java_handle_t *) obj;                                 \
1681         m = (methodinfo *) methodID;                               \
1682                                                                \
1683         ret = _Jv_jni_Call##intern##MethodA(o, LLNI_vftbl_direct(o), m, args); \
1684                                                                \
1685         return ret;                                                \
1686 }
1687
1688 JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
1689 JNI_CALL_VIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1690 JNI_CALL_VIRTUAL_METHOD_A(Char,    jchar,    Int)
1691 JNI_CALL_VIRTUAL_METHOD_A(Short,   jshort,   Int)
1692 JNI_CALL_VIRTUAL_METHOD_A(Int,     jint,     Int)
1693 JNI_CALL_VIRTUAL_METHOD_A(Long,    jlong,    Long)
1694 JNI_CALL_VIRTUAL_METHOD_A(Float,   jfloat,   Float)
1695 JNI_CALL_VIRTUAL_METHOD_A(Double,  jdouble,  Double)
1696
1697
1698 jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
1699                                                                  ...)
1700 {
1701         java_handle_t *o;
1702         methodinfo    *m;
1703         java_handle_t *ret;
1704         va_list        ap;
1705
1706         o = (java_handle_t *) obj;
1707         m = (methodinfo *) methodID;
1708
1709         va_start(ap, methodID);
1710         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, ap);
1711         va_end(ap);
1712
1713         return jni_NewLocalRef(env, (jobject) ret);
1714 }
1715
1716
1717 jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1718                                                                   va_list args)
1719 {
1720         java_handle_t *o;
1721         methodinfo    *m;
1722         java_handle_t *ret;
1723
1724         o = (java_handle_t *) obj;
1725         m = (methodinfo *) methodID;
1726
1727         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, args);
1728
1729         return jni_NewLocalRef(env, (jobject) ret);
1730 }
1731
1732
1733 jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1734                                                                   const jvalue *args)
1735 {
1736         java_handle_t *o;
1737         methodinfo    *m;
1738         java_handle_t *ret;
1739
1740         o = (java_handle_t *) obj;
1741         m = (methodinfo *) methodID;
1742
1743         ret = _Jv_jni_CallObjectMethodA(o, LLNI_vftbl_direct(o), m, args);
1744
1745         return jni_NewLocalRef(env, (jobject) ret);
1746 }
1747
1748
1749
1750 void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1751 {
1752         java_handle_t *o;
1753         methodinfo    *m;
1754         va_list        ap;
1755
1756         o = (java_handle_t *) obj;
1757         m = (methodinfo *) methodID;
1758
1759         va_start(ap, methodID);
1760         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
1761         va_end(ap);
1762 }
1763
1764
1765 void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1766                                                          va_list args)
1767 {
1768         java_handle_t *o;
1769         methodinfo    *m;
1770
1771         o = (java_handle_t *) obj;
1772         m = (methodinfo *) methodID;
1773
1774         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
1775 }
1776
1777
1778 void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1779                                                          const jvalue *args)
1780 {
1781         java_handle_t *o;
1782         methodinfo    *m;
1783
1784         o = (java_handle_t *) obj;
1785         m = (methodinfo *) methodID;
1786
1787         _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
1788 }
1789
1790
1791
1792 #define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern)                      \
1793 type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj,         \
1794                                                                                   jclass clazz, jmethodID methodID, \
1795                                                                                   ...)                              \
1796 {                                                                           \
1797         java_handle_t *o;                                                       \
1798         classinfo     *c;                                                       \
1799         methodinfo    *m;                                                       \
1800         va_list        ap;                                                      \
1801         type           ret;                                                     \
1802                                                                             \
1803         o = (java_handle_t *) obj;                                              \
1804         c = LLNI_classinfo_unwrap(clazz);                                       \
1805         m = (methodinfo *) methodID;                                            \
1806                                                                             \
1807         va_start(ap, methodID);                                                 \
1808         ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap);                 \
1809         va_end(ap);                                                             \
1810                                                                             \
1811         return ret;                                                             \
1812 }
1813
1814 JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
1815 JNI_CALL_NONVIRTUAL_METHOD(Byte,    jbyte,    Int)
1816 JNI_CALL_NONVIRTUAL_METHOD(Char,    jchar,    Int)
1817 JNI_CALL_NONVIRTUAL_METHOD(Short,   jshort,   Int)
1818 JNI_CALL_NONVIRTUAL_METHOD(Int,     jint,     Int)
1819 JNI_CALL_NONVIRTUAL_METHOD(Long,    jlong,    Long)
1820 JNI_CALL_NONVIRTUAL_METHOD(Float,   jfloat,   Float)
1821 JNI_CALL_NONVIRTUAL_METHOD(Double,  jdouble,  Double)
1822
1823
1824 #define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern)                     \
1825 type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj,         \
1826                                                                                    jclass clazz, jmethodID methodID, \
1827                                                                                    va_list args)                     \
1828 {                                                                            \
1829         java_handle_t *o;                                                        \
1830         classinfo     *c;                                                        \
1831         methodinfo    *m;                                                        \
1832         type           ret;                                                      \
1833                                                                              \
1834         o = (java_handle_t *) obj;                                               \
1835         c = LLNI_classinfo_unwrap(clazz);                                        \
1836         m = (methodinfo *) methodID;                                             \
1837                                                                              \
1838         ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);                       \
1839                                                                              \
1840         return ret;                                                              \
1841 }
1842
1843 JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
1844 JNI_CALL_NONVIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1845 JNI_CALL_NONVIRTUAL_METHOD_V(Char,    jchar,    Int)
1846 JNI_CALL_NONVIRTUAL_METHOD_V(Short,   jshort,   Int)
1847 JNI_CALL_NONVIRTUAL_METHOD_V(Int,     jint,     Int)
1848 JNI_CALL_NONVIRTUAL_METHOD_V(Long,    jlong,    Long)
1849 JNI_CALL_NONVIRTUAL_METHOD_V(Float,   jfloat,   Float)
1850 JNI_CALL_NONVIRTUAL_METHOD_V(Double,  jdouble,  Double)
1851
1852
1853 #define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern)                     \
1854 type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj,         \
1855                                                                                    jclass clazz, jmethodID methodID, \
1856                                                                                    const jvalue *args)               \
1857 {                                                                            \
1858         log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!");      \
1859                                                                              \
1860         return 0;                                                                \
1861 }
1862
1863 JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
1864 JNI_CALL_NONVIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1865 JNI_CALL_NONVIRTUAL_METHOD_A(Char,    jchar,    Int)
1866 JNI_CALL_NONVIRTUAL_METHOD_A(Short,   jshort,   Int)
1867 JNI_CALL_NONVIRTUAL_METHOD_A(Int,     jint,     Int)
1868 JNI_CALL_NONVIRTUAL_METHOD_A(Long,    jlong,    Long)
1869 JNI_CALL_NONVIRTUAL_METHOD_A(Float,   jfloat,   Float)
1870 JNI_CALL_NONVIRTUAL_METHOD_A(Double,  jdouble,  Double)
1871
1872 jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
1873                                                                                    jclass clazz, jmethodID methodID,
1874                                                                                    ...)
1875 {
1876         java_handle_t *o;
1877         classinfo     *c;
1878         methodinfo    *m;
1879         java_handle_t *r;
1880         va_list        ap;
1881
1882         o = (java_handle_t *) obj;
1883         c = LLNI_classinfo_unwrap(clazz);
1884         m = (methodinfo *) methodID;
1885
1886         va_start(ap, methodID);
1887         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
1888         va_end(ap);
1889
1890         return jni_NewLocalRef(env, (jobject) r);
1891 }
1892
1893
1894 jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
1895                                                                                         jclass clazz, jmethodID methodID,
1896                                                                                         va_list args)
1897 {
1898         java_handle_t *o;
1899         classinfo     *c;
1900         methodinfo    *m;
1901         java_handle_t *r;
1902
1903         o = (java_handle_t *) obj;
1904         c = LLNI_classinfo_unwrap(clazz);
1905         m = (methodinfo *) methodID;
1906
1907         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
1908
1909         return jni_NewLocalRef(env, (jobject) r);
1910 }
1911
1912
1913 jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
1914                                                                                         jclass clazz, jmethodID methodID,
1915                                                                                         const jvalue *args)
1916 {
1917         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
1918
1919         return jni_NewLocalRef(env, NULL);
1920 }
1921
1922
1923 void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
1924                                                                           jmethodID methodID, ...)
1925 {
1926         java_handle_t *o;
1927         classinfo     *c;
1928         methodinfo    *m;
1929         va_list        ap;
1930
1931         o = (java_handle_t *) obj;
1932         c = LLNI_classinfo_unwrap(clazz);
1933         m = (methodinfo *) methodID;
1934
1935         va_start(ap, methodID);
1936         _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
1937         va_end(ap);
1938 }
1939
1940
1941 void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
1942                                                                            jmethodID methodID, va_list args)
1943 {
1944         java_handle_t *o;
1945         classinfo     *c;
1946         methodinfo    *m;
1947
1948         o = (java_handle_t *) obj;
1949         c = LLNI_classinfo_unwrap(clazz);
1950         m = (methodinfo *) methodID;
1951
1952         _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
1953 }
1954
1955
1956 void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
1957                                                                            jmethodID methodID, const jvalue * args)
1958 {       
1959         java_handle_t *o;
1960         classinfo     *c;
1961         methodinfo    *m;
1962
1963         o = (java_handle_t *) obj;
1964         c = LLNI_classinfo_unwrap(clazz);
1965         m = (methodinfo *) methodID;
1966
1967         _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
1968 }
1969
1970
1971 /* Accessing Fields of Objects ************************************************/
1972
1973 /* GetFieldID ******************************************************************
1974
1975    Returns the field ID for an instance (nonstatic) field of a
1976    class. The field is specified by its name and signature. The
1977    Get<type>Field and Set<type>Field families of accessor functions
1978    use field IDs to retrieve object fields.
1979
1980 *******************************************************************************/
1981
1982 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
1983                                                         const char *sig)
1984 {
1985         classinfo *c;
1986         fieldinfo *f;
1987         utf       *uname;
1988         utf       *udesc;
1989
1990         STATISTICS(jniinvokation());
1991
1992         c = LLNI_classinfo_unwrap(clazz);
1993
1994         /* XXX NPE check? */
1995
1996         uname = utf_new_char((char *) name);
1997         udesc = utf_new_char((char *) sig);
1998
1999         f = class_findfield(c, uname, udesc); 
2000         
2001         if (f == NULL)
2002                 exceptions_throw_nosuchfielderror(c, uname);  
2003
2004         return (jfieldID) f;
2005 }
2006
2007
2008 /* Get<type>Field Routines *****************************************************
2009
2010    This family of accessor routines returns the value of an instance
2011    (nonstatic) field of an object. The field to access is specified by
2012    a field ID obtained by calling GetFieldID().
2013
2014 *******************************************************************************/
2015
2016 #define GET_FIELD(o,type,f) \
2017     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
2018
2019 #define JNI_GET_FIELD(name, type, intern)                                 \
2020 type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
2021 {                                                                         \
2022         intern ret;                                                           \
2023                                                                           \
2024         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
2025                                                                           \
2026         LLNI_CRITICAL_START;                                                  \
2027                                                                           \
2028         ret = GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID); \
2029                                                                           \
2030         LLNI_CRITICAL_END;                                                    \
2031                                                                           \
2032         return (type) ret;                                                    \
2033 }
2034
2035 JNI_GET_FIELD(Boolean, jboolean, s4)
2036 JNI_GET_FIELD(Byte,    jbyte,    s4)
2037 JNI_GET_FIELD(Char,    jchar,    s4)
2038 JNI_GET_FIELD(Short,   jshort,   s4)
2039 JNI_GET_FIELD(Int,     jint,     s4)
2040 JNI_GET_FIELD(Long,    jlong,    s8)
2041 JNI_GET_FIELD(Float,   jfloat,   float)
2042 JNI_GET_FIELD(Double,  jdouble,  double)
2043
2044
2045 jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
2046 {
2047         java_handle_t *o;
2048
2049         TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
2050
2051         LLNI_CRITICAL_START;
2052
2053         o = LLNI_WRAP(GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), java_object_t*, fieldID));
2054
2055         LLNI_CRITICAL_END;
2056
2057         return jni_NewLocalRef(env, (jobject) o);
2058 }
2059
2060
2061 /* Set<type>Field Routines *****************************************************
2062
2063    This family of accessor routines sets the value of an instance
2064    (nonstatic) field of an object. The field to access is specified by
2065    a field ID obtained by calling GetFieldID().
2066
2067 *******************************************************************************/
2068
2069 #define SET_FIELD(o,type,f,value) \
2070     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
2071
2072 #define JNI_SET_FIELD(name, type, intern)                                  \
2073 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
2074                                                           type value)                                  \
2075 {                                                                          \
2076         TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
2077                                                                            \
2078         LLNI_CRITICAL_START;                                                   \
2079                                                                            \
2080         SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
2081                                                                                \
2082         LLNI_CRITICAL_START;                                                   \
2083 }
2084
2085 JNI_SET_FIELD(Boolean, jboolean, s4)
2086 JNI_SET_FIELD(Byte,    jbyte,    s4)
2087 JNI_SET_FIELD(Char,    jchar,    s4)
2088 JNI_SET_FIELD(Short,   jshort,   s4)
2089 JNI_SET_FIELD(Int,     jint,     s4)
2090 JNI_SET_FIELD(Long,    jlong,    s8)
2091 JNI_SET_FIELD(Float,   jfloat,   float)
2092 JNI_SET_FIELD(Double,  jdouble,  double)
2093
2094
2095 void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
2096                                                         jobject value)
2097 {
2098         TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
2099
2100         LLNI_CRITICAL_START;
2101
2102         SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
2103
2104         LLNI_CRITICAL_END;
2105 }
2106
2107
2108 /* Calling Static Methods *****************************************************/
2109
2110 /* GetStaticMethodID ***********************************************************
2111
2112    Returns the method ID for a static method of a class. The method is
2113    specified by its name and signature.
2114
2115    GetStaticMethodID() causes an uninitialized class to be
2116    initialized.
2117
2118 *******************************************************************************/
2119
2120 jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
2121                                                                         const char *sig)
2122 {
2123         classinfo  *c;
2124         utf        *uname;
2125         utf        *udesc;
2126         methodinfo *m;
2127
2128         TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
2129
2130         c = LLNI_classinfo_unwrap(clazz);
2131
2132         if (c == NULL)
2133                 return NULL;
2134
2135         if (!(c->state & CLASS_INITIALIZED))
2136                 if (!initialize_class(c))
2137                         return NULL;
2138
2139         /* try to get the static method of the class */
2140
2141         uname = utf_new_char((char *) name);
2142         udesc = utf_new_char((char *) sig);
2143
2144         m = class_resolvemethod(c, uname, udesc);
2145
2146         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
2147                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2148
2149                 return NULL;
2150         }
2151
2152         return (jmethodID) m;
2153 }
2154
2155
2156 #define JNI_CALL_STATIC_METHOD(name, type, intern)               \
2157 type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
2158                                                                           jmethodID methodID, ...)   \
2159 {                                                                \
2160         methodinfo *m;                                               \
2161         va_list     ap;                                              \
2162         type        res;                                             \
2163                                                                  \
2164         m = (methodinfo *) methodID;                                 \
2165                                                                  \
2166         va_start(ap, methodID);                                      \
2167         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap);       \
2168         va_end(ap);                                                  \
2169                                                                  \
2170         return res;                                                  \
2171 }
2172
2173 JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
2174 JNI_CALL_STATIC_METHOD(Byte,    jbyte,    Int)
2175 JNI_CALL_STATIC_METHOD(Char,    jchar,    Int)
2176 JNI_CALL_STATIC_METHOD(Short,   jshort,   Int)
2177 JNI_CALL_STATIC_METHOD(Int,     jint,     Int)
2178 JNI_CALL_STATIC_METHOD(Long,    jlong,    Long)
2179 JNI_CALL_STATIC_METHOD(Float,   jfloat,   Float)
2180 JNI_CALL_STATIC_METHOD(Double,  jdouble,  Double)
2181
2182
2183 #define JNI_CALL_STATIC_METHOD_V(name, type, intern)                     \
2184 type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz,        \
2185                                                                            jmethodID methodID, va_list args) \
2186 {                                                                        \
2187         methodinfo *m;                                                       \
2188         type        res;                                                     \
2189                                                                          \
2190         m = (methodinfo *) methodID;                                         \
2191                                                                          \
2192         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args);             \
2193                                                                          \
2194         return res;                                                          \
2195 }
2196
2197 JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
2198 JNI_CALL_STATIC_METHOD_V(Byte,    jbyte,    Int)
2199 JNI_CALL_STATIC_METHOD_V(Char,    jchar,    Int)
2200 JNI_CALL_STATIC_METHOD_V(Short,   jshort,   Int)
2201 JNI_CALL_STATIC_METHOD_V(Int,     jint,     Int)
2202 JNI_CALL_STATIC_METHOD_V(Long,    jlong,    Long)
2203 JNI_CALL_STATIC_METHOD_V(Float,   jfloat,   Float)
2204 JNI_CALL_STATIC_METHOD_V(Double,  jdouble,  Double)
2205
2206
2207 #define JNI_CALL_STATIC_METHOD_A(name, type, intern)                           \
2208 type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz,              \
2209                                                                            jmethodID methodID, const jvalue *args) \
2210 {                                                                              \
2211         methodinfo *m;                                                             \
2212         type        res;                                                           \
2213                                                                                \
2214         m = (methodinfo *) methodID;                                               \
2215                                                                                \
2216         res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args);                  \
2217                                                                                \
2218         return res;                                                                \
2219 }
2220
2221 JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
2222 JNI_CALL_STATIC_METHOD_A(Byte,    jbyte,    Int)
2223 JNI_CALL_STATIC_METHOD_A(Char,    jchar,    Int)
2224 JNI_CALL_STATIC_METHOD_A(Short,   jshort,   Int)
2225 JNI_CALL_STATIC_METHOD_A(Int,     jint,     Int)
2226 JNI_CALL_STATIC_METHOD_A(Long,    jlong,    Long)
2227 JNI_CALL_STATIC_METHOD_A(Float,   jfloat,   Float)
2228 JNI_CALL_STATIC_METHOD_A(Double,  jdouble,  Double)
2229
2230
2231 jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
2232                                                                            jmethodID methodID, ...)
2233 {
2234         methodinfo    *m;
2235         java_handle_t *o;
2236         va_list        ap;
2237
2238         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2239
2240         m = (methodinfo *) methodID;
2241
2242         va_start(ap, methodID);
2243         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
2244         va_end(ap);
2245
2246         return jni_NewLocalRef(env, (jobject) o);
2247 }
2248
2249
2250 jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
2251                                                                                 jmethodID methodID, va_list args)
2252 {
2253         methodinfo    *m;
2254         java_handle_t *o;
2255
2256         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2257
2258         m = (methodinfo *) methodID;
2259
2260         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
2261
2262         return jni_NewLocalRef(env, (jobject) o);
2263 }
2264
2265
2266 jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
2267                                                                                 jmethodID methodID, const jvalue *args)
2268 {
2269         methodinfo    *m;
2270         java_handle_t *o;
2271
2272         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2273
2274         m = (methodinfo *) methodID;
2275
2276         o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
2277
2278         return jni_NewLocalRef(env, (jobject) o);
2279 }
2280
2281
2282 void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
2283                                                                   jmethodID methodID, ...)
2284 {
2285         methodinfo *m;
2286         va_list     ap;
2287
2288         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2289
2290         m = (methodinfo *) methodID;
2291
2292         va_start(ap, methodID);
2293         _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
2294         va_end(ap);
2295 }
2296
2297
2298 void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
2299                                                                    jmethodID methodID, va_list args)
2300 {
2301         methodinfo *m;
2302
2303         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2304
2305         m = (methodinfo *) methodID;
2306
2307         _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
2308 }
2309
2310
2311 void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
2312                                                                    jmethodID methodID, const jvalue * args)
2313 {
2314         methodinfo *m;
2315
2316         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2317
2318         m = (methodinfo *) methodID;
2319
2320         _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
2321 }
2322
2323
2324 /* Accessing Static Fields ****************************************************/
2325
2326 /* GetStaticFieldID ************************************************************
2327
2328    Returns the field ID for a static field of a class. The field is
2329    specified by its name and signature. The GetStatic<type>Field and
2330    SetStatic<type>Field families of accessor functions use field IDs
2331    to retrieve static fields.
2332
2333 *******************************************************************************/
2334
2335 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
2336                                                                   const char *sig)
2337 {
2338         classinfo *c;
2339         fieldinfo *f;
2340         utf       *uname;
2341         utf       *usig;
2342
2343         STATISTICS(jniinvokation());
2344
2345         c = LLNI_classinfo_unwrap(clazz);
2346
2347         uname = utf_new_char((char *) name);
2348         usig  = utf_new_char((char *) sig);
2349
2350         f = class_findfield(c, uname, usig);
2351         
2352         if (f == NULL)
2353                 exceptions_throw_nosuchfielderror(c, uname);
2354
2355         return (jfieldID) f;
2356 }
2357
2358
2359 /* GetStatic<type>Field ********************************************************
2360
2361    This family of accessor routines returns the value of a static
2362    field of an object.
2363
2364 *******************************************************************************/
2365
2366 #define JNI_GET_STATIC_FIELD(name, type, field)                \
2367 type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
2368                                                                         jfieldID fieldID)          \
2369 {                                                              \
2370         classinfo *c;                                              \
2371         fieldinfo *f;                                              \
2372                                                                \
2373         STATISTICS(jniinvokation());                               \
2374                                                                \
2375         c = LLNI_classinfo_unwrap(clazz);                          \
2376         f = (fieldinfo *) fieldID;                                 \
2377                                                                \
2378         if (!(c->state & CLASS_INITIALIZED))                       \
2379                 if (!initialize_class(c))                              \
2380                         return 0;                                          \
2381                                                                \
2382         return f->value->field;                                    \
2383 }
2384
2385 JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
2386 JNI_GET_STATIC_FIELD(Byte,    jbyte,    i)
2387 JNI_GET_STATIC_FIELD(Char,    jchar,    i)
2388 JNI_GET_STATIC_FIELD(Short,   jshort,   i)
2389 JNI_GET_STATIC_FIELD(Int,     jint,     i)
2390 JNI_GET_STATIC_FIELD(Long,    jlong,    l)
2391 JNI_GET_STATIC_FIELD(Float,   jfloat,   f)
2392 JNI_GET_STATIC_FIELD(Double,  jdouble,  d)
2393
2394
2395 jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
2396                                                                          jfieldID fieldID)
2397 {
2398         classinfo     *c;
2399         fieldinfo     *f;
2400         java_handle_t *h;
2401
2402         STATISTICS(jniinvokation());
2403
2404         c = LLNI_classinfo_unwrap(clazz);
2405         f = (fieldinfo *) fieldID;
2406
2407         if (!(c->state & CLASS_INITIALIZED))
2408                 if (!initialize_class(c))
2409                         return NULL;
2410
2411         h = (java_handle_t*) LLNI_WRAP(f->value->a);
2412
2413         return jni_NewLocalRef(env, (jobject) h);
2414 }
2415
2416
2417 /*  SetStatic<type>Field *******************************************************
2418
2419         This family of accessor routines sets the value of a static field
2420         of an object.
2421
2422 *******************************************************************************/
2423
2424 #define JNI_SET_STATIC_FIELD(name, type, field)                \
2425 void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
2426                                                                         jfieldID fieldID,          \
2427                                                                         type value)                \
2428 {                                                              \
2429         classinfo *c;                                              \
2430         fieldinfo *f;                                              \
2431                                                                \
2432         STATISTICS(jniinvokation());                               \
2433                                                                \
2434         c = LLNI_classinfo_unwrap(clazz);                          \
2435         f = (fieldinfo *) fieldID;                                 \
2436                                                                \
2437         if (!(c->state & CLASS_INITIALIZED))                       \
2438                 if (!initialize_class(c))                              \
2439                         return;                                            \
2440                                                                \
2441         f->value->field = value;                                   \
2442 }
2443
2444 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
2445 JNI_SET_STATIC_FIELD(Byte,    jbyte,    i)
2446 JNI_SET_STATIC_FIELD(Char,    jchar,    i)
2447 JNI_SET_STATIC_FIELD(Short,   jshort,   i)
2448 JNI_SET_STATIC_FIELD(Int,     jint,     i)
2449 JNI_SET_STATIC_FIELD(Long,    jlong,    l)
2450 JNI_SET_STATIC_FIELD(Float,   jfloat,   f)
2451 JNI_SET_STATIC_FIELD(Double,  jdouble,  d)
2452
2453
2454 void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
2455                                                                   jobject value)
2456 {
2457         classinfo *c;
2458         fieldinfo *f;
2459
2460         STATISTICS(jniinvokation());
2461
2462         c = LLNI_classinfo_unwrap(clazz);
2463         f = (fieldinfo *) fieldID;
2464
2465         if (!(c->state & CLASS_INITIALIZED))
2466                 if (!initialize_class(c))
2467                         return;
2468
2469         f->value->a = LLNI_UNWRAP((java_handle_t *) value);
2470 }
2471
2472
2473 /* String Operations **********************************************************/
2474
2475 /* NewString *******************************************************************
2476
2477    Create new java.lang.String object from an array of Unicode
2478    characters.
2479
2480 *******************************************************************************/
2481
2482 jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len)
2483 {
2484         TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len));
2485         
2486         java_handle_chararray_t* a = builtin_newarray_char(len);
2487
2488         if (a == NULL)
2489                 return NULL;
2490
2491         /* copy text */
2492         for (jsize i = 0; i < len; i++)
2493                 LLNI_array_direct(a, i) = buf[i];
2494
2495         java_handle_t* h = builtin_new(class_java_lang_String);
2496
2497         if (h == NULL)
2498                 return NULL;
2499
2500         java_lang_String s(h, a, len, 0);
2501
2502         return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle());
2503 }
2504
2505
2506 static jchar emptyStringJ[]={0,0};
2507
2508 /* GetStringLength *************************************************************
2509
2510    Returns the length (the count of Unicode characters) of a Java
2511    string.
2512
2513 *******************************************************************************/
2514
2515 jsize jni_GetStringLength(JNIEnv *env, jstring str)
2516 {
2517         TRACEJNICALLSENTER(("jni_GetStringLength(env=%p, str=%p)", env, str));
2518
2519         java_lang_String s(str);
2520         jsize count = s.get_count();
2521
2522         TRACEJNICALLSEXIT(("->%d)", count));
2523
2524         return count;
2525 }
2526
2527
2528 /* GetStringChars **************************************************************
2529
2530    Returns a pointer to the array of Unicode characters of the
2531    string. This pointer is valid until ReleaseStringChars() is called.
2532
2533 *******************************************************************************/
2534
2535 const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
2536 {       
2537         u2      *stringbuffer;
2538         int32_t  i;
2539
2540         TRACEJNICALLS(("jni_GetStringChars(env=%p, str=%p, isCopy=%p)", env, str, isCopy));
2541
2542         if (str == NULL)
2543                 // FIXME This is really ugly.
2544                 return emptyStringJ;
2545
2546         java_lang_String s(str);
2547
2548         java_handle_chararray_t* ca     = s.get_value();
2549         int32_t                  count  = s.get_count();
2550         int32_t                  offset = s.get_offset();
2551         
2552         if (ca == NULL)
2553                 return NULL;
2554
2555         /* allocate memory */
2556
2557         stringbuffer = MNEW(u2, count + 1);
2558
2559         /* copy text */
2560
2561         for (i = 0; i < count; i++)
2562                 stringbuffer[i] = LLNI_array_direct(ca, offset + i);
2563         
2564         /* terminate string */
2565
2566         stringbuffer[i] = '\0';
2567
2568         if (isCopy)
2569                 *isCopy = JNI_TRUE;
2570
2571         return (jchar*) stringbuffer;
2572 }
2573
2574
2575 /* ReleaseStringChars **********************************************************
2576
2577    Informs the VM that the native code no longer needs access to
2578    chars. The chars argument is a pointer obtained from string using
2579    GetStringChars().
2580
2581 *******************************************************************************/
2582
2583 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
2584 {
2585         TRACEJNICALLS(("jni_ReleaseStringChars(env=%p, str=%p, chars=%p)", env, str, chars));
2586
2587         // FIXME
2588         if (chars == emptyStringJ)
2589                 return;
2590
2591         java_lang_String s(str);
2592         int32_t count = s.get_count();
2593
2594         MFREE(((jchar*) chars), jchar, count + 1);
2595 }
2596
2597
2598 /* NewStringUTF ****************************************************************
2599
2600    Constructs a new java.lang.String object from an array of UTF-8
2601    characters.
2602
2603 *******************************************************************************/
2604
2605 jstring jni_NewStringUTF(JNIEnv *env, const char *bytes)
2606 {
2607         TRACEJNICALLS(("jni_NewStringUTF(env=%p, bytes=%s)", env, bytes));
2608
2609         java_handle_t *h = javastring_safe_new_from_utf8(bytes);
2610
2611     return (jstring) jni_NewLocalRef(env, (jobject) h);
2612 }
2613
2614
2615 /****************** returns the utf8 length in bytes of a string *******************/
2616
2617 jsize jni_GetStringUTFLength(JNIEnv *env, jstring string)
2618 {   
2619         TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string));
2620
2621         java_lang_String s(string);
2622         java_handle_chararray_t* ca     = s.get_value();
2623         int32_t                  count  = s.get_count();
2624
2625         // FIXME GC critical section!
2626         int32_t length = u2_utflength(ca->data, count);
2627
2628         return length;
2629 }
2630
2631
2632 /* GetStringUTFChars ***********************************************************
2633
2634    Returns a pointer to an array of UTF-8 characters of the
2635    string. This array is valid until it is released by
2636    ReleaseStringUTFChars().
2637
2638 *******************************************************************************/
2639
2640 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
2641                                                                           jboolean *isCopy)
2642 {
2643         utf *u;
2644
2645         STATISTICS(jniinvokation());
2646
2647         if (string == NULL)
2648                 return "";
2649
2650         if (isCopy)
2651                 *isCopy = JNI_TRUE;
2652         
2653         u = javastring_toutf((java_handle_t *) string, false);
2654
2655         if (u != NULL)
2656                 return u->text;
2657
2658         return "";
2659 }
2660
2661
2662 /* ReleaseStringUTFChars *******************************************************
2663
2664    Informs the VM that the native code no longer needs access to
2665    utf. The utf argument is a pointer derived from string using
2666    GetStringUTFChars().
2667
2668 *******************************************************************************/
2669
2670 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
2671 {
2672         STATISTICS(jniinvokation());
2673
2674     /* XXX we don't release utf chars right now, perhaps that should be done 
2675            later. Since there is always one reference the garbage collector will
2676            never get them */
2677 }
2678
2679
2680 /* Array Operations ***********************************************************/
2681
2682 /* GetArrayLength **************************************************************
2683
2684    Returns the number of elements in the array.
2685
2686 *******************************************************************************/
2687
2688 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
2689 {
2690         java_handle_t *a;
2691         jsize          size;
2692
2693         TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
2694
2695         a = (java_handle_t *) array;
2696
2697         size = LLNI_array_size(a);
2698
2699         return size;
2700 }
2701
2702
2703 /* NewObjectArray **************************************************************
2704
2705    Constructs a new array holding objects in class elementClass. All
2706    elements are initially set to initialElement.
2707
2708 *******************************************************************************/
2709
2710 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
2711                                                                         jclass elementClass, jobject initialElement)
2712 {
2713         classinfo                 *c;
2714         java_handle_t             *o;
2715         java_handle_objectarray_t *oa;
2716         s4                         i;
2717
2718         STATISTICS(jniinvokation());
2719
2720         c = LLNI_classinfo_unwrap(elementClass);
2721         o = (java_handle_t *) initialElement;
2722
2723         if (length < 0) {
2724                 exceptions_throw_negativearraysizeexception();
2725                 return NULL;
2726         }
2727
2728     oa = builtin_anewarray(length, c);
2729
2730         if (oa == NULL)
2731                 return NULL;
2732
2733         /* set all elements to initialElement */
2734
2735         for (i = 0; i < length; i++)
2736                 array_objectarray_element_set(oa, i, o);
2737
2738         return (jobjectArray) jni_NewLocalRef(env, (jobject) oa);
2739 }
2740
2741
2742 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
2743                                                                           jsize index)
2744 {
2745         java_handle_objectarray_t *oa;
2746         java_handle_t             *o;
2747
2748         STATISTICS(jniinvokation());
2749
2750         oa = (java_handle_objectarray_t *) array;
2751
2752         if (index >= LLNI_array_size(oa)) {
2753                 exceptions_throw_arrayindexoutofboundsexception();
2754                 return NULL;
2755         }
2756
2757         o = array_objectarray_element_get(oa, index);
2758
2759         return jni_NewLocalRef(env, (jobject) o);
2760 }
2761
2762
2763 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
2764                                                                    jsize index, jobject val)
2765 {
2766         java_handle_objectarray_t *oa;
2767         java_handle_t             *o;
2768
2769         STATISTICS(jniinvokation());
2770
2771         oa = (java_handle_objectarray_t *) array;
2772         o  = (java_handle_t *) val;
2773
2774         if (index >= LLNI_array_size(oa)) {
2775                 exceptions_throw_arrayindexoutofboundsexception();
2776                 return;
2777         }
2778
2779         /* check if the class of value is a subclass of the element class
2780            of the array */
2781
2782         if (!builtin_canstore(oa, o))
2783                 return;
2784
2785         array_objectarray_element_set(oa, index, o);
2786 }
2787
2788
2789 #define JNI_NEW_ARRAY(name, type, intern)                \
2790 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
2791 {                                                        \
2792         java_handle_##intern##array_t *a;                    \
2793                                                          \
2794         STATISTICS(jniinvokation());                         \
2795                                                          \
2796         if (len < 0) {                                       \
2797                 exceptions_throw_negativearraysizeexception();   \
2798                 return NULL;                                     \
2799         }                                                    \
2800                                                          \
2801         a = builtin_newarray_##intern(len);                  \
2802                                                          \
2803         return (type) jni_NewLocalRef(env, (jobject) a); \
2804 }
2805
2806 JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
2807 JNI_NEW_ARRAY(Byte,    jbyteArray,    byte)
2808 JNI_NEW_ARRAY(Char,    jcharArray,    char)
2809 JNI_NEW_ARRAY(Short,   jshortArray,   short)
2810 JNI_NEW_ARRAY(Int,     jintArray,     int)
2811 JNI_NEW_ARRAY(Long,    jlongArray,    long)
2812 JNI_NEW_ARRAY(Float,   jfloatArray,   float)
2813 JNI_NEW_ARRAY(Double,  jdoubleArray,  double)
2814
2815
2816 /* Get<PrimitiveType>ArrayElements *********************************************
2817
2818    A family of functions that returns the body of the primitive array.
2819
2820 *******************************************************************************/
2821
2822 #define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
2823 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
2824                                                                                  jboolean *isCopy)             \
2825 {                                                                      \
2826         java_handle_##intern##array_t *a;                                  \
2827                                                                        \
2828         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
2829                                                                        \
2830         a = (java_handle_##intern##array_t *) array;                       \
2831                                                                        \
2832         if (isCopy)                                                        \
2833                 *isCopy = JNI_FALSE;                                           \
2834                                                                        \
2835         return (type *) LLNI_array_data(a);                                \
2836 }
2837
2838 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
2839 JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
2840 JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
2841 JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
2842 JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
2843 JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
2844 JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
2845 JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
2846
2847
2848 /* Release<PrimitiveType>ArrayElements *****************************************
2849
2850    A family of functions that informs the VM that the native code no
2851    longer needs access to elems. The elems argument is a pointer
2852    derived from array using the corresponding
2853    Get<PrimitiveType>ArrayElements() function. If necessary, this
2854    function copies back all changes made to elems to the original
2855    array.
2856
2857 *******************************************************************************/
2858
2859 #define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
2860 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
2861                                                                                   type *elems, jint mode)          \
2862 {                                                                          \
2863         java_handle_##intern##array_t *a;                                      \
2864                                                                            \
2865         STATISTICS(jniinvokation());                                           \
2866                                                                            \
2867         a = (java_handle_##intern##array_t *) array;                           \
2868                                                                            \
2869         if (elems != (type *) LLNI_array_data(a)) {                            \
2870                 switch (mode) {                                                    \
2871                 case JNI_COMMIT:                                                   \
2872                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
2873                         break;                                                         \
2874                 case 0:                                                            \
2875                         MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
2876                         /* XXX TWISTI how should it be freed? */                       \
2877                         break;                                                         \
2878                 case JNI_ABORT:                                                    \
2879                         /* XXX TWISTI how should it be freed? */                       \
2880                         break;                                                         \
2881                 }                                                                  \
2882         }                                                                      \
2883 }
2884
2885 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
2886 JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
2887 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
2888 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
2889 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
2890 JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
2891 JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
2892 JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
2893
2894
2895 /*  Get<PrimitiveType>ArrayRegion **********************************************
2896
2897         A family of functions that copies a region of a primitive array
2898         into a buffer.
2899
2900 *******************************************************************************/
2901
2902 #define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
2903 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
2904                                                                         jsize start, jsize len, type *buf)  \
2905 {                                                                       \
2906         java_handle_##intern##array_t *a;                                   \
2907                                                                         \
2908         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
2909                                                                         \
2910         a = (java_handle_##intern##array_t *) array;                        \
2911                                                                         \
2912         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
2913                 exceptions_throw_arrayindexoutofboundsexception();              \
2914         else                                                                \
2915                 MCOPY(buf, &LLNI_array_direct(a, start), intern2, len);         \
2916 }
2917
2918 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2919 JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2920 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
2921 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
2922 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
2923 JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
2924 JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
2925 JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
2926
2927
2928 /*  Set<PrimitiveType>ArrayRegion **********************************************
2929
2930         A family of functions that copies back a region of a primitive
2931         array from a buffer.
2932
2933 *******************************************************************************/
2934
2935 #define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
2936 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
2937                                                                         jsize start, jsize len, const type *buf) \
2938 {                                                                            \
2939         java_handle_##intern##array_t *a;                                        \
2940                                                                              \
2941         STATISTICS(jniinvokation());                                             \
2942                                                                              \
2943         a = (java_handle_##intern##array_t *) array;                             \
2944                                                                              \
2945         if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a)))      \
2946                 exceptions_throw_arrayindexoutofboundsexception();                   \
2947         else                                                                     \
2948                 MCOPY(&LLNI_array_direct(a, start), buf, intern2, len);              \
2949 }
2950
2951 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2952 JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2953 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
2954 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
2955 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
2956 JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
2957 JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
2958 JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
2959
2960
2961 /* Registering Native Methods *************************************************/
2962
2963 /* RegisterNatives *************************************************************
2964
2965    Registers native methods with the class specified by the clazz
2966    argument. The methods parameter specifies an array of
2967    JNINativeMethod structures that contain the names, signatures, and
2968    function pointers of the native methods. The nMethods parameter
2969    specifies the number of native methods in the array.
2970
2971 *******************************************************************************/
2972
2973 jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods)
2974 {
2975         TRACEJNICALLS(("jni_RegisterNatives(env=%p, clazz=%p, methods=%p, nMethods=%d)", env, clazz, methods, nMethods));
2976
2977         classinfo* c = LLNI_classinfo_unwrap(clazz);
2978
2979         /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
2980         if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
2981         */
2982
2983         NativeMethods& nm = VM::get_current()->get_nativemethods();
2984         nm.register_methods(c->name, methods, nMethods);
2985
2986     return 0;
2987 }
2988
2989
2990 /* UnregisterNatives ***********************************************************
2991
2992    Unregisters native methods of a class. The class goes back to the
2993    state before it was linked or registered with its native method
2994    functions.
2995
2996    This function should not be used in normal native code. Instead, it
2997    provides special programs a way to reload and relink native
2998    libraries.
2999
3000 *******************************************************************************/
3001
3002 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
3003 {
3004         STATISTICS(jniinvokation());
3005
3006         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
3007
3008     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
3009
3010     return 0;
3011 }
3012
3013
3014 /* Monitor Operations *********************************************************/
3015
3016 /* MonitorEnter ****************************************************************
3017
3018    Enters the monitor associated with the underlying Java object
3019    referred to by obj.
3020
3021 *******************************************************************************/
3022
3023 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
3024 {
3025         STATISTICS(jniinvokation());
3026
3027         if (obj == NULL) {
3028                 exceptions_throw_nullpointerexception();
3029                 return JNI_ERR;
3030         }
3031
3032         LOCK_MONITOR_ENTER(obj);
3033
3034         return JNI_OK;
3035 }
3036
3037
3038 /* MonitorExit *****************************************************************
3039
3040    The current thread must be the owner of the monitor associated with
3041    the underlying Java object referred to by obj. The thread
3042    decrements the counter indicating the number of times it has
3043    entered this monitor. If the value of the counter becomes zero, the
3044    current thread releases the monitor.
3045
3046 *******************************************************************************/
3047
3048 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
3049 {
3050         STATISTICS(jniinvokation());
3051
3052         if (obj == NULL) {
3053                 exceptions_throw_nullpointerexception();
3054                 return JNI_ERR;
3055         }
3056
3057         LOCK_MONITOR_EXIT(obj);
3058
3059         return JNI_OK;
3060 }
3061
3062
3063 /* JavaVM Interface ***********************************************************/
3064
3065 /* GetJavaVM *******************************************************************
3066
3067    Returns the Java VM interface (used in the Invocation API)
3068    associated with the current thread. The result is placed at the
3069    location pointed to by the second argument, vm.
3070
3071 *******************************************************************************/
3072
3073 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
3074 {
3075         STATISTICS(jniinvokation());
3076
3077     *javavm = VM::get_current()->get_javavm();
3078
3079         return 0;
3080 }
3081
3082
3083 /* GetStringRegion *************************************************************
3084
3085    Copies len number of Unicode characters beginning at offset start
3086    to the given buffer buf.
3087
3088    Throws StringIndexOutOfBoundsException on index overflow.
3089
3090 *******************************************************************************/
3091
3092 void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
3093 {
3094         java_lang_String s(str);
3095         java_handle_chararray_t* ca    = s.get_value();
3096         int32_t                  count = s.get_count();
3097
3098         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3099                 exceptions_throw_stringindexoutofboundsexception();
3100                 return;
3101         }
3102
3103         MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
3104 }
3105
3106
3107 /* GetStringUTFRegion **********************************************************
3108
3109     Translates len number of Unicode characters beginning at offset
3110     start into UTF-8 format and place the result in the given buffer
3111     buf.
3112
3113     Throws StringIndexOutOfBoundsException on index overflow. 
3114
3115 *******************************************************************************/
3116
3117 void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
3118 {
3119         TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
3120
3121         java_lang_String s(str);
3122         java_handle_chararray_t* ca     = s.get_value();
3123         int32_t                  count  = s.get_count();
3124         int32_t                  offset = s.get_offset();
3125
3126         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3127                 exceptions_throw_stringindexoutofboundsexception();
3128                 return;
3129         }
3130
3131         int32_t i;
3132
3133         for (i = 0; i < len; i++)
3134                 buf[i] = LLNI_array_direct(ca, offset + start + i);
3135
3136         buf[i] = '\0';
3137 }
3138
3139
3140 /* GetPrimitiveArrayCritical ***************************************************
3141
3142    Obtain a direct pointer to array elements.
3143
3144    ATTENTION: Critical section keeps open when this function returns!
3145    See ReleasePrimitiveArrayCritical.
3146
3147 *******************************************************************************/
3148
3149 void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
3150 {
3151         java_handle_t*   h;
3152         java_array_t*    a;
3153         arraydescriptor* ad;
3154         void*            data;
3155
3156         TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
3157
3158         if (isCopy != NULL) {
3159                 *isCopy = JNI_FALSE;
3160         }
3161
3162         LLNI_CRITICAL_START;
3163
3164         h  = (java_handle_t*) array;
3165         a  = (java_array_t*) LLNI_UNWRAP(h);
3166         ad = a->objheader.vftbl->arraydesc;
3167
3168         /* Sanity check. */
3169
3170         assert(ad != NULL);
3171
3172         data = (void*) (((intptr_t) a) + ad->dataoffset);
3173
3174         return data;
3175 }
3176
3177
3178 /* ReleasePrimitiveArrayCritical ***********************************************
3179
3180    No specific documentation.
3181
3182    ATTENTION: This function closes the critical section opened in
3183    GetPrimitiveArrayCritical!
3184
3185 *******************************************************************************/
3186
3187 void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
3188 {
3189         TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
3190
3191         LLNI_CRITICAL_END;
3192 }
3193
3194
3195 /* GetStringCritical ***********************************************************
3196
3197    The semantics of these two functions are similar to the existing
3198    Get/ReleaseStringChars functions.
3199
3200 *******************************************************************************/
3201
3202 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
3203                                                                            jboolean *isCopy)
3204 {
3205         STATISTICS(jniinvokation());
3206
3207         return jni_GetStringChars(env, string, isCopy);
3208 }
3209
3210
3211 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
3212                                                                    const jchar *cstring)
3213 {
3214         STATISTICS(jniinvokation());
3215
3216         _Jv_JNI_ReleaseStringChars(env, string, cstring);
3217 }
3218
3219
3220 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
3221 {
3222         TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
3223
3224         return (jweak) obj;
3225 }
3226
3227
3228 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
3229 {
3230         TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
3231 }
3232
3233
3234 /* NewGlobalRef ****************************************************************
3235
3236    Creates a new global reference to the object referred to by the obj
3237    argument.
3238
3239 *******************************************************************************/
3240
3241 jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
3242 {
3243         hashtable_global_ref_entry *gre;
3244         u4   key;                           /* hashkey                            */
3245         u4   slot;                          /* slot in hashtable                  */
3246         java_handle_t *o;
3247
3248         TRACEJNICALLS(("jni_NewGlobalRef(env=%p, obj=%p)", env, obj));
3249
3250         o = (java_handle_t *) obj;
3251
3252         hashtable_global_ref->mutex->lock();
3253
3254         LLNI_CRITICAL_START;
3255
3256         /* normally addresses are aligned to 4, 8 or 16 bytes */
3257
3258         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3259         slot = key & (hashtable_global_ref->size - 1);
3260         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3261         
3262         /* search external hash chain for the entry */
3263
3264         while (gre) {
3265                 if (gre->o == LLNI_DIRECT(o)) {
3266                         /* global object found, increment the reference */
3267
3268                         gre->refs++;
3269
3270                         break;
3271                 }
3272
3273                 gre = gre->hashlink;                /* next element in external chain */
3274         }
3275
3276         LLNI_CRITICAL_END;
3277
3278         /* global ref not found, create a new one */
3279
3280         if (gre == NULL) {
3281                 gre = (hashtable_global_ref_entry*) heap_alloc_uncollectable(sizeof(hashtable_global_ref_entry));
3282
3283 #if defined(ENABLE_GC_CACAO)
3284                 /* register global ref with the GC */
3285
3286                 gc_reference_register(&(gre->o), GC_REFTYPE_JNI_GLOBALREF);
3287 #endif
3288
3289                 LLNI_CRITICAL_START;
3290
3291                 gre->o    = LLNI_DIRECT(o);
3292                 gre->refs = 1;
3293
3294                 LLNI_CRITICAL_END;
3295
3296                 /* insert entry into hashtable */
3297
3298                 gre->hashlink = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3299
3300                 hashtable_global_ref->ptr[slot] = gre;
3301
3302                 /* update number of hashtable-entries */
3303
3304                 hashtable_global_ref->entries++;
3305         }
3306
3307         hashtable_global_ref->mutex->unlock();
3308
3309 #if defined(ENABLE_HANDLES)
3310         return gre;
3311 #else
3312         return obj;
3313 #endif
3314 }
3315
3316
3317 /* DeleteGlobalRef *************************************************************
3318
3319    Deletes the global reference pointed to by globalRef.
3320
3321 *******************************************************************************/
3322
3323 void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
3324 {
3325         hashtable_global_ref_entry *gre;
3326         hashtable_global_ref_entry *prevgre;
3327         u4   key;                           /* hashkey                            */
3328         u4   slot;                          /* slot in hashtable                  */
3329         java_handle_t              *o;
3330
3331         TRACEJNICALLS(("jni_DeleteGlobalRef(env=%p, globalRef=%p)", env, globalRef));
3332
3333         o = (java_handle_t *) globalRef;
3334
3335         hashtable_global_ref->mutex->lock();
3336
3337         LLNI_CRITICAL_START;
3338
3339         /* normally addresses are aligned to 4, 8 or 16 bytes */
3340
3341         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3342         slot = key & (hashtable_global_ref->size - 1);
3343         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3344
3345         /* initialize prevgre */
3346
3347         prevgre = NULL;
3348
3349         /* search external hash chain for the entry */
3350
3351         while (gre) {
3352                 if (gre->o == LLNI_DIRECT(o)) {
3353                         /* global object found, decrement the reference count */
3354
3355                         gre->refs--;
3356
3357                         /* if reference count is 0, remove the entry */
3358
3359                         if (gre->refs == 0) {
3360                                 /* special handling if it's the first in the chain */
3361
3362                                 if (prevgre == NULL)
3363                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
3364                                 else
3365                                         prevgre->hashlink = gre->hashlink;
3366
3367 #if defined(ENABLE_GC_CACAO)
3368                                 /* unregister global ref with the GC */
3369
3370                                 gc_reference_unregister(&(gre->o));
3371 #endif
3372
3373                                 heap_free(gre);
3374                         }
3375
3376                         LLNI_CRITICAL_END;
3377
3378                         hashtable_global_ref->mutex->unlock();
3379
3380                         return;
3381                 }
3382
3383                 prevgre = gre;                    /* save current pointer for removal */
3384                 gre     = gre->hashlink;            /* next element in external chain */
3385         }
3386
3387         log_println("jni_DeleteGlobalRef: Global reference not found.");
3388
3389         LLNI_CRITICAL_END;
3390
3391         hashtable_global_ref->mutex->unlock();
3392 }
3393
3394
3395 /* ExceptionCheck **************************************************************
3396
3397    Returns JNI_TRUE when there is a pending exception; otherwise,
3398    returns JNI_FALSE.
3399
3400 *******************************************************************************/
3401
3402 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
3403 {
3404         java_handle_t *o;
3405
3406         STATISTICS(jniinvokation());
3407
3408         o = exceptions_get_exception();
3409
3410         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
3411 }
3412
3413
3414 /* New JNI 1.4 functions ******************************************************/
3415
3416 /* NewDirectByteBuffer *********************************************************
3417
3418    Allocates and returns a direct java.nio.ByteBuffer referring to the
3419    block of memory starting at the memory address address and
3420    extending capacity bytes.
3421
3422 *******************************************************************************/
3423
3424 jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
3425 {
3426 #if defined(ENABLE_JAVASE)
3427 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3428         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3429
3430         // Allocate a gnu.classpath.Pointer{32,64} object.
3431
3432 # if SIZEOF_VOID_P == 8
3433         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer64);
3434 # else
3435         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer32);
3436 # endif
3437
3438         if (h == NULL)
3439                 return NULL;
3440
3441         gnu_classpath_Pointer p(h, address);
3442
3443         // Create a java.nio.DirectByteBufferImpl$ReadWrite object.
3444
3445         java_handle_t* nbuf =
3446                 (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
3447                                                                            (jmethodID) dbbirw_init, NULL, p.get_handle(),
3448                                                                            (jint) capacity, (jint) capacity, (jint) 0);
3449
3450         // Add a local reference and return the value.
3451
3452         TRACEJNICALLSEXIT(("->%p", nbuf));
3453
3454         return jni_NewLocalRef(env, (jobject) nbuf);
3455
3456 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3457
3458         jobject o;
3459         int64_t addr;
3460         int32_t cap;
3461
3462         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3463
3464         /* Be paranoid about address sign-extension. */
3465
3466         addr = (int64_t) ((uintptr_t) address);
3467         cap  = (int32_t) capacity;
3468
3469         o = jni_NewObject(env, (jclass) class_java_nio_DirectByteBuffer,
3470                                           (jmethodID) dbb_init, addr, cap);
3471
3472         /* Add local reference and return the value. */
3473
3474         TRACEJNICALLSEXIT(("->%p", o));
3475
3476         return jni_NewLocalRef(env, o);
3477
3478 # else
3479 #  error unknown classpath configuration
3480 # endif
3481
3482 #else
3483         vm_abort("jni_NewDirectByteBuffer: Not implemented in this configuration.");
3484
3485         /* keep compiler happy */
3486
3487         return NULL;
3488 #endif
3489 }
3490
3491
3492 /* GetDirectBufferAddress ******************************************************
3493
3494    Fetches and returns the starting address of the memory region
3495    referenced by the given direct java.nio.Buffer.
3496
3497 *******************************************************************************/
3498
3499 void* jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3500 {
3501 #if defined(ENABLE_JAVASE)
3502 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3503
3504         TRACEJNICALLSENTER(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3505
3506         /* Prevent compiler warning. */
3507
3508         java_handle_t* h = (java_handle_t *) buf;
3509
3510         if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
3511                 return NULL;
3512
3513         java_nio_DirectByteBufferImpl dbb(buf);
3514         java_handle_t* address = dbb.get_address();
3515
3516         if (address == NULL) {
3517                 TRACEJNICALLSEXIT(("->%p", NULL));
3518                 return NULL;
3519         }
3520
3521         gnu_classpath_Pointer p(address);
3522         void* data = p.get_data();
3523
3524         TRACEJNICALLSEXIT(("->%p", data));
3525
3526         return data;
3527
3528 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3529
3530         TRACEJNICALLS(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3531
3532         java_nio_Buffer jnb(buf);
3533
3534         if (jnb.is_non_null() && !builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
3535                 return NULL;
3536
3537         void* address = jnb.get_address();
3538
3539         return address;
3540
3541 # else
3542 #  error unknown classpath configuration
3543 # endif
3544
3545 #else
3546
3547         vm_abort("jni_GetDirectBufferAddress: Not implemented in this configuration.");
3548
3549         // Keep compiler happy.
3550         return NULL;
3551
3552 #endif
3553 }
3554
3555
3556 /* GetDirectBufferCapacity *****************************************************
3557
3558    Fetches and returns the capacity in bytes of the memory region
3559    referenced by the given direct java.nio.Buffer.
3560
3561 *******************************************************************************/
3562
3563 jlong jni_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
3564 {
3565 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3566         TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
3567
3568         java_handle_t* h = (java_handle_t *) buf;
3569
3570         if (!builtin_instanceof(h, class_java_nio_DirectByteBufferImpl))
3571                 return -1;
3572
3573         java_nio_Buffer b(h);
3574         jlong capacity = b.get_cap();
3575
3576         return capacity;
3577 #else
3578         vm_abort("jni_GetDirectBufferCapacity: not implemented in this configuration");
3579
3580         // Keep compiler happy.
3581
3582         return 0;
3583 #endif
3584 }
3585
3586
3587 /* GetObjectRefType ************************************************************
3588
3589    Returns the type of the object referred to by the obj argument. The
3590    argument obj can either be a local, global or weak global
3591    reference.
3592
3593 *******************************************************************************/
3594
3595 jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj)
3596 {
3597         log_println("jni_GetObjectRefType: IMPLEMENT ME!");
3598
3599         return (jobjectRefType) NULL;
3600 }
3601
3602
3603 /* DestroyJavaVM ***************************************************************
3604
3605    Unloads a Java VM and reclaims its resources. Only the main thread
3606    can unload the VM. The system waits until the main thread is only
3607    remaining user thread before it destroys the VM.
3608
3609 *******************************************************************************/
3610
3611 jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
3612 {
3613         int status;
3614
3615         TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
3616
3617         if (VM::get_current()->is_created() == false)
3618                 return JNI_ERR;
3619
3620     status = vm_destroy(javavm);
3621
3622         return status;
3623 }
3624
3625
3626 /* AttachCurrentThread *********************************************************
3627
3628    Attaches the current thread to a Java VM. Returns a JNI interface
3629    pointer in the JNIEnv argument.
3630
3631    Trying to attach a thread that is already attached is a no-op.
3632
3633    A native thread cannot be attached simultaneously to two Java VMs.
3634
3635    When a thread is attached to the VM, the context class loader is
3636    the bootstrap loader.
3637
3638 *******************************************************************************/
3639
3640 static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
3641 {
3642 #if defined(ENABLE_THREADS)
3643         JavaVMAttachArgs *vm_aargs;
3644         bool              result;
3645
3646     /* If the current thread has already been attached, this operation
3647            is a no-op. */
3648
3649         result = thread_current_is_attached();
3650
3651         if (result == true) {
3652                 *p_env = VM::get_current()->get_jnienv();
3653                 return JNI_OK;
3654         }
3655
3656         vm_aargs = (JavaVMAttachArgs *) thr_args;
3657
3658         if (vm_aargs != NULL) {
3659                 if ((vm_aargs->version != JNI_VERSION_1_2) &&
3660                         (vm_aargs->version != JNI_VERSION_1_4))
3661                         return JNI_EVERSION;
3662         }
3663
3664         if (!thread_attach_current_external_thread(vm_aargs, false))
3665                 return JNI_ERR;
3666
3667         if (!localref_table_init())
3668                 return JNI_ERR;
3669 #endif
3670
3671         *p_env = VM::get_current()->get_jnienv();
3672
3673         return JNI_OK;
3674 }
3675
3676
3677 jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
3678 {
3679         int result;
3680
3681         TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
3682
3683         if (VM::get_current()->is_created() == false)
3684                 return JNI_ERR;
3685
3686         result = jni_attach_current_thread(p_env, thr_args, false);
3687
3688         return result;
3689 }
3690
3691
3692 /* DetachCurrentThread *********************************************************
3693
3694    Detaches the current thread from a Java VM. All Java monitors held
3695    by this thread are released. All Java threads waiting for this
3696    thread to die are notified.
3697
3698    In JDK 1.1, the main thread cannot be detached from the VM. It must
3699    call DestroyJavaVM to unload the entire VM.
3700
3701    In the JDK, the main thread can be detached from the VM.
3702
3703    The main thread, which is the thread that created the Java VM,
3704    cannot be detached from the VM. Instead, the main thread must call
3705    JNI_DestroyJavaVM() to unload the entire VM.
3706
3707 *******************************************************************************/
3708
3709 jint jni_DetachCurrentThread(JavaVM *vm)
3710 {
3711 #if defined(ENABLE_THREADS)
3712         bool result;
3713
3714         TRACEJNICALLS(("jni_DetachCurrentThread(vm=%p)", vm));
3715
3716     /* If the current thread has already been detached, this operation
3717            is a no-op. */
3718
3719         result = thread_current_is_attached();
3720
3721         if (result == false)
3722                 return true;
3723
3724         /* We need to pop all frames before we can destroy the table. */
3725
3726         localref_frame_pop_all();
3727
3728         if (!localref_table_destroy())
3729                 return JNI_ERR;
3730
3731         if (!thread_detach_current_external_thread())
3732                 return JNI_ERR;
3733 #endif
3734
3735         return JNI_OK;
3736 }
3737
3738
3739 /* GetEnv **********************************************************************
3740
3741    If the current thread is not attached to the VM, sets *env to NULL,
3742    and returns JNI_EDETACHED. If the specified version is not
3743    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
3744    sets *env to the appropriate interface, and returns JNI_OK.
3745
3746 *******************************************************************************/
3747
3748 jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
3749 {
3750         TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
3751
3752         if (VM::get_current()->is_created() == false) {
3753                 *env = NULL;
3754                 return JNI_EDETACHED;
3755         }
3756
3757 #if defined(ENABLE_THREADS)
3758         if (thread_get_current() == NULL) {
3759                 *env = NULL;
3760
3761                 return JNI_EDETACHED;
3762         }
3763 #endif
3764
3765         /* Check the JNI version. */
3766
3767         if (jni_version_check(version) == true) {
3768                 *env = VM::get_current()->get_jnienv();
3769                 return JNI_OK;
3770         }
3771
3772 #if defined(ENABLE_JVMTI)
3773         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
3774                 == JVMTI_VERSION_INTERFACE_JVMTI) {
3775
3776                 *env = (void *) jvmti_new_environment();
3777
3778                 if (env != NULL)
3779                         return JNI_OK;
3780         }
3781 #endif
3782         
3783         *env = NULL;
3784
3785         return JNI_EVERSION;
3786 }
3787
3788
3789 /* AttachCurrentThreadAsDaemon *************************************************
3790
3791    Same semantics as AttachCurrentThread, but the newly-created
3792    java.lang.Thread instance is a daemon.
3793
3794    If the thread has already been attached via either
3795    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
3796    simply sets the value pointed to by penv to the JNIEnv of the
3797    current thread. In this case neither AttachCurrentThread nor this
3798    routine have any effect on the daemon status of the thread.
3799
3800 *******************************************************************************/
3801
3802 jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
3803 {
3804         int result;
3805
3806         TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
3807
3808         if (VM::get_current()->is_created() == false)
3809                 return JNI_ERR;
3810
3811         result = jni_attach_current_thread(penv, args, true);
3812
3813         return result;
3814 }
3815
3816
3817 /* JNI invocation table *******************************************************/
3818
3819 const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
3820         NULL,
3821         NULL,
3822         NULL,
3823
3824         _Jv_JNI_DestroyJavaVM,
3825         jni_AttachCurrentThread,
3826         jni_DetachCurrentThread,
3827         jni_GetEnv,
3828         jni_AttachCurrentThreadAsDaemon
3829 };
3830
3831
3832 /* JNI function table *********************************************************/
3833
3834 struct JNINativeInterface_ _Jv_JNINativeInterface = {
3835         NULL,
3836         NULL,
3837         NULL,
3838         NULL,    
3839         _Jv_JNI_GetVersion,
3840
3841         jni_DefineClass,
3842         jni_FindClass,
3843         jni_FromReflectedMethod,
3844         jni_FromReflectedField,
3845         jni_ToReflectedMethod,
3846         jni_GetSuperclass,
3847         _Jv_JNI_IsAssignableFrom,
3848         _Jv_JNI_ToReflectedField,
3849
3850         _Jv_JNI_Throw,
3851         _Jv_JNI_ThrowNew,
3852         _Jv_JNI_ExceptionOccurred,
3853         jni_ExceptionDescribe,
3854         jni_ExceptionClear,
3855         _Jv_JNI_FatalError,
3856         jni_PushLocalFrame,
3857         jni_PopLocalFrame,
3858
3859         jni_NewGlobalRef,
3860         jni_DeleteGlobalRef,
3861         jni_DeleteLocalRef,
3862         _Jv_JNI_IsSameObject,
3863         jni_NewLocalRef,
3864         jni_EnsureLocalCapacity,
3865
3866         _Jv_JNI_AllocObject,
3867         jni_NewObject,
3868         _Jv_JNI_NewObjectV,
3869         _Jv_JNI_NewObjectA,
3870
3871         jni_GetObjectClass,
3872         _Jv_JNI_IsInstanceOf,
3873
3874         _Jv_JNI_GetMethodID,
3875
3876         _Jv_JNI_CallObjectMethod,
3877         _Jv_JNI_CallObjectMethodV,
3878         _Jv_JNI_CallObjectMethodA,
3879         _Jv_JNI_CallBooleanMethod,
3880         _Jv_JNI_CallBooleanMethodV,
3881         _Jv_JNI_CallBooleanMethodA,
3882         _Jv_JNI_CallByteMethod,
3883         _Jv_JNI_CallByteMethodV,
3884         _Jv_JNI_CallByteMethodA,
3885         _Jv_JNI_CallCharMethod,
3886         _Jv_JNI_CallCharMethodV,
3887         _Jv_JNI_CallCharMethodA,
3888         _Jv_JNI_CallShortMethod,
3889         _Jv_JNI_CallShortMethodV,
3890         _Jv_JNI_CallShortMethodA,
3891         _Jv_JNI_CallIntMethod,
3892         _Jv_JNI_CallIntMethodV,
3893         _Jv_JNI_CallIntMethodA,
3894         _Jv_JNI_CallLongMethod,
3895         _Jv_JNI_CallLongMethodV,
3896         _Jv_JNI_CallLongMethodA,
3897         _Jv_JNI_CallFloatMethod,
3898         _Jv_JNI_CallFloatMethodV,
3899         _Jv_JNI_CallFloatMethodA,
3900         _Jv_JNI_CallDoubleMethod,
3901         _Jv_JNI_CallDoubleMethodV,
3902         _Jv_JNI_CallDoubleMethodA,
3903         _Jv_JNI_CallVoidMethod,
3904         _Jv_JNI_CallVoidMethodV,
3905         _Jv_JNI_CallVoidMethodA,
3906
3907         _Jv_JNI_CallNonvirtualObjectMethod,
3908         _Jv_JNI_CallNonvirtualObjectMethodV,
3909         _Jv_JNI_CallNonvirtualObjectMethodA,
3910         _Jv_JNI_CallNonvirtualBooleanMethod,
3911         _Jv_JNI_CallNonvirtualBooleanMethodV,
3912         _Jv_JNI_CallNonvirtualBooleanMethodA,
3913         _Jv_JNI_CallNonvirtualByteMethod,
3914         _Jv_JNI_CallNonvirtualByteMethodV,
3915         _Jv_JNI_CallNonvirtualByteMethodA,
3916         _Jv_JNI_CallNonvirtualCharMethod,
3917         _Jv_JNI_CallNonvirtualCharMethodV,
3918         _Jv_JNI_CallNonvirtualCharMethodA,
3919         _Jv_JNI_CallNonvirtualShortMethod,
3920         _Jv_JNI_CallNonvirtualShortMethodV,
3921         _Jv_JNI_CallNonvirtualShortMethodA,
3922         _Jv_JNI_CallNonvirtualIntMethod,
3923         _Jv_JNI_CallNonvirtualIntMethodV,
3924         _Jv_JNI_CallNonvirtualIntMethodA,
3925         _Jv_JNI_CallNonvirtualLongMethod,
3926         _Jv_JNI_CallNonvirtualLongMethodV,
3927         _Jv_JNI_CallNonvirtualLongMethodA,
3928         _Jv_JNI_CallNonvirtualFloatMethod,
3929         _Jv_JNI_CallNonvirtualFloatMethodV,
3930         _Jv_JNI_CallNonvirtualFloatMethodA,
3931         _Jv_JNI_CallNonvirtualDoubleMethod,
3932         _Jv_JNI_CallNonvirtualDoubleMethodV,
3933         _Jv_JNI_CallNonvirtualDoubleMethodA,
3934         _Jv_JNI_CallNonvirtualVoidMethod,
3935         _Jv_JNI_CallNonvirtualVoidMethodV,
3936         _Jv_JNI_CallNonvirtualVoidMethodA,
3937
3938         _Jv_JNI_GetFieldID,
3939
3940         _Jv_JNI_GetObjectField,
3941         _Jv_JNI_GetBooleanField,
3942         _Jv_JNI_GetByteField,
3943         _Jv_JNI_GetCharField,
3944         _Jv_JNI_GetShortField,
3945         _Jv_JNI_GetIntField,
3946         _Jv_JNI_GetLongField,
3947         _Jv_JNI_GetFloatField,
3948         _Jv_JNI_GetDoubleField,
3949         _Jv_JNI_SetObjectField,
3950         _Jv_JNI_SetBooleanField,
3951         _Jv_JNI_SetByteField,
3952         _Jv_JNI_SetCharField,
3953         _Jv_JNI_SetShortField,
3954         _Jv_JNI_SetIntField,
3955         _Jv_JNI_SetLongField,
3956         _Jv_JNI_SetFloatField,
3957         _Jv_JNI_SetDoubleField,
3958
3959         _Jv_JNI_GetStaticMethodID,
3960
3961         _Jv_JNI_CallStaticObjectMethod,
3962         _Jv_JNI_CallStaticObjectMethodV,
3963         _Jv_JNI_CallStaticObjectMethodA,
3964         _Jv_JNI_CallStaticBooleanMethod,
3965         _Jv_JNI_CallStaticBooleanMethodV,
3966         _Jv_JNI_CallStaticBooleanMethodA,
3967         _Jv_JNI_CallStaticByteMethod,
3968         _Jv_JNI_CallStaticByteMethodV,
3969         _Jv_JNI_CallStaticByteMethodA,
3970         _Jv_JNI_CallStaticCharMethod,
3971         _Jv_JNI_CallStaticCharMethodV,
3972         _Jv_JNI_CallStaticCharMethodA,
3973         _Jv_JNI_CallStaticShortMethod,
3974         _Jv_JNI_CallStaticShortMethodV,
3975         _Jv_JNI_CallStaticShortMethodA,
3976         _Jv_JNI_CallStaticIntMethod,
3977         _Jv_JNI_CallStaticIntMethodV,
3978         _Jv_JNI_CallStaticIntMethodA,
3979         _Jv_JNI_CallStaticLongMethod,
3980         _Jv_JNI_CallStaticLongMethodV,
3981         _Jv_JNI_CallStaticLongMethodA,
3982         _Jv_JNI_CallStaticFloatMethod,
3983         _Jv_JNI_CallStaticFloatMethodV,
3984         _Jv_JNI_CallStaticFloatMethodA,
3985         _Jv_JNI_CallStaticDoubleMethod,
3986         _Jv_JNI_CallStaticDoubleMethodV,
3987         _Jv_JNI_CallStaticDoubleMethodA,
3988         _Jv_JNI_CallStaticVoidMethod,
3989         _Jv_JNI_CallStaticVoidMethodV,
3990         _Jv_JNI_CallStaticVoidMethodA,
3991
3992         _Jv_JNI_GetStaticFieldID,
3993
3994         _Jv_JNI_GetStaticObjectField,
3995         _Jv_JNI_GetStaticBooleanField,
3996         _Jv_JNI_GetStaticByteField,
3997         _Jv_JNI_GetStaticCharField,
3998         _Jv_JNI_GetStaticShortField,
3999         _Jv_JNI_GetStaticIntField,
4000         _Jv_JNI_GetStaticLongField,
4001         _Jv_JNI_GetStaticFloatField,
4002         _Jv_JNI_GetStaticDoubleField,
4003         _Jv_JNI_SetStaticObjectField,
4004         _Jv_JNI_SetStaticBooleanField,
4005         _Jv_JNI_SetStaticByteField,
4006         _Jv_JNI_SetStaticCharField,
4007         _Jv_JNI_SetStaticShortField,
4008         _Jv_JNI_SetStaticIntField,
4009         _Jv_JNI_SetStaticLongField,
4010         _Jv_JNI_SetStaticFloatField,
4011         _Jv_JNI_SetStaticDoubleField,
4012
4013         jni_NewString,
4014         jni_GetStringLength,
4015         jni_GetStringChars,
4016         _Jv_JNI_ReleaseStringChars,
4017
4018         jni_NewStringUTF,
4019         jni_GetStringUTFLength,
4020         _Jv_JNI_GetStringUTFChars,
4021         _Jv_JNI_ReleaseStringUTFChars,
4022
4023         _Jv_JNI_GetArrayLength,
4024
4025         _Jv_JNI_NewObjectArray,
4026         _Jv_JNI_GetObjectArrayElement,
4027         _Jv_JNI_SetObjectArrayElement,
4028
4029         _Jv_JNI_NewBooleanArray,
4030         _Jv_JNI_NewByteArray,
4031         _Jv_JNI_NewCharArray,
4032         _Jv_JNI_NewShortArray,
4033         _Jv_JNI_NewIntArray,
4034         _Jv_JNI_NewLongArray,
4035         _Jv_JNI_NewFloatArray,
4036         _Jv_JNI_NewDoubleArray,
4037
4038         _Jv_JNI_GetBooleanArrayElements,
4039         _Jv_JNI_GetByteArrayElements,
4040         _Jv_JNI_GetCharArrayElements,
4041         _Jv_JNI_GetShortArrayElements,
4042         _Jv_JNI_GetIntArrayElements,
4043         _Jv_JNI_GetLongArrayElements,
4044         _Jv_JNI_GetFloatArrayElements,
4045         _Jv_JNI_GetDoubleArrayElements,
4046
4047         _Jv_JNI_ReleaseBooleanArrayElements,
4048         _Jv_JNI_ReleaseByteArrayElements,
4049         _Jv_JNI_ReleaseCharArrayElements,
4050         _Jv_JNI_ReleaseShortArrayElements,
4051         _Jv_JNI_ReleaseIntArrayElements,
4052         _Jv_JNI_ReleaseLongArrayElements,
4053         _Jv_JNI_ReleaseFloatArrayElements,
4054         _Jv_JNI_ReleaseDoubleArrayElements,
4055
4056         _Jv_JNI_GetBooleanArrayRegion,
4057         _Jv_JNI_GetByteArrayRegion,
4058         _Jv_JNI_GetCharArrayRegion,
4059         _Jv_JNI_GetShortArrayRegion,
4060         _Jv_JNI_GetIntArrayRegion,
4061         _Jv_JNI_GetLongArrayRegion,
4062         _Jv_JNI_GetFloatArrayRegion,
4063         _Jv_JNI_GetDoubleArrayRegion,
4064         _Jv_JNI_SetBooleanArrayRegion,
4065         _Jv_JNI_SetByteArrayRegion,
4066         _Jv_JNI_SetCharArrayRegion,
4067         _Jv_JNI_SetShortArrayRegion,
4068         _Jv_JNI_SetIntArrayRegion,
4069         _Jv_JNI_SetLongArrayRegion,
4070         _Jv_JNI_SetFloatArrayRegion,
4071         _Jv_JNI_SetDoubleArrayRegion,
4072
4073         jni_RegisterNatives,
4074         _Jv_JNI_UnregisterNatives,
4075
4076         _Jv_JNI_MonitorEnter,
4077         _Jv_JNI_MonitorExit,
4078
4079         _Jv_JNI_GetJavaVM,
4080
4081         /* New JNI 1.2 functions. */
4082
4083         jni_GetStringRegion,
4084         jni_GetStringUTFRegion,
4085
4086         jni_GetPrimitiveArrayCritical,
4087         jni_ReleasePrimitiveArrayCritical,
4088
4089         _Jv_JNI_GetStringCritical,
4090         _Jv_JNI_ReleaseStringCritical,
4091
4092         _Jv_JNI_NewWeakGlobalRef,
4093         _Jv_JNI_DeleteWeakGlobalRef,
4094
4095         _Jv_JNI_ExceptionCheck,
4096
4097         /* New JNI 1.4 functions. */
4098
4099         jni_NewDirectByteBuffer,
4100         jni_GetDirectBufferAddress,
4101         jni_GetDirectBufferCapacity,
4102
4103         /* New JNI 1.6 functions. */
4104
4105         jni_GetObjectRefType
4106 };
4107
4108
4109 /* Invocation API Functions ***************************************************/
4110
4111 /* JNI_GetDefaultJavaVMInitArgs ************************************************
4112
4113    Returns a default configuration for the Java VM.
4114
4115 *******************************************************************************/
4116
4117 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
4118 {
4119         JavaVMInitArgs *_vm_args;
4120
4121         _vm_args = (JavaVMInitArgs *) vm_args;
4122
4123         /* GNU classpath currently supports JNI 1.2 */
4124
4125         switch (_vm_args->version) {
4126         case JNI_VERSION_1_1:
4127                 _vm_args->version = JNI_VERSION_1_1;
4128                 break;
4129
4130         case JNI_VERSION_1_2:
4131         case JNI_VERSION_1_4:
4132                 _vm_args->ignoreUnrecognized = JNI_FALSE;
4133                 _vm_args->options = NULL;
4134                 _vm_args->nOptions = 0;
4135                 break;
4136
4137         case JNI_VERSION_CACAO:
4138                 // We reveal ourselves by accepting this version number,
4139                 // this actually means we are using the supported JNI version.
4140                 _vm_args->version = JNI_VERSION_SUPPORTED;
4141                 break;
4142
4143         default:
4144                 return JNI_ERR;
4145         }
4146
4147         return JNI_OK;
4148 }
4149
4150
4151 /* JNI_GetCreatedJavaVMs *******************************************************
4152
4153    Returns all Java VMs that have been created. Pointers to VMs are written in
4154    the buffer vmBuf in the order they are created. At most bufLen number of
4155    entries will be written. The total number of created VMs is returned in
4156    *nVMs.
4157
4158 *******************************************************************************/
4159
4160 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
4161 {
4162         TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
4163
4164         if (bufLen <= 0)
4165                 return JNI_ERR;
4166
4167         // We currently only support 1 VM running.
4168
4169         vmBuf[0] = VM::get_current()->get_javavm();
4170         *nVMs    = 1;
4171
4172     return JNI_OK;
4173 }
4174
4175
4176 /* JNI_CreateJavaVM ************************************************************
4177
4178    Loads and initializes a Java VM. The current thread becomes the main thread.
4179    Sets the env argument to the JNI interface pointer of the main thread.
4180
4181 *******************************************************************************/
4182
4183 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
4184 {
4185         TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
4186
4187         /* actually create the JVM */
4188
4189         if (!VM_create(p_vm, p_env, vm_args))
4190                 return JNI_ERR;
4191
4192         return JNI_OK;
4193 }
4194
4195 } // extern "C"
4196
4197
4198 /*
4199  * These are local overrides for various environment variables in Emacs.
4200  * Please do not remove this and leave it at the end of the file, where
4201  * Emacs will automagically detect them.
4202  * ---------------------------------------------------------------------
4203  * Local variables:
4204  * mode: c++
4205  * indent-tabs-mode: t
4206  * c-basic-offset: 4
4207  * tab-width: 4
4208  * End:
4209  * vim:noexpandtab:sw=4:ts=4:
4210  */