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