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