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