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