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