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