9a06ab245edff229ea2488bc75953414b521401d
[cacao.git] / src / native / jni.cpp
1 /* src/native/jni.cpp - implementation of the Java Native Interface functions
2
3    Copyright (C) 1996-2011
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         if ((o == NULL) || (LLNI_vftbl_direct(o) == NULL))
1429                 return NULL;
1430
1431         LLNI_class_get(o, c);
1432
1433         java_handle_t* h = LLNI_classinfo_wrap(c);
1434
1435         return (jclass) jni_NewLocalRef(env, (jobject) h);
1436 }
1437
1438
1439 /* IsInstanceOf ****************************************************************
1440
1441    Tests whether an object is an instance of a class.
1442
1443 *******************************************************************************/
1444
1445 jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
1446 {
1447         classinfo     *c;
1448         java_handle_t *h;
1449
1450         TRACEJNICALLS(("_Jv_JNI_IsInstanceOf(env=%p, obj=%p, clazz=%p)", env, obj, clazz));
1451
1452         /* XXX Is this correct? */
1453         c = LLNI_classinfo_unwrap(clazz);
1454         h = (java_handle_t *) obj;
1455
1456         return class_is_instance(c, h);
1457 }
1458
1459
1460 /* Reflection Support *********************************************************/
1461
1462 /* FromReflectedMethod *********************************************************
1463
1464    Converts java.lang.reflect.Method or java.lang.reflect.Constructor
1465    object to a method ID.
1466   
1467 *******************************************************************************/
1468   
1469 jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
1470 {
1471 #if defined(ENABLE_JAVASE)
1472         methodinfo*    m;
1473
1474         TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
1475
1476         java_lang_Object o(method);
1477
1478         if (o.is_null())
1479                 return NULL;
1480
1481         if (o.get_Class() == class_java_lang_reflect_Constructor) {
1482                 java_lang_reflect_Constructor rc(method);
1483                 m = rc.get_method();
1484         }
1485         else {
1486                 assert(o.get_Class() == class_java_lang_reflect_Method);
1487
1488                 java_lang_reflect_Method rm(method);
1489                 m = rm.get_method();
1490         }
1491
1492         return (jmethodID) m;
1493 #else
1494         vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
1495
1496         // Keep compiler happy.
1497         return NULL;
1498 #endif
1499 }
1500
1501
1502 /* FromReflectedField **********************************************************
1503
1504    Converts a java.lang.reflect.Field to a field ID.
1505
1506 *******************************************************************************/
1507  
1508 jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
1509 {
1510 #if defined(ENABLE_JAVASE)
1511
1512         TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
1513
1514         java_lang_reflect_Field rf(field);
1515
1516         if (rf.is_null())
1517                 return NULL;
1518
1519         fieldinfo* f = rf.get_field();
1520
1521         return (jfieldID) f;
1522 #else
1523         vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
1524
1525         // Keep compiler happy.
1526         return NULL;
1527 #endif
1528 }
1529
1530
1531 /* ToReflectedMethod ***********************************************************
1532
1533    Converts a method ID derived from cls to an instance of the
1534    java.lang.reflect.Method class or to an instance of the
1535    java.lang.reflect.Constructor class.
1536
1537 *******************************************************************************/
1538
1539 jobject jni_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
1540 {
1541 #if defined(ENABLE_JAVASE)
1542         TRACEJNICALLS(("jni_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
1543
1544         methodinfo* m = (methodinfo *) methodID;
1545
1546         /* HotSpot does the same assert. */
1547
1548         assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
1549
1550         java_handle_t* h;
1551
1552         if (m->name == utf_init) {
1553                 h = java_lang_reflect_Constructor(m).get_handle();
1554         }
1555         else {
1556                 h = java_lang_reflect_Method(m).get_handle();
1557         }
1558
1559         return (jobject) h;
1560 #else
1561         vm_abort("jni_ToReflectedMethod: Not implemented in this configuration.");
1562
1563         /* keep compiler happy */
1564
1565         return NULL;
1566 #endif
1567 }
1568
1569
1570 /* ToReflectedField ************************************************************
1571
1572    Converts a field ID derived from cls to an instance of the
1573    java.lang.reflect.Field class.
1574
1575 *******************************************************************************/
1576
1577 jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1578                                                                  jboolean isStatic)
1579 {
1580         STATISTICS(jniinvokation());
1581
1582         log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
1583
1584         return NULL;
1585 }
1586
1587
1588 /* Calling Instance Methods ***************************************************/
1589
1590 /* GetMethodID *****************************************************************
1591
1592    Returns the method ID for an instance (nonstatic) method of a class
1593    or interface. The method may be defined in one of the clazz's
1594    superclasses and inherited by clazz. The method is determined by
1595    its name and signature.
1596
1597    GetMethodID() causes an uninitialized class to be initialized.
1598
1599 *******************************************************************************/
1600
1601 jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
1602                                                           const char *sig)
1603 {
1604         classinfo  *c;
1605         utf        *uname;
1606         utf        *udesc;
1607         methodinfo *m;
1608
1609         STATISTICS(jniinvokation());
1610
1611         c = LLNI_classinfo_unwrap(clazz);
1612
1613         if (c == NULL)
1614                 return NULL;
1615
1616         if (!(c->state & CLASS_INITIALIZED))
1617                 if (!initialize_class(c))
1618                         return NULL;
1619
1620         /* try to get the method of the class or one of it's superclasses */
1621
1622         uname = utf_new_char((char *) name);
1623         udesc = utf_new_char((char *) sig);
1624
1625         m = class_resolvemethod(c, uname, udesc);
1626
1627         if ((m == NULL) || (m->flags & ACC_STATIC)) {
1628                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
1629
1630                 return NULL;
1631         }
1632
1633         return (jmethodID) m;
1634 }
1635
1636
1637 /* JNI-functions for calling instance methods *********************************/
1638
1639 #define JNI_CALL_VIRTUAL_METHOD(name, type, intern)         \
1640 type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj,   \
1641                                                                 jmethodID methodID, ...)    \
1642 {                                                           \
1643         java_handle_t *o;                                       \
1644         methodinfo    *m;                                       \
1645         va_list        ap;                                      \
1646         type           ret;                                     \
1647                                                             \
1648         o = (java_handle_t *) obj;                              \
1649         m = (methodinfo *) methodID;                            \
1650                                                             \
1651         va_start(ap, methodID);                                 \
1652         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, ap); \
1653         va_end(ap);                                             \
1654                                                             \
1655         return ret;                                             \
1656 }
1657
1658 JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
1659 JNI_CALL_VIRTUAL_METHOD(Byte,    jbyte,    Int)
1660 JNI_CALL_VIRTUAL_METHOD(Char,    jchar,    Int)
1661 JNI_CALL_VIRTUAL_METHOD(Short,   jshort,   Int)
1662 JNI_CALL_VIRTUAL_METHOD(Int,     jint,     Int)
1663 JNI_CALL_VIRTUAL_METHOD(Long,    jlong,    Long)
1664 JNI_CALL_VIRTUAL_METHOD(Float,   jfloat,   Float)
1665 JNI_CALL_VIRTUAL_METHOD(Double,  jdouble,  Double)
1666
1667
1668 #define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern)              \
1669 type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj,         \
1670                                                                  jmethodID methodID, va_list args) \
1671 {                                                                  \
1672         java_handle_t *o;                                              \
1673         methodinfo    *m;                                              \
1674         type           ret;                                            \
1675                                                                    \
1676         o = (java_handle_t *) obj;                                     \
1677         m = (methodinfo *) methodID;                                   \
1678                                                                    \
1679         ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, args);      \
1680                                                                    \
1681         return ret;                                                    \
1682 }
1683
1684 JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
1685 JNI_CALL_VIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1686 JNI_CALL_VIRTUAL_METHOD_V(Char,    jchar,    Int)
1687 JNI_CALL_VIRTUAL_METHOD_V(Short,   jshort,   Int)
1688 JNI_CALL_VIRTUAL_METHOD_V(Int,     jint,     Int)
1689 JNI_CALL_VIRTUAL_METHOD_V(Long,    jlong,    Long)
1690 JNI_CALL_VIRTUAL_METHOD_V(Float,   jfloat,   Float)
1691 JNI_CALL_VIRTUAL_METHOD_V(Double,  jdouble,  Double)
1692
1693
1694 #define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern)          \
1695 type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj,     \
1696                                                                  jmethodID methodID,           \
1697                                                                  const jvalue *args)           \
1698 {                                                              \
1699         java_handle_t *o;                                          \
1700         methodinfo    *m;                                          \
1701         type           ret;                                        \
1702                                                                \
1703         o = (java_handle_t *) obj;                                 \
1704         m = (methodinfo *) methodID;                               \
1705                                                                \
1706         ret = _Jv_jni_Call##intern##MethodA(o, LLNI_vftbl_direct(o), m, args); \
1707                                                                \
1708         return ret;                                                \
1709 }
1710
1711 JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
1712 JNI_CALL_VIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1713 JNI_CALL_VIRTUAL_METHOD_A(Char,    jchar,    Int)
1714 JNI_CALL_VIRTUAL_METHOD_A(Short,   jshort,   Int)
1715 JNI_CALL_VIRTUAL_METHOD_A(Int,     jint,     Int)
1716 JNI_CALL_VIRTUAL_METHOD_A(Long,    jlong,    Long)
1717 JNI_CALL_VIRTUAL_METHOD_A(Float,   jfloat,   Float)
1718 JNI_CALL_VIRTUAL_METHOD_A(Double,  jdouble,  Double)
1719
1720
1721 jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
1722                                                                  ...)
1723 {
1724         java_handle_t *o;
1725         methodinfo    *m;
1726         java_handle_t *ret;
1727         va_list        ap;
1728
1729         o = (java_handle_t *) obj;
1730         m = (methodinfo *) methodID;
1731
1732         va_start(ap, methodID);
1733         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, ap);
1734         va_end(ap);
1735
1736         return jni_NewLocalRef(env, (jobject) ret);
1737 }
1738
1739
1740 jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1741                                                                   va_list args)
1742 {
1743         java_handle_t *o;
1744         methodinfo    *m;
1745         java_handle_t *ret;
1746
1747         o = (java_handle_t *) obj;
1748         m = (methodinfo *) methodID;
1749
1750         ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, args);
1751
1752         return jni_NewLocalRef(env, (jobject) ret);
1753 }
1754
1755
1756 jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1757                                                                   const jvalue *args)
1758 {
1759         java_handle_t *o;
1760         methodinfo    *m;
1761         java_handle_t *ret;
1762
1763         o = (java_handle_t *) obj;
1764         m = (methodinfo *) methodID;
1765
1766         ret = _Jv_jni_CallObjectMethodA(o, LLNI_vftbl_direct(o), m, args);
1767
1768         return jni_NewLocalRef(env, (jobject) ret);
1769 }
1770
1771
1772
1773 void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
1774 {
1775         java_handle_t *o;
1776         methodinfo    *m;
1777         va_list        ap;
1778
1779         o = (java_handle_t *) obj;
1780         m = (methodinfo *) methodID;
1781
1782         va_start(ap, methodID);
1783         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
1784         va_end(ap);
1785 }
1786
1787
1788 void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
1789                                                          va_list args)
1790 {
1791         java_handle_t *o;
1792         methodinfo    *m;
1793
1794         o = (java_handle_t *) obj;
1795         m = (methodinfo *) methodID;
1796
1797         _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
1798 }
1799
1800
1801 void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
1802                                                          const jvalue *args)
1803 {
1804         java_handle_t *o;
1805         methodinfo    *m;
1806
1807         o = (java_handle_t *) obj;
1808         m = (methodinfo *) methodID;
1809
1810         _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
1811 }
1812
1813
1814
1815 #define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern)                      \
1816 type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj,         \
1817                                                                                   jclass clazz, jmethodID methodID, \
1818                                                                                   ...)                              \
1819 {                                                                           \
1820         java_handle_t *o;                                                       \
1821         classinfo     *c;                                                       \
1822         methodinfo    *m;                                                       \
1823         va_list        ap;                                                      \
1824         type           ret;                                                     \
1825                                                                             \
1826         o = (java_handle_t *) obj;                                              \
1827         c = LLNI_classinfo_unwrap(clazz);                                       \
1828         m = (methodinfo *) methodID;                                            \
1829                                                                             \
1830         va_start(ap, methodID);                                                 \
1831         ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap);                 \
1832         va_end(ap);                                                             \
1833                                                                             \
1834         return ret;                                                             \
1835 }
1836
1837 JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
1838 JNI_CALL_NONVIRTUAL_METHOD(Byte,    jbyte,    Int)
1839 JNI_CALL_NONVIRTUAL_METHOD(Char,    jchar,    Int)
1840 JNI_CALL_NONVIRTUAL_METHOD(Short,   jshort,   Int)
1841 JNI_CALL_NONVIRTUAL_METHOD(Int,     jint,     Int)
1842 JNI_CALL_NONVIRTUAL_METHOD(Long,    jlong,    Long)
1843 JNI_CALL_NONVIRTUAL_METHOD(Float,   jfloat,   Float)
1844 JNI_CALL_NONVIRTUAL_METHOD(Double,  jdouble,  Double)
1845
1846
1847 #define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern)                     \
1848 type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj,         \
1849                                                                                    jclass clazz, jmethodID methodID, \
1850                                                                                    va_list args)                     \
1851 {                                                                            \
1852         java_handle_t *o;                                                        \
1853         classinfo     *c;                                                        \
1854         methodinfo    *m;                                                        \
1855         type           ret;                                                      \
1856                                                                              \
1857         o = (java_handle_t *) obj;                                               \
1858         c = LLNI_classinfo_unwrap(clazz);                                        \
1859         m = (methodinfo *) methodID;                                             \
1860                                                                              \
1861         ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args);                       \
1862                                                                              \
1863         return ret;                                                              \
1864 }
1865
1866 JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
1867 JNI_CALL_NONVIRTUAL_METHOD_V(Byte,    jbyte,    Int)
1868 JNI_CALL_NONVIRTUAL_METHOD_V(Char,    jchar,    Int)
1869 JNI_CALL_NONVIRTUAL_METHOD_V(Short,   jshort,   Int)
1870 JNI_CALL_NONVIRTUAL_METHOD_V(Int,     jint,     Int)
1871 JNI_CALL_NONVIRTUAL_METHOD_V(Long,    jlong,    Long)
1872 JNI_CALL_NONVIRTUAL_METHOD_V(Float,   jfloat,   Float)
1873 JNI_CALL_NONVIRTUAL_METHOD_V(Double,  jdouble,  Double)
1874
1875
1876 #define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern)                     \
1877 type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj,         \
1878                                                                                    jclass clazz, jmethodID methodID, \
1879                                                                                    const jvalue *args)               \
1880 {                                                                            \
1881         log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!");      \
1882                                                                              \
1883         return 0;                                                                \
1884 }
1885
1886 JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
1887 JNI_CALL_NONVIRTUAL_METHOD_A(Byte,    jbyte,    Int)
1888 JNI_CALL_NONVIRTUAL_METHOD_A(Char,    jchar,    Int)
1889 JNI_CALL_NONVIRTUAL_METHOD_A(Short,   jshort,   Int)
1890 JNI_CALL_NONVIRTUAL_METHOD_A(Int,     jint,     Int)
1891 JNI_CALL_NONVIRTUAL_METHOD_A(Long,    jlong,    Long)
1892 JNI_CALL_NONVIRTUAL_METHOD_A(Float,   jfloat,   Float)
1893 JNI_CALL_NONVIRTUAL_METHOD_A(Double,  jdouble,  Double)
1894
1895 jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
1896                                                                                    jclass clazz, jmethodID methodID,
1897                                                                                    ...)
1898 {
1899         java_handle_t *o;
1900         classinfo     *c;
1901         methodinfo    *m;
1902         java_handle_t *r;
1903         va_list        ap;
1904
1905         o = (java_handle_t *) obj;
1906         c = LLNI_classinfo_unwrap(clazz);
1907         m = (methodinfo *) methodID;
1908
1909         va_start(ap, methodID);
1910         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
1911         va_end(ap);
1912
1913         return jni_NewLocalRef(env, (jobject) r);
1914 }
1915
1916
1917 jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
1918                                                                                         jclass clazz, jmethodID methodID,
1919                                                                                         va_list args)
1920 {
1921         java_handle_t *o;
1922         classinfo     *c;
1923         methodinfo    *m;
1924         java_handle_t *r;
1925
1926         o = (java_handle_t *) obj;
1927         c = LLNI_classinfo_unwrap(clazz);
1928         m = (methodinfo *) methodID;
1929
1930         r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
1931
1932         return jni_NewLocalRef(env, (jobject) r);
1933 }
1934
1935
1936 jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
1937                                                                                         jclass clazz, jmethodID methodID,
1938                                                                                         const jvalue *args)
1939 {
1940         log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
1941
1942         return jni_NewLocalRef(env, NULL);
1943 }
1944
1945
1946 void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
1947                                                                           jmethodID methodID, ...)
1948 {
1949         java_handle_t *o;
1950         classinfo     *c;
1951         methodinfo    *m;
1952         va_list        ap;
1953
1954         o = (java_handle_t *) obj;
1955         c = LLNI_classinfo_unwrap(clazz);
1956         m = (methodinfo *) methodID;
1957
1958         va_start(ap, methodID);
1959         _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
1960         va_end(ap);
1961 }
1962
1963
1964 void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
1965                                                                            jmethodID methodID, va_list args)
1966 {
1967         java_handle_t *o;
1968         classinfo     *c;
1969         methodinfo    *m;
1970
1971         o = (java_handle_t *) obj;
1972         c = LLNI_classinfo_unwrap(clazz);
1973         m = (methodinfo *) methodID;
1974
1975         _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
1976 }
1977
1978
1979 void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
1980                                                                            jmethodID methodID, const jvalue * args)
1981 {       
1982         java_handle_t *o;
1983         classinfo     *c;
1984         methodinfo    *m;
1985
1986         o = (java_handle_t *) obj;
1987         c = LLNI_classinfo_unwrap(clazz);
1988         m = (methodinfo *) methodID;
1989
1990         _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
1991 }
1992
1993
1994 /* Accessing Fields of Objects ************************************************/
1995
1996 /* GetFieldID ******************************************************************
1997
1998    Returns the field ID for an instance (nonstatic) field of a
1999    class. The field is specified by its name and signature. The
2000    Get<type>Field and Set<type>Field families of accessor functions
2001    use field IDs to retrieve object fields.
2002
2003 *******************************************************************************/
2004
2005 jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
2006                                                         const char *sig)
2007 {
2008         classinfo *c;
2009         fieldinfo *f;
2010         utf       *uname;
2011         utf       *udesc;
2012
2013         STATISTICS(jniinvokation());
2014
2015         c = LLNI_classinfo_unwrap(clazz);
2016
2017         /* XXX NPE check? */
2018
2019         uname = utf_new_char((char *) name);
2020         udesc = utf_new_char((char *) sig);
2021
2022         f = class_findfield(c, uname, udesc); 
2023         
2024         if (f == NULL)
2025                 exceptions_throw_nosuchfielderror(c, uname);  
2026
2027         return (jfieldID) f;
2028 }
2029
2030
2031 /* Get<type>Field Routines *****************************************************
2032
2033    This family of accessor routines returns the value of an instance
2034    (nonstatic) field of an object. The field to access is specified by
2035    a field ID obtained by calling GetFieldID().
2036
2037 *******************************************************************************/
2038
2039 #define GET_FIELD(o,type,f) \
2040     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
2041
2042 #define JNI_GET_FIELD(name, type, intern)                                 \
2043 type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
2044 {                                                                         \
2045         intern ret;                                                           \
2046                                                                           \
2047         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
2048                                                                           \
2049         LLNI_CRITICAL_START;                                                  \
2050                                                                           \
2051         ret = GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID); \
2052                                                                           \
2053         LLNI_CRITICAL_END;                                                    \
2054                                                                           \
2055         return (type) ret;                                                    \
2056 }
2057
2058 JNI_GET_FIELD(Boolean, jboolean, s4)
2059 JNI_GET_FIELD(Byte,    jbyte,    s4)
2060 JNI_GET_FIELD(Char,    jchar,    s4)
2061 JNI_GET_FIELD(Short,   jshort,   s4)
2062 JNI_GET_FIELD(Int,     jint,     s4)
2063 JNI_GET_FIELD(Long,    jlong,    s8)
2064 JNI_GET_FIELD(Float,   jfloat,   float)
2065 JNI_GET_FIELD(Double,  jdouble,  double)
2066
2067
2068 jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
2069 {
2070         java_handle_t *o;
2071
2072         TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
2073
2074         LLNI_CRITICAL_START;
2075
2076         o = LLNI_WRAP(GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), java_object_t*, fieldID));
2077
2078         LLNI_CRITICAL_END;
2079
2080         return jni_NewLocalRef(env, (jobject) o);
2081 }
2082
2083
2084 /* Set<type>Field Routines *****************************************************
2085
2086    This family of accessor routines sets the value of an instance
2087    (nonstatic) field of an object. The field to access is specified by
2088    a field ID obtained by calling GetFieldID().
2089
2090 *******************************************************************************/
2091
2092 #define SET_FIELD(o,type,f,value) \
2093     *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
2094
2095 #define GET_FIELDINFO(f) ((fieldinfo*) (f))
2096
2097 #define JNI_SET_FIELD(name, type, intern)                                  \
2098 void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID,  \
2099                                                           type value)                                  \
2100 {                                                                          \
2101         TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
2102                                                                            \
2103         LLNI_CRITICAL_START;                                                   \
2104                                                                            \
2105         SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
2106                                                                                \
2107         LLNI_CRITICAL_END;                                                     \
2108                                                                                                                                                    \
2109         if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)                      \
2110                 Atomic::memory_barrier();                                          \
2111 }
2112
2113 JNI_SET_FIELD(Boolean, jboolean, s4)
2114 JNI_SET_FIELD(Byte,    jbyte,    s4)
2115 JNI_SET_FIELD(Char,    jchar,    s4)
2116 JNI_SET_FIELD(Short,   jshort,   s4)
2117 JNI_SET_FIELD(Int,     jint,     s4)
2118 JNI_SET_FIELD(Long,    jlong,    s8)
2119 JNI_SET_FIELD(Float,   jfloat,   float)
2120 JNI_SET_FIELD(Double,  jdouble,  double)
2121
2122
2123 void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
2124                                                         jobject value)
2125 {
2126         TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
2127
2128         LLNI_CRITICAL_START;
2129
2130         SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
2131
2132         LLNI_CRITICAL_END;
2133
2134         if (GET_FIELDINFO(fieldID)->flags & ACC_VOLATILE)
2135                 Atomic::memory_barrier();
2136 }
2137
2138
2139 /* Calling Static Methods *****************************************************/
2140
2141 /* GetStaticMethodID ***********************************************************
2142
2143    Returns the method ID for a static method of a class. The method is
2144    specified by its name and signature.
2145
2146    GetStaticMethodID() causes an uninitialized class to be
2147    initialized.
2148
2149 *******************************************************************************/
2150
2151 jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
2152                                                                         const char *sig)
2153 {
2154         classinfo  *c;
2155         utf        *uname;
2156         utf        *udesc;
2157         methodinfo *m;
2158
2159         TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
2160
2161         c = LLNI_classinfo_unwrap(clazz);
2162
2163         if (c == NULL)
2164                 return NULL;
2165
2166         if (!(c->state & CLASS_INITIALIZED))
2167                 if (!initialize_class(c))
2168                         return NULL;
2169
2170         /* try to get the static method of the class */
2171
2172         uname = utf_new_char((char *) name);
2173         udesc = utf_new_char((char *) sig);
2174
2175         m = class_resolvemethod(c, uname, udesc);
2176
2177         if ((m == NULL) || !(m->flags & ACC_STATIC)) {
2178                 exceptions_throw_nosuchmethoderror(c, uname, udesc);
2179
2180                 return NULL;
2181         }
2182
2183         return (jmethodID) m;
2184 }
2185
2186
2187 #define JNI_CALL_STATIC_METHOD(name, type, intern)               \
2188 type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
2189                                                                           jmethodID methodID, ...)   \
2190 {                                                                \
2191         methodinfo *m;                                               \
2192         va_list     ap;                                              \
2193         type        res;                                             \
2194                                                                  \
2195         m = (methodinfo *) methodID;                                 \
2196                                                                  \
2197         va_start(ap, methodID);                                      \
2198         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap);       \
2199         va_end(ap);                                                  \
2200                                                                  \
2201         return res;                                                  \
2202 }
2203
2204 JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
2205 JNI_CALL_STATIC_METHOD(Byte,    jbyte,    Int)
2206 JNI_CALL_STATIC_METHOD(Char,    jchar,    Int)
2207 JNI_CALL_STATIC_METHOD(Short,   jshort,   Int)
2208 JNI_CALL_STATIC_METHOD(Int,     jint,     Int)
2209 JNI_CALL_STATIC_METHOD(Long,    jlong,    Long)
2210 JNI_CALL_STATIC_METHOD(Float,   jfloat,   Float)
2211 JNI_CALL_STATIC_METHOD(Double,  jdouble,  Double)
2212
2213
2214 #define JNI_CALL_STATIC_METHOD_V(name, type, intern)                     \
2215 type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz,        \
2216                                                                            jmethodID methodID, va_list args) \
2217 {                                                                        \
2218         methodinfo *m;                                                       \
2219         type        res;                                                     \
2220                                                                          \
2221         m = (methodinfo *) methodID;                                         \
2222                                                                          \
2223         res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args);             \
2224                                                                          \
2225         return res;                                                          \
2226 }
2227
2228 JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
2229 JNI_CALL_STATIC_METHOD_V(Byte,    jbyte,    Int)
2230 JNI_CALL_STATIC_METHOD_V(Char,    jchar,    Int)
2231 JNI_CALL_STATIC_METHOD_V(Short,   jshort,   Int)
2232 JNI_CALL_STATIC_METHOD_V(Int,     jint,     Int)
2233 JNI_CALL_STATIC_METHOD_V(Long,    jlong,    Long)
2234 JNI_CALL_STATIC_METHOD_V(Float,   jfloat,   Float)
2235 JNI_CALL_STATIC_METHOD_V(Double,  jdouble,  Double)
2236
2237
2238 #define JNI_CALL_STATIC_METHOD_A(name, type, intern)                           \
2239 type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz,              \
2240                                                                            jmethodID methodID, const jvalue *args) \
2241 {                                                                              \
2242         methodinfo *m;                                                             \
2243         type        res;                                                           \
2244                                                                                \
2245         m = (methodinfo *) methodID;                                               \
2246                                                                                \
2247         res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args);                  \
2248                                                                                \
2249         return res;                                                                \
2250 }
2251
2252 JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
2253 JNI_CALL_STATIC_METHOD_A(Byte,    jbyte,    Int)
2254 JNI_CALL_STATIC_METHOD_A(Char,    jchar,    Int)
2255 JNI_CALL_STATIC_METHOD_A(Short,   jshort,   Int)
2256 JNI_CALL_STATIC_METHOD_A(Int,     jint,     Int)
2257 JNI_CALL_STATIC_METHOD_A(Long,    jlong,    Long)
2258 JNI_CALL_STATIC_METHOD_A(Float,   jfloat,   Float)
2259 JNI_CALL_STATIC_METHOD_A(Double,  jdouble,  Double)
2260
2261
2262 jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
2263                                                                            jmethodID methodID, ...)
2264 {
2265         methodinfo    *m;
2266         java_handle_t *o;
2267         va_list        ap;
2268
2269         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2270
2271         m = (methodinfo *) methodID;
2272
2273         va_start(ap, methodID);
2274         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
2275         va_end(ap);
2276
2277         return jni_NewLocalRef(env, (jobject) o);
2278 }
2279
2280
2281 jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
2282                                                                                 jmethodID methodID, va_list args)
2283 {
2284         methodinfo    *m;
2285         java_handle_t *o;
2286
2287         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p)", env, clazz, methodID));
2288
2289         m = (methodinfo *) methodID;
2290
2291         o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
2292
2293         return jni_NewLocalRef(env, (jobject) o);
2294 }
2295
2296
2297 jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
2298                                                                                 jmethodID methodID, const jvalue *args)
2299 {
2300         methodinfo    *m;
2301         java_handle_t *o;
2302
2303         TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2304
2305         m = (methodinfo *) methodID;
2306
2307         o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
2308
2309         return jni_NewLocalRef(env, (jobject) o);
2310 }
2311
2312
2313 void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
2314                                                                   jmethodID methodID, ...)
2315 {
2316         methodinfo *m;
2317         va_list     ap;
2318
2319         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
2320
2321         m = (methodinfo *) methodID;
2322
2323         va_start(ap, methodID);
2324         _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
2325         va_end(ap);
2326 }
2327
2328
2329 void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
2330                                                                    jmethodID methodID, va_list args)
2331 {
2332         methodinfo *m;
2333
2334         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p)", env, clazz, methodID));
2335
2336         m = (methodinfo *) methodID;
2337
2338         _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
2339 }
2340
2341
2342 void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
2343                                                                    jmethodID methodID, const jvalue * args)
2344 {
2345         methodinfo *m;
2346
2347         TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
2348
2349         m = (methodinfo *) methodID;
2350
2351         _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
2352 }
2353
2354
2355 /* Accessing Static Fields ****************************************************/
2356
2357 /* GetStaticFieldID ************************************************************
2358
2359    Returns the field ID for a static field of a class. The field is
2360    specified by its name and signature. The GetStatic<type>Field and
2361    SetStatic<type>Field families of accessor functions use field IDs
2362    to retrieve static fields.
2363
2364 *******************************************************************************/
2365
2366 jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
2367                                                                   const char *sig)
2368 {
2369         classinfo *c;
2370         fieldinfo *f;
2371         utf       *uname;
2372         utf       *usig;
2373
2374         STATISTICS(jniinvokation());
2375
2376         c = LLNI_classinfo_unwrap(clazz);
2377
2378         uname = utf_new_char((char *) name);
2379         usig  = utf_new_char((char *) sig);
2380
2381         f = class_findfield(c, uname, usig);
2382         
2383         if (f == NULL)
2384                 exceptions_throw_nosuchfielderror(c, uname);
2385
2386         return (jfieldID) f;
2387 }
2388
2389
2390 /* GetStatic<type>Field ********************************************************
2391
2392    This family of accessor routines returns the value of a static
2393    field of an object.
2394
2395 *******************************************************************************/
2396
2397 #define JNI_GET_STATIC_FIELD(name, type, field)                \
2398 type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
2399                                                                         jfieldID fieldID)          \
2400 {                                                              \
2401         classinfo *c;                                              \
2402         fieldinfo *f;                                              \
2403                                                                \
2404         STATISTICS(jniinvokation());                               \
2405                                                                \
2406         c = LLNI_classinfo_unwrap(clazz);                          \
2407         f = (fieldinfo *) fieldID;                                 \
2408                                                                \
2409         if (!(c->state & CLASS_INITIALIZED))                       \
2410                 if (!initialize_class(c))                              \
2411                         return 0;                                          \
2412                                                                \
2413         return f->value->field;                                    \
2414 }
2415
2416 JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
2417 JNI_GET_STATIC_FIELD(Byte,    jbyte,    i)
2418 JNI_GET_STATIC_FIELD(Char,    jchar,    i)
2419 JNI_GET_STATIC_FIELD(Short,   jshort,   i)
2420 JNI_GET_STATIC_FIELD(Int,     jint,     i)
2421 JNI_GET_STATIC_FIELD(Long,    jlong,    l)
2422 JNI_GET_STATIC_FIELD(Float,   jfloat,   f)
2423 JNI_GET_STATIC_FIELD(Double,  jdouble,  d)
2424
2425
2426 jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
2427                                                                          jfieldID fieldID)
2428 {
2429         classinfo     *c;
2430         fieldinfo     *f;
2431         java_handle_t *h;
2432
2433         STATISTICS(jniinvokation());
2434
2435         c = LLNI_classinfo_unwrap(clazz);
2436         f = (fieldinfo *) fieldID;
2437
2438         if (!(c->state & CLASS_INITIALIZED))
2439                 if (!initialize_class(c))
2440                         return NULL;
2441
2442         h = (java_handle_t*) LLNI_WRAP(f->value->a);
2443
2444         return jni_NewLocalRef(env, (jobject) h);
2445 }
2446
2447
2448 /*  SetStatic<type>Field *******************************************************
2449
2450         This family of accessor routines sets the value of a static field
2451         of an object.
2452
2453 *******************************************************************************/
2454
2455 #define JNI_SET_STATIC_FIELD(name, type, field)                \
2456 void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
2457                                                                         jfieldID fieldID,          \
2458                                                                         type value)                \
2459 {                                                              \
2460         classinfo *c;                                              \
2461         fieldinfo *f;                                              \
2462                                                                \
2463         STATISTICS(jniinvokation());                               \
2464                                                                \
2465         c = LLNI_classinfo_unwrap(clazz);                          \
2466         f = (fieldinfo *) fieldID;                                 \
2467                                                                \
2468         if (!(c->state & CLASS_INITIALIZED))                       \
2469                 if (!initialize_class(c))                              \
2470                         return;                                            \
2471                                                                \
2472         f->value->field = value;                                   \
2473                                                                                                                            \
2474         if (f->flags & ACC_VOLATILE)                               \
2475                 Atomic::memory_barrier();                              \
2476 }
2477
2478 JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
2479 JNI_SET_STATIC_FIELD(Byte,    jbyte,    i)
2480 JNI_SET_STATIC_FIELD(Char,    jchar,    i)
2481 JNI_SET_STATIC_FIELD(Short,   jshort,   i)
2482 JNI_SET_STATIC_FIELD(Int,     jint,     i)
2483 JNI_SET_STATIC_FIELD(Long,    jlong,    l)
2484 JNI_SET_STATIC_FIELD(Float,   jfloat,   f)
2485 JNI_SET_STATIC_FIELD(Double,  jdouble,  d)
2486
2487
2488 void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
2489                                                                   jobject value)
2490 {
2491         classinfo *c;
2492         fieldinfo *f;
2493
2494         STATISTICS(jniinvokation());
2495
2496         c = LLNI_classinfo_unwrap(clazz);
2497         f = (fieldinfo *) fieldID;
2498
2499         if (!(c->state & CLASS_INITIALIZED))
2500                 if (!initialize_class(c))
2501                         return;
2502
2503         f->value->a = LLNI_UNWRAP((java_handle_t *) value);
2504
2505         if (f->flags & ACC_VOLATILE)
2506                 Atomic::memory_barrier();
2507 }
2508
2509
2510 /* String Operations **********************************************************/
2511
2512 /* NewString *******************************************************************
2513
2514    Create new java.lang.String object from an array of Unicode
2515    characters.
2516
2517 *******************************************************************************/
2518
2519 jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len)
2520 {
2521         TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len));
2522
2523         CharArray ca(len);
2524
2525         if (ca.is_null())
2526                 return NULL;
2527
2528         /* copy text */
2529
2530         // XXX: Fix me!
2531         uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
2532         for (jsize i = 0; i < len; i++)
2533                 ptr[i] = buf[i];
2534
2535         java_handle_t* h = builtin_new(class_java_lang_String);
2536
2537         if (h == NULL)
2538                 return NULL;
2539
2540         java_lang_String s(h, ca.get_handle(), len, 0);
2541
2542         return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle());
2543 }
2544
2545
2546 static jchar emptyStringJ[]={0,0};
2547
2548 /* GetStringLength *************************************************************
2549
2550    Returns the length (the count of Unicode characters) of a Java
2551    string.
2552
2553 *******************************************************************************/
2554
2555 jsize jni_GetStringLength(JNIEnv *env, jstring str)
2556 {
2557         TRACEJNICALLSENTER(("jni_GetStringLength(env=%p, str=%p)", env, str));
2558
2559         java_lang_String s(str);
2560         jsize count = s.get_count();
2561
2562         TRACEJNICALLSEXIT(("->%d)", count));
2563
2564         return count;
2565 }
2566
2567
2568 /* GetStringChars **************************************************************
2569
2570    Returns a pointer to the array of Unicode characters of the
2571    string. This pointer is valid until ReleaseStringChars() is called.
2572
2573 *******************************************************************************/
2574
2575 const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
2576 {       
2577         u2      *stringbuffer;
2578         int32_t  i;
2579
2580         TRACEJNICALLS(("jni_GetStringChars(env=%p, str=%p, isCopy=%p)", env, str, isCopy));
2581
2582         if (str == NULL)
2583                 // FIXME This is really ugly.
2584                 return emptyStringJ;
2585
2586         java_lang_String s(str);
2587
2588         CharArray ca(s.get_value());
2589
2590         int32_t count  = s.get_count();
2591         int32_t offset = s.get_offset();
2592         
2593         if (ca.is_null())
2594                 return NULL;
2595
2596         /* allocate memory */
2597
2598         stringbuffer = MNEW(u2, count + 1);
2599
2600         /* copy text */
2601
2602         // XXX: Fix me!
2603         uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
2604         for (i = 0; i < count; i++)
2605                 stringbuffer[i] = ptr[offset + i];
2606         
2607         /* terminate string */
2608
2609         stringbuffer[i] = '\0';
2610
2611         if (isCopy)
2612                 *isCopy = JNI_TRUE;
2613
2614         return (jchar*) stringbuffer;
2615 }
2616
2617
2618 /* ReleaseStringChars **********************************************************
2619
2620    Informs the VM that the native code no longer needs access to
2621    chars. The chars argument is a pointer obtained from string using
2622    GetStringChars().
2623
2624 *******************************************************************************/
2625
2626 void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
2627 {
2628         TRACEJNICALLS(("jni_ReleaseStringChars(env=%p, str=%p, chars=%p)", env, str, chars));
2629
2630         // FIXME
2631         if (chars == emptyStringJ)
2632                 return;
2633
2634         java_lang_String s(str);
2635         int32_t count = s.get_count();
2636
2637         MFREE(((jchar*) chars), jchar, count + 1);
2638 }
2639
2640
2641 /* NewStringUTF ****************************************************************
2642
2643    Constructs a new java.lang.String object from an array of UTF-8
2644    characters.
2645
2646 *******************************************************************************/
2647
2648 jstring jni_NewStringUTF(JNIEnv *env, const char *bytes)
2649 {
2650         TRACEJNICALLS(("jni_NewStringUTF(env=%p, bytes=%s)", env, bytes));
2651
2652         java_handle_t *h = javastring_safe_new_from_utf8(bytes);
2653
2654     return (jstring) jni_NewLocalRef(env, (jobject) h);
2655 }
2656
2657
2658 /****************** returns the utf8 length in bytes of a string *******************/
2659
2660 jsize jni_GetStringUTFLength(JNIEnv *env, jstring string)
2661 {   
2662         TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string));
2663
2664         java_lang_String s(string);
2665         CharArray        ca(s.get_value());
2666         int32_t          count = s.get_count();
2667
2668         // FIXME GC critical section!
2669         uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
2670         int32_t length = u2_utflength(ptr, count);
2671
2672         return length;
2673 }
2674
2675
2676 /* GetStringUTFChars ***********************************************************
2677
2678    Returns a pointer to an array of UTF-8 characters of the
2679    string. This array is valid until it is released by
2680    ReleaseStringUTFChars().
2681
2682 *******************************************************************************/
2683
2684 const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
2685                                                                           jboolean *isCopy)
2686 {
2687         utf *u;
2688
2689         STATISTICS(jniinvokation());
2690
2691         if (string == NULL)
2692                 return "";
2693
2694         if (isCopy)
2695                 *isCopy = JNI_TRUE;
2696         
2697         u = javastring_toutf((java_handle_t *) string, false);
2698
2699         if (u != NULL)
2700                 return u->text;
2701
2702         return "";
2703 }
2704
2705
2706 /* ReleaseStringUTFChars *******************************************************
2707
2708    Informs the VM that the native code no longer needs access to
2709    utf. The utf argument is a pointer derived from string using
2710    GetStringUTFChars().
2711
2712 *******************************************************************************/
2713
2714 void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
2715 {
2716         STATISTICS(jniinvokation());
2717
2718     /* XXX we don't release utf chars right now, perhaps that should be done 
2719            later. Since there is always one reference the garbage collector will
2720            never get them */
2721 }
2722
2723
2724 /* Array Operations ***********************************************************/
2725
2726 /* GetArrayLength **************************************************************
2727
2728    Returns the number of elements in the array.
2729
2730 *******************************************************************************/
2731
2732 jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
2733 {
2734         TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
2735
2736         Array a(array);
2737
2738         jsize size = a.get_length();
2739
2740         return size;
2741 }
2742
2743
2744 /* NewObjectArray **************************************************************
2745
2746    Constructs a new array holding objects in class elementClass. All
2747    elements are initially set to initialElement.
2748
2749 *******************************************************************************/
2750
2751 jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
2752                                                                         jclass elementClass, jobject initialElement)
2753 {
2754         classinfo*     c;
2755         java_handle_t* o;
2756         s4             i;
2757
2758         STATISTICS(jniinvokation());
2759
2760         c = LLNI_classinfo_unwrap(elementClass);
2761         o = (java_handle_t *) initialElement;
2762
2763         if (length < 0) {
2764                 exceptions_throw_negativearraysizeexception();
2765                 return NULL;
2766         }
2767
2768         ObjectArray oa(length, c);
2769
2770         if (oa.is_null())
2771                 return NULL;
2772
2773         /* set all elements to initialElement */
2774
2775         for (i = 0; i < length; i++)
2776                 oa.set_element(i, o);
2777
2778         return (jobjectArray) jni_NewLocalRef(env, (jobject) oa.get_handle());
2779 }
2780
2781
2782 jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
2783                                                                           jsize index)
2784 {
2785         STATISTICS(jniinvokation());
2786
2787         ObjectArray oa(array);
2788
2789         if (index >= oa.get_length()) {
2790                 exceptions_throw_arrayindexoutofboundsexception();
2791                 return NULL;
2792         }
2793
2794         java_handle_t* o = oa.get_element(index);
2795
2796         return jni_NewLocalRef(env, (jobject) o);
2797 }
2798
2799
2800 void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
2801                                                                    jsize index, jobject val)
2802 {
2803         STATISTICS(jniinvokation());
2804
2805         ObjectArray oa(array);
2806
2807         if (index >= oa.get_length()) {
2808                 exceptions_throw_arrayindexoutofboundsexception();
2809                 return;
2810         }
2811
2812         /* check if the class of value is a subclass of the element class
2813            of the array */
2814
2815         java_handle_t* o  = (java_handle_t *) val;
2816
2817         if (!builtin_canstore(oa.get_handle(), o))
2818                 return;
2819
2820         oa.set_element(index, o);
2821 }
2822
2823
2824 #define JNI_NEW_ARRAY(name, type)                        \
2825 type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len)    \
2826 {                                                        \
2827         STATISTICS(jniinvokation());                         \
2828                                                          \
2829         if (len < 0) {                                       \
2830                 exceptions_throw_negativearraysizeexception();   \
2831                 return NULL;                                     \
2832         }                                                    \
2833                                                          \
2834         name##Array a(len);                                  \
2835                                                          \
2836         return (type) jni_NewLocalRef(env,                   \
2837                         (jobject) a.get_handle());                   \
2838 }
2839
2840 JNI_NEW_ARRAY(Boolean, jbooleanArray)
2841 JNI_NEW_ARRAY(Byte,    jbyteArray)
2842 JNI_NEW_ARRAY(Char,    jcharArray)
2843 JNI_NEW_ARRAY(Short,   jshortArray)
2844 JNI_NEW_ARRAY(Int,     jintArray)
2845 JNI_NEW_ARRAY(Long,    jlongArray)
2846 JNI_NEW_ARRAY(Float,   jfloatArray)
2847 JNI_NEW_ARRAY(Double,  jdoubleArray)
2848
2849
2850 /* Get<PrimitiveType>ArrayElements *********************************************
2851
2852    A family of functions that returns the body of the primitive array.
2853
2854 *******************************************************************************/
2855
2856 #define JNI_GET_ARRAY_ELEMENTS(name, type, intern)                     \
2857 type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
2858                                                                                  jboolean *isCopy)             \
2859 {                                                                      \
2860         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
2861                                                                        \
2862         name##Array a(array);                                              \
2863                                                                        \
2864         if (isCopy)                                                        \
2865                 *isCopy = JNI_FALSE;                                           \
2866                                                                        \
2867         return (type *) a.get_raw_data_ptr();                              \
2868 }
2869
2870 JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
2871 JNI_GET_ARRAY_ELEMENTS(Byte,    jbyte,    byte)
2872 JNI_GET_ARRAY_ELEMENTS(Char,    jchar,    char)
2873 JNI_GET_ARRAY_ELEMENTS(Short,   jshort,   short)
2874 JNI_GET_ARRAY_ELEMENTS(Int,     jint,     int)
2875 JNI_GET_ARRAY_ELEMENTS(Long,    jlong,    long)
2876 JNI_GET_ARRAY_ELEMENTS(Float,   jfloat,   float)
2877 JNI_GET_ARRAY_ELEMENTS(Double,  jdouble,  double)
2878
2879
2880 /* Release<PrimitiveType>ArrayElements *****************************************
2881
2882    A family of functions that informs the VM that the native code no
2883    longer needs access to elems. The elems argument is a pointer
2884    derived from array using the corresponding
2885    Get<PrimitiveType>ArrayElements() function. If necessary, this
2886    function copies back all changes made to elems to the original
2887    array.
2888
2889 *******************************************************************************/
2890
2891 #define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2)            \
2892 void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
2893                                                                                   type *elems, jint mode)          \
2894 {                                                                          \
2895         STATISTICS(jniinvokation());                                           \
2896                                                                            \
2897         name##Array a(array);                                                  \
2898                                                                            \
2899         if (elems != (type *) a.get_raw_data_ptr()) {                          \
2900                 switch (mode) {                                                    \
2901                 case JNI_COMMIT:                                                   \
2902                         a.set_region(0, a.get_length(), (intern2 *) elems);            \
2903                         break;                                                         \
2904                 case 0:                                                            \
2905                         a.set_region(0, a.get_length(), (intern2 *) elems);            \
2906                         /* XXX TWISTI how should it be freed? */                       \
2907                         break;                                                         \
2908                 case JNI_ABORT:                                                    \
2909                         /* XXX TWISTI how should it be freed? */                       \
2910                         break;                                                         \
2911                 }                                                                  \
2912         }                                                                      \
2913 }
2914
2915 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
2916 JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
2917 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
2918 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
2919 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
2920 JNI_RELEASE_ARRAY_ELEMENTS(Long,    jlong,    long,    s8)
2921 JNI_RELEASE_ARRAY_ELEMENTS(Float,   jfloat,   float,   float)
2922 JNI_RELEASE_ARRAY_ELEMENTS(Double,  jdouble,  double,  double)
2923
2924
2925 /*  Get<PrimitiveType>ArrayRegion **********************************************
2926
2927         A family of functions that copies a region of a primitive array
2928         into a buffer.
2929
2930 *******************************************************************************/
2931
2932 #define JNI_GET_ARRAY_REGION(name, type, intern, intern2)               \
2933 void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
2934                                                                         jsize start, jsize len, type *buf)  \
2935 {                                                                       \
2936         TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
2937                                                                         \
2938         name##Array a(array);                                               \
2939                                                                         \
2940         if ((start < 0) || (len < 0) || (start + len > a.get_length()))     \
2941                 exceptions_throw_arrayindexoutofboundsexception();              \
2942         else                                                                \
2943                 a.get_region(start, len, (intern2 *) buf);                      \
2944 }
2945
2946 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2947 JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2948 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
2949 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
2950 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
2951 JNI_GET_ARRAY_REGION(Long,    jlong,    long,    s8)
2952 JNI_GET_ARRAY_REGION(Float,   jfloat,   float,   float)
2953 JNI_GET_ARRAY_REGION(Double,  jdouble,  double,  double)
2954
2955
2956 /*  Set<PrimitiveType>ArrayRegion **********************************************
2957
2958         A family of functions that copies back a region of a primitive
2959         array from a buffer.
2960
2961 *******************************************************************************/
2962
2963 #define JNI_SET_ARRAY_REGION(name, type, intern, intern2)                    \
2964 void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
2965                                                                         jsize start, jsize len, const type *buf) \
2966 {                                                                            \
2967         STATISTICS(jniinvokation());                                             \
2968                                                                              \
2969         name##Array a(array);                                                    \
2970                                                                              \
2971         if ((start < 0) || (len < 0) || (start + len > a.get_length()))          \
2972                 exceptions_throw_arrayindexoutofboundsexception();                   \
2973         else                                                                     \
2974                 a.set_region(start, len, (intern2 *) buf);                           \
2975 }
2976
2977 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
2978 JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
2979 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
2980 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
2981 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
2982 JNI_SET_ARRAY_REGION(Long,    jlong,    long,    s8)
2983 JNI_SET_ARRAY_REGION(Float,   jfloat,   float,   float)
2984 JNI_SET_ARRAY_REGION(Double,  jdouble,  double,  double)
2985
2986
2987 /* Registering Native Methods *************************************************/
2988
2989 /* RegisterNatives *************************************************************
2990
2991    Registers native methods with the class specified by the clazz
2992    argument. The methods parameter specifies an array of
2993    JNINativeMethod structures that contain the names, signatures, and
2994    function pointers of the native methods. The nMethods parameter
2995    specifies the number of native methods in the array.
2996
2997 *******************************************************************************/
2998
2999 jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods)
3000 {
3001         TRACEJNICALLS(("jni_RegisterNatives(env=%p, clazz=%p, methods=%p, nMethods=%d)", env, clazz, methods, nMethods));
3002
3003         classinfo* c = LLNI_classinfo_unwrap(clazz);
3004
3005         NativeMethods& nm = VM::get_current()->get_nativemethods();
3006         nm.register_methods(c->name, methods, nMethods);
3007
3008         return 0;
3009 }
3010
3011
3012 /* UnregisterNatives ***********************************************************
3013
3014    Unregisters native methods of a class. The class goes back to the
3015    state before it was linked or registered with its native method
3016    functions.
3017
3018    This function should not be used in normal native code. Instead, it
3019    provides special programs a way to reload and relink native
3020    libraries.
3021
3022 *******************************************************************************/
3023
3024 jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
3025 {
3026         STATISTICS(jniinvokation());
3027
3028         /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
3029
3030     log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
3031
3032     return 0;
3033 }
3034
3035
3036 /* Monitor Operations *********************************************************/
3037
3038 /* MonitorEnter ****************************************************************
3039
3040    Enters the monitor associated with the underlying Java object
3041    referred to by obj.
3042
3043 *******************************************************************************/
3044
3045 jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
3046 {
3047         STATISTICS(jniinvokation());
3048
3049         if (obj == NULL) {
3050                 exceptions_throw_nullpointerexception();
3051                 return JNI_ERR;
3052         }
3053
3054         LOCK_MONITOR_ENTER(obj);
3055
3056         return JNI_OK;
3057 }
3058
3059
3060 /* MonitorExit *****************************************************************
3061
3062    The current thread must be the owner of the monitor associated with
3063    the underlying Java object referred to by obj. The thread
3064    decrements the counter indicating the number of times it has
3065    entered this monitor. If the value of the counter becomes zero, the
3066    current thread releases the monitor.
3067
3068 *******************************************************************************/
3069
3070 jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
3071 {
3072         STATISTICS(jniinvokation());
3073
3074         if (obj == NULL) {
3075                 exceptions_throw_nullpointerexception();
3076                 return JNI_ERR;
3077         }
3078
3079         LOCK_MONITOR_EXIT(obj);
3080
3081         return JNI_OK;
3082 }
3083
3084
3085 /* JavaVM Interface ***********************************************************/
3086
3087 /* GetJavaVM *******************************************************************
3088
3089    Returns the Java VM interface (used in the Invocation API)
3090    associated with the current thread. The result is placed at the
3091    location pointed to by the second argument, vm.
3092
3093 *******************************************************************************/
3094
3095 jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
3096 {
3097         STATISTICS(jniinvokation());
3098
3099     *javavm = VM::get_current()->get_javavm();
3100
3101         return 0;
3102 }
3103
3104
3105 /* GetStringRegion *************************************************************
3106
3107    Copies len number of Unicode characters beginning at offset start
3108    to the given buffer buf.
3109
3110    Throws StringIndexOutOfBoundsException on index overflow.
3111
3112 *******************************************************************************/
3113
3114 void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
3115 {
3116         java_lang_String s(str);
3117         CharArray        ca(s.get_value());
3118         int32_t          count = s.get_count();
3119
3120         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3121                 exceptions_throw_stringindexoutofboundsexception();
3122                 return;
3123         }
3124
3125         ca.get_region(start, len, buf);
3126 }
3127
3128
3129 /* GetStringUTFRegion **********************************************************
3130
3131     Translates len number of Unicode characters beginning at offset
3132     start into UTF-8 format and place the result in the given buffer
3133     buf.
3134
3135     Throws StringIndexOutOfBoundsException on index overflow. 
3136
3137 *******************************************************************************/
3138
3139 void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
3140 {
3141         TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
3142
3143         java_lang_String s(str);
3144
3145         CharArray ca(s.get_value());
3146
3147         int32_t count  = s.get_count();
3148         int32_t offset = s.get_offset();
3149
3150         if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
3151                 exceptions_throw_stringindexoutofboundsexception();
3152                 return;
3153         }
3154
3155         int32_t i;
3156
3157         // XXX: Fix me!
3158         uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr();
3159         for (i = 0; i < len; i++)
3160                 buf[i] = ptr[offset + start + i];
3161
3162         buf[i] = '\0';
3163 }
3164
3165
3166 /* GetPrimitiveArrayCritical ***************************************************
3167
3168    Obtain a direct pointer to array elements.
3169
3170    ATTENTION: Critical section keeps open when this function returns!
3171    See ReleasePrimitiveArrayCritical.
3172
3173 *******************************************************************************/
3174
3175 void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
3176 {
3177         java_handle_t*   h;
3178         java_array_t*    a;
3179         arraydescriptor* ad;
3180         void*            data;
3181
3182         TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
3183
3184         if (isCopy != NULL) {
3185                 *isCopy = JNI_FALSE;
3186         }
3187
3188         LLNI_CRITICAL_START;
3189
3190         h  = (java_handle_t*) array;
3191         a  = (java_array_t*) LLNI_UNWRAP(h);
3192         ad = a->objheader.vftbl->arraydesc;
3193
3194         /* Sanity check. */
3195
3196         assert(ad != NULL);
3197
3198         data = (void*) (((intptr_t) a) + ad->dataoffset);
3199
3200         return data;
3201 }
3202
3203
3204 /* ReleasePrimitiveArrayCritical ***********************************************
3205
3206    No specific documentation.
3207
3208    ATTENTION: This function closes the critical section opened in
3209    GetPrimitiveArrayCritical!
3210
3211 *******************************************************************************/
3212
3213 void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
3214 {
3215         TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
3216
3217         LLNI_CRITICAL_END;
3218 }
3219
3220
3221 /* GetStringCritical ***********************************************************
3222
3223    The semantics of these two functions are similar to the existing
3224    Get/ReleaseStringChars functions.
3225
3226 *******************************************************************************/
3227
3228 const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
3229                                                                            jboolean *isCopy)
3230 {
3231         STATISTICS(jniinvokation());
3232
3233         return jni_GetStringChars(env, string, isCopy);
3234 }
3235
3236
3237 void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
3238                                                                    const jchar *cstring)
3239 {
3240         STATISTICS(jniinvokation());
3241
3242         _Jv_JNI_ReleaseStringChars(env, string, cstring);
3243 }
3244
3245
3246 jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
3247 {
3248         TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
3249
3250         return (jweak) obj;
3251 }
3252
3253
3254 void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
3255 {
3256         TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
3257 }
3258
3259
3260 /* NewGlobalRef ****************************************************************
3261
3262    Creates a new global reference to the object referred to by the obj
3263    argument.
3264
3265 *******************************************************************************/
3266
3267 jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
3268 {
3269         hashtable_global_ref_entry *gre;
3270         u4   key;                           /* hashkey                            */
3271         u4   slot;                          /* slot in hashtable                  */
3272         java_handle_t *o;
3273
3274         TRACEJNICALLS(("jni_NewGlobalRef(env=%p, obj=%p)", env, obj));
3275
3276         o = (java_handle_t *) obj;
3277
3278         hashtable_global_ref->mutex->lock();
3279
3280         LLNI_CRITICAL_START;
3281
3282         /* normally addresses are aligned to 4, 8 or 16 bytes */
3283
3284         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3285         slot = key & (hashtable_global_ref->size - 1);
3286         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3287         
3288         /* search external hash chain for the entry */
3289
3290         while (gre) {
3291                 if (gre->o == LLNI_DIRECT(o)) {
3292                         /* global object found, increment the reference */
3293
3294                         gre->refs++;
3295
3296                         break;
3297                 }
3298
3299                 gre = gre->hashlink;                /* next element in external chain */
3300         }
3301
3302         LLNI_CRITICAL_END;
3303
3304         /* global ref not found, create a new one */
3305
3306         if (gre == NULL) {
3307                 gre = (hashtable_global_ref_entry*) heap_alloc_uncollectable(sizeof(hashtable_global_ref_entry));
3308
3309 #if defined(ENABLE_GC_CACAO)
3310                 /* register global ref with the GC */
3311
3312                 gc_reference_register(&(gre->o), GC_REFTYPE_JNI_GLOBALREF);
3313 #endif
3314
3315                 LLNI_CRITICAL_START;
3316
3317                 gre->o    = LLNI_DIRECT(o);
3318                 gre->refs = 1;
3319
3320                 LLNI_CRITICAL_END;
3321
3322                 /* insert entry into hashtable */
3323
3324                 gre->hashlink = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3325
3326                 hashtable_global_ref->ptr[slot] = gre;
3327
3328                 /* update number of hashtable-entries */
3329
3330                 hashtable_global_ref->entries++;
3331         }
3332
3333         hashtable_global_ref->mutex->unlock();
3334
3335 #if defined(ENABLE_HANDLES)
3336         return gre;
3337 #else
3338         return obj;
3339 #endif
3340 }
3341
3342
3343 /* DeleteGlobalRef *************************************************************
3344
3345    Deletes the global reference pointed to by globalRef.
3346
3347 *******************************************************************************/
3348
3349 void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
3350 {
3351         hashtable_global_ref_entry *gre;
3352         hashtable_global_ref_entry *prevgre;
3353         u4   key;                           /* hashkey                            */
3354         u4   slot;                          /* slot in hashtable                  */
3355         java_handle_t              *o;
3356
3357         TRACEJNICALLS(("jni_DeleteGlobalRef(env=%p, globalRef=%p)", env, globalRef));
3358
3359         o = (java_handle_t *) globalRef;
3360
3361         hashtable_global_ref->mutex->lock();
3362
3363         LLNI_CRITICAL_START;
3364
3365         /* normally addresses are aligned to 4, 8 or 16 bytes */
3366
3367         key  = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
3368         slot = key & (hashtable_global_ref->size - 1);
3369         gre  = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
3370
3371         /* initialize prevgre */
3372
3373         prevgre = NULL;
3374
3375         /* search external hash chain for the entry */
3376
3377         while (gre) {
3378                 if (gre->o == LLNI_DIRECT(o)) {
3379                         /* global object found, decrement the reference count */
3380
3381                         gre->refs--;
3382
3383                         /* if reference count is 0, remove the entry */
3384
3385                         if (gre->refs == 0) {
3386                                 /* special handling if it's the first in the chain */
3387
3388                                 if (prevgre == NULL)
3389                                         hashtable_global_ref->ptr[slot] = gre->hashlink;
3390                                 else
3391                                         prevgre->hashlink = gre->hashlink;
3392
3393 #if defined(ENABLE_GC_CACAO)
3394                                 /* unregister global ref with the GC */
3395
3396                                 gc_reference_unregister(&(gre->o));
3397 #endif
3398
3399                                 heap_free(gre);
3400                         }
3401
3402                         LLNI_CRITICAL_END;
3403
3404                         hashtable_global_ref->mutex->unlock();
3405
3406                         return;
3407                 }
3408
3409                 prevgre = gre;                    /* save current pointer for removal */
3410                 gre     = gre->hashlink;            /* next element in external chain */
3411         }
3412
3413         log_println("jni_DeleteGlobalRef: Global reference not found.");
3414
3415         LLNI_CRITICAL_END;
3416
3417         hashtable_global_ref->mutex->unlock();
3418 }
3419
3420
3421 /* ExceptionCheck **************************************************************
3422
3423    Returns JNI_TRUE when there is a pending exception; otherwise,
3424    returns JNI_FALSE.
3425
3426 *******************************************************************************/
3427
3428 jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
3429 {
3430         java_handle_t *o;
3431
3432         STATISTICS(jniinvokation());
3433
3434         o = exceptions_get_exception();
3435
3436         return (o != NULL) ? JNI_TRUE : JNI_FALSE;
3437 }
3438
3439
3440 /* New JNI 1.4 functions ******************************************************/
3441
3442 /* NewDirectByteBuffer *********************************************************
3443
3444    Allocates and returns a direct java.nio.ByteBuffer referring to the
3445    block of memory starting at the memory address address and
3446    extending capacity bytes.
3447
3448 *******************************************************************************/
3449
3450 jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
3451 {
3452 #if defined(ENABLE_JAVASE)
3453 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3454         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3455
3456         // Allocate a gnu.classpath.Pointer{32,64} object.
3457
3458 # if SIZEOF_VOID_P == 8
3459         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer64);
3460 # else
3461         java_handle_t* h = builtin_new(class_gnu_classpath_Pointer32);
3462 # endif
3463
3464         if (h == NULL)
3465                 return NULL;
3466
3467         gnu_classpath_Pointer p(h, address);
3468
3469         // Create a java.nio.DirectByteBufferImpl$ReadWrite object.
3470
3471         java_handle_t* nbuf =
3472                 (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
3473                                                                            (jmethodID) dbbirw_init, NULL, p.get_handle(),
3474                                                                            (jint) capacity, (jint) capacity, (jint) 0);
3475
3476         // Add a local reference and return the value.
3477
3478         TRACEJNICALLSEXIT(("->%p", nbuf));
3479
3480         return jni_NewLocalRef(env, (jobject) nbuf);
3481
3482 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3483
3484         jobject o;
3485         int64_t addr;
3486         int32_t cap;
3487
3488         TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
3489
3490         /* Be paranoid about address sign-extension. */
3491
3492         addr = (int64_t) ((uintptr_t) address);
3493         cap  = (int32_t) capacity;
3494
3495         o = jni_NewObject(env, (jclass) class_java_nio_DirectByteBuffer,
3496                                           (jmethodID) dbb_init, addr, cap);
3497
3498         /* Add local reference and return the value. */
3499
3500         TRACEJNICALLSEXIT(("->%p", o));
3501
3502         return jni_NewLocalRef(env, o);
3503
3504 # else
3505 #  error unknown classpath configuration
3506 # endif
3507
3508 #else
3509         vm_abort("jni_NewDirectByteBuffer: Not implemented in this configuration.");
3510
3511         /* keep compiler happy */
3512
3513         return NULL;
3514 #endif
3515 }
3516
3517
3518 /* GetDirectBufferAddress ******************************************************
3519
3520    Fetches and returns the starting address of the memory region
3521    referenced by the given direct java.nio.Buffer.
3522
3523 *******************************************************************************/
3524
3525 void* jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3526 {
3527 #if defined(ENABLE_JAVASE)
3528 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3529
3530         TRACEJNICALLSENTER(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3531
3532         /* Prevent compiler warning. */
3533
3534         java_handle_t* h = (java_handle_t *) buf;
3535
3536         if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
3537                 return NULL;
3538
3539         java_nio_DirectByteBufferImpl dbb(buf);
3540         java_handle_t* address = dbb.get_address();
3541
3542         if (address == NULL) {
3543                 TRACEJNICALLSEXIT(("->%p", NULL));
3544                 return NULL;
3545         }
3546
3547         gnu_classpath_Pointer p(address);
3548         void* data = p.get_data();
3549
3550         TRACEJNICALLSEXIT(("->%p", data));
3551
3552         return data;
3553
3554 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3555
3556         TRACEJNICALLS(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
3557
3558         java_nio_Buffer jnb(buf);
3559
3560         if (jnb.is_non_null() && !builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
3561                 return NULL;
3562
3563         void* address = jnb.get_address();
3564
3565         return address;
3566
3567 # else
3568 #  error unknown classpath configuration
3569 # endif
3570
3571 #else
3572
3573         vm_abort("jni_GetDirectBufferAddress: Not implemented in this configuration.");
3574
3575         // Keep compiler happy.
3576         return NULL;
3577
3578 #endif
3579 }
3580
3581
3582 /* GetDirectBufferCapacity *****************************************************
3583
3584    Fetches and returns the capacity in bytes of the memory region
3585    referenced by the given direct java.nio.Buffer.
3586
3587 *******************************************************************************/
3588
3589 jlong jni_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
3590 {
3591 #if defined(ENABLE_JAVASE)
3592 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
3593         TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
3594
3595         java_handle_t* h = (java_handle_t *) buf;
3596
3597         if (!builtin_instanceof(h, class_java_nio_DirectByteBufferImpl))
3598                 return -1;
3599
3600         java_nio_Buffer b(h);
3601         jlong capacity = b.get_cap();
3602
3603         return capacity;
3604 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
3605
3606         TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
3607
3608         java_nio_Buffer jnb(buf);
3609
3610         if (!builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
3611                 return -1;
3612
3613         jlong capacity = jnb.get_capacity();
3614
3615         return capacity;
3616
3617 # else
3618 #  error unknown classpath configuration
3619 # endif
3620
3621 #else
3622         vm_abort("jni_GetDirectBufferCapacity: not implemented in this configuration");
3623
3624         // Keep compiler happy.
3625
3626         return 0;
3627 #endif
3628 }
3629
3630
3631 /* GetObjectRefType ************************************************************
3632
3633    Returns the type of the object referred to by the obj argument. The
3634    argument obj can either be a local, global or weak global
3635    reference.
3636
3637 *******************************************************************************/
3638
3639 jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj)
3640 {
3641         log_println("jni_GetObjectRefType: IMPLEMENT ME!");
3642
3643         return (jobjectRefType) NULL;
3644 }
3645
3646
3647 /* DestroyJavaVM ***************************************************************
3648
3649    Unloads a Java VM and reclaims its resources. Only the main thread
3650    can unload the VM. The system waits until the main thread is only
3651    remaining user thread before it destroys the VM.
3652
3653 *******************************************************************************/
3654
3655 jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
3656 {
3657         int status;
3658
3659         TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
3660
3661         if (VM::get_current()->is_created() == false)
3662                 return JNI_ERR;
3663
3664     status = vm_destroy(javavm);
3665
3666         return status;
3667 }
3668
3669
3670 /* AttachCurrentThread *********************************************************
3671
3672    Attaches the current thread to a Java VM. Returns a JNI interface
3673    pointer in the JNIEnv argument.
3674
3675    Trying to attach a thread that is already attached is a no-op.
3676
3677    A native thread cannot be attached simultaneously to two Java VMs.
3678
3679    When a thread is attached to the VM, the context class loader is
3680    the bootstrap loader.
3681
3682 *******************************************************************************/
3683
3684 static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
3685 {
3686 #if defined(ENABLE_THREADS)
3687         JavaVMAttachArgs *vm_aargs;
3688         bool              result;
3689
3690     /* If the current thread has already been attached, this operation
3691            is a no-op. */
3692
3693         result = thread_current_is_attached();
3694
3695         if (result == true) {
3696                 *p_env = VM::get_current()->get_jnienv();
3697                 return JNI_OK;
3698         }
3699
3700         vm_aargs = (JavaVMAttachArgs *) thr_args;
3701
3702         if (vm_aargs != NULL) {
3703                 if ((vm_aargs->version != JNI_VERSION_1_2) &&
3704                         (vm_aargs->version != JNI_VERSION_1_4))
3705                         return JNI_EVERSION;
3706         }
3707
3708         if (!thread_attach_current_external_thread(vm_aargs, false))
3709                 return JNI_ERR;
3710
3711         if (!localref_table_init())
3712                 return JNI_ERR;
3713 #endif
3714
3715         *p_env = VM::get_current()->get_jnienv();
3716
3717         return JNI_OK;
3718 }
3719
3720
3721 jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
3722 {
3723         int result;
3724
3725         TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
3726
3727         if (VM::get_current()->is_created() == false)
3728                 return JNI_ERR;
3729
3730         result = jni_attach_current_thread(p_env, thr_args, false);
3731
3732         return result;
3733 }
3734
3735
3736 /* DetachCurrentThread *********************************************************
3737
3738    Detaches the current thread from a Java VM. All Java monitors held
3739    by this thread are released. All Java threads waiting for this
3740    thread to die are notified.
3741
3742    In JDK 1.1, the main thread cannot be detached from the VM. It must
3743    call DestroyJavaVM to unload the entire VM.
3744
3745    In the JDK, the main thread can be detached from the VM.
3746
3747    The main thread, which is the thread that created the Java VM,
3748    cannot be detached from the VM. Instead, the main thread must call
3749    JNI_DestroyJavaVM() to unload the entire VM.
3750
3751 *******************************************************************************/
3752
3753 jint jni_DetachCurrentThread(JavaVM *vm)
3754 {
3755 #if defined(ENABLE_THREADS)
3756         bool result;
3757
3758         TRACEJNICALLS(("jni_DetachCurrentThread(vm=%p)", vm));
3759
3760     /* If the current thread has already been detached, this operation
3761            is a no-op. */
3762
3763         result = thread_current_is_attached();
3764
3765         if (result == false)
3766                 return true;
3767
3768         /* We need to pop all frames before we can destroy the table. */
3769
3770         localref_frame_pop_all();
3771
3772         if (!localref_table_destroy())
3773                 return JNI_ERR;
3774
3775         if (!thread_detach_current_external_thread())
3776                 return JNI_ERR;
3777 #endif
3778
3779         return JNI_OK;
3780 }
3781
3782
3783 /* GetEnv **********************************************************************
3784
3785    If the current thread is not attached to the VM, sets *env to NULL,
3786    and returns JNI_EDETACHED. If the specified version is not
3787    supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
3788    sets *env to the appropriate interface, and returns JNI_OK.
3789
3790 *******************************************************************************/
3791
3792 jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
3793 {
3794         TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
3795
3796         if (VM::get_current()->is_created() == false) {
3797                 *env = NULL;
3798                 return JNI_EDETACHED;
3799         }
3800
3801 #if defined(ENABLE_THREADS)
3802         if (thread_get_current() == NULL) {
3803                 *env = NULL;
3804
3805                 return JNI_EDETACHED;
3806         }
3807 #endif
3808
3809         /* Check the JNI version. */
3810
3811         if (jni_version_check(version) == true) {
3812                 *env = VM::get_current()->get_jnienv();
3813                 return JNI_OK;
3814         }
3815
3816 #if defined(ENABLE_JVMTI)
3817         if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE) 
3818                 == JVMTI_VERSION_INTERFACE_JVMTI) {
3819
3820                 *env = (void *) jvmti_new_environment();
3821
3822                 if (env != NULL)
3823                         return JNI_OK;
3824         }
3825 #endif
3826         
3827         *env = NULL;
3828
3829         return JNI_EVERSION;
3830 }
3831
3832
3833 /* AttachCurrentThreadAsDaemon *************************************************
3834
3835    Same semantics as AttachCurrentThread, but the newly-created
3836    java.lang.Thread instance is a daemon.
3837
3838    If the thread has already been attached via either
3839    AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
3840    simply sets the value pointed to by penv to the JNIEnv of the
3841    current thread. In this case neither AttachCurrentThread nor this
3842    routine have any effect on the daemon status of the thread.
3843
3844 *******************************************************************************/
3845
3846 jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
3847 {
3848         int result;
3849
3850         TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
3851
3852         if (VM::get_current()->is_created() == false)
3853                 return JNI_ERR;
3854
3855         result = jni_attach_current_thread(penv, args, true);
3856
3857         return result;
3858 }
3859
3860
3861 /* JNI invocation table *******************************************************/
3862
3863 const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
3864         NULL,
3865         NULL,
3866         NULL,
3867
3868         _Jv_JNI_DestroyJavaVM,
3869         jni_AttachCurrentThread,
3870         jni_DetachCurrentThread,
3871         jni_GetEnv,
3872         jni_AttachCurrentThreadAsDaemon
3873 };
3874
3875
3876 /* JNI function table *********************************************************/
3877
3878 struct JNINativeInterface_ _Jv_JNINativeInterface = {
3879         NULL,
3880         NULL,
3881         NULL,
3882         NULL,    
3883         _Jv_JNI_GetVersion,
3884
3885         jni_DefineClass,
3886         jni_FindClass,
3887         jni_FromReflectedMethod,
3888         jni_FromReflectedField,
3889         jni_ToReflectedMethod,
3890         jni_GetSuperclass,
3891         _Jv_JNI_IsAssignableFrom,
3892         _Jv_JNI_ToReflectedField,
3893
3894         _Jv_JNI_Throw,
3895         _Jv_JNI_ThrowNew,
3896         _Jv_JNI_ExceptionOccurred,
3897         jni_ExceptionDescribe,
3898         jni_ExceptionClear,
3899         _Jv_JNI_FatalError,
3900         jni_PushLocalFrame,
3901         jni_PopLocalFrame,
3902
3903         jni_NewGlobalRef,
3904         jni_DeleteGlobalRef,
3905         jni_DeleteLocalRef,
3906         _Jv_JNI_IsSameObject,
3907         jni_NewLocalRef,
3908         jni_EnsureLocalCapacity,
3909
3910         _Jv_JNI_AllocObject,
3911         jni_NewObject,
3912         _Jv_JNI_NewObjectV,
3913         _Jv_JNI_NewObjectA,
3914
3915         jni_GetObjectClass,
3916         _Jv_JNI_IsInstanceOf,
3917
3918         _Jv_JNI_GetMethodID,
3919
3920         _Jv_JNI_CallObjectMethod,
3921         _Jv_JNI_CallObjectMethodV,
3922         _Jv_JNI_CallObjectMethodA,
3923         _Jv_JNI_CallBooleanMethod,
3924         _Jv_JNI_CallBooleanMethodV,
3925         _Jv_JNI_CallBooleanMethodA,
3926         _Jv_JNI_CallByteMethod,
3927         _Jv_JNI_CallByteMethodV,
3928         _Jv_JNI_CallByteMethodA,
3929         _Jv_JNI_CallCharMethod,
3930         _Jv_JNI_CallCharMethodV,
3931         _Jv_JNI_CallCharMethodA,
3932         _Jv_JNI_CallShortMethod,
3933         _Jv_JNI_CallShortMethodV,
3934         _Jv_JNI_CallShortMethodA,
3935         _Jv_JNI_CallIntMethod,
3936         _Jv_JNI_CallIntMethodV,
3937         _Jv_JNI_CallIntMethodA,
3938         _Jv_JNI_CallLongMethod,
3939         _Jv_JNI_CallLongMethodV,
3940         _Jv_JNI_CallLongMethodA,
3941         _Jv_JNI_CallFloatMethod,
3942         _Jv_JNI_CallFloatMethodV,
3943         _Jv_JNI_CallFloatMethodA,
3944         _Jv_JNI_CallDoubleMethod,
3945         _Jv_JNI_CallDoubleMethodV,
3946         _Jv_JNI_CallDoubleMethodA,
3947         _Jv_JNI_CallVoidMethod,
3948         _Jv_JNI_CallVoidMethodV,
3949         _Jv_JNI_CallVoidMethodA,
3950
3951         _Jv_JNI_CallNonvirtualObjectMethod,
3952         _Jv_JNI_CallNonvirtualObjectMethodV,
3953         _Jv_JNI_CallNonvirtualObjectMethodA,
3954         _Jv_JNI_CallNonvirtualBooleanMethod,
3955         _Jv_JNI_CallNonvirtualBooleanMethodV,
3956         _Jv_JNI_CallNonvirtualBooleanMethodA,
3957         _Jv_JNI_CallNonvirtualByteMethod,
3958         _Jv_JNI_CallNonvirtualByteMethodV,
3959         _Jv_JNI_CallNonvirtualByteMethodA,
3960         _Jv_JNI_CallNonvirtualCharMethod,
3961         _Jv_JNI_CallNonvirtualCharMethodV,
3962         _Jv_JNI_CallNonvirtualCharMethodA,
3963         _Jv_JNI_CallNonvirtualShortMethod,
3964         _Jv_JNI_CallNonvirtualShortMethodV,
3965         _Jv_JNI_CallNonvirtualShortMethodA,
3966         _Jv_JNI_CallNonvirtualIntMethod,
3967         _Jv_JNI_CallNonvirtualIntMethodV,
3968         _Jv_JNI_CallNonvirtualIntMethodA,
3969         _Jv_JNI_CallNonvirtualLongMethod,
3970         _Jv_JNI_CallNonvirtualLongMethodV,
3971         _Jv_JNI_CallNonvirtualLongMethodA,
3972         _Jv_JNI_CallNonvirtualFloatMethod,
3973         _Jv_JNI_CallNonvirtualFloatMethodV,
3974         _Jv_JNI_CallNonvirtualFloatMethodA,
3975         _Jv_JNI_CallNonvirtualDoubleMethod,
3976         _Jv_JNI_CallNonvirtualDoubleMethodV,
3977         _Jv_JNI_CallNonvirtualDoubleMethodA,
3978         _Jv_JNI_CallNonvirtualVoidMethod,
3979         _Jv_JNI_CallNonvirtualVoidMethodV,
3980         _Jv_JNI_CallNonvirtualVoidMethodA,
3981
3982         _Jv_JNI_GetFieldID,
3983
3984         _Jv_JNI_GetObjectField,
3985         _Jv_JNI_GetBooleanField,
3986         _Jv_JNI_GetByteField,
3987         _Jv_JNI_GetCharField,
3988         _Jv_JNI_GetShortField,
3989         _Jv_JNI_GetIntField,
3990         _Jv_JNI_GetLongField,
3991         _Jv_JNI_GetFloatField,
3992         _Jv_JNI_GetDoubleField,
3993         _Jv_JNI_SetObjectField,
3994         _Jv_JNI_SetBooleanField,
3995         _Jv_JNI_SetByteField,
3996         _Jv_JNI_SetCharField,
3997         _Jv_JNI_SetShortField,
3998         _Jv_JNI_SetIntField,
3999         _Jv_JNI_SetLongField,
4000         _Jv_JNI_SetFloatField,
4001         _Jv_JNI_SetDoubleField,
4002
4003         _Jv_JNI_GetStaticMethodID,
4004
4005         _Jv_JNI_CallStaticObjectMethod,
4006         _Jv_JNI_CallStaticObjectMethodV,
4007         _Jv_JNI_CallStaticObjectMethodA,
4008         _Jv_JNI_CallStaticBooleanMethod,
4009         _Jv_JNI_CallStaticBooleanMethodV,
4010         _Jv_JNI_CallStaticBooleanMethodA,
4011         _Jv_JNI_CallStaticByteMethod,
4012         _Jv_JNI_CallStaticByteMethodV,
4013         _Jv_JNI_CallStaticByteMethodA,
4014         _Jv_JNI_CallStaticCharMethod,
4015         _Jv_JNI_CallStaticCharMethodV,
4016         _Jv_JNI_CallStaticCharMethodA,
4017         _Jv_JNI_CallStaticShortMethod,
4018         _Jv_JNI_CallStaticShortMethodV,
4019         _Jv_JNI_CallStaticShortMethodA,
4020         _Jv_JNI_CallStaticIntMethod,
4021         _Jv_JNI_CallStaticIntMethodV,
4022         _Jv_JNI_CallStaticIntMethodA,
4023         _Jv_JNI_CallStaticLongMethod,
4024         _Jv_JNI_CallStaticLongMethodV,
4025         _Jv_JNI_CallStaticLongMethodA,
4026         _Jv_JNI_CallStaticFloatMethod,
4027         _Jv_JNI_CallStaticFloatMethodV,
4028         _Jv_JNI_CallStaticFloatMethodA,
4029         _Jv_JNI_CallStaticDoubleMethod,
4030         _Jv_JNI_CallStaticDoubleMethodV,
4031         _Jv_JNI_CallStaticDoubleMethodA,
4032         _Jv_JNI_CallStaticVoidMethod,
4033         _Jv_JNI_CallStaticVoidMethodV,
4034         _Jv_JNI_CallStaticVoidMethodA,
4035
4036         _Jv_JNI_GetStaticFieldID,
4037
4038         _Jv_JNI_GetStaticObjectField,
4039         _Jv_JNI_GetStaticBooleanField,
4040         _Jv_JNI_GetStaticByteField,
4041         _Jv_JNI_GetStaticCharField,
4042         _Jv_JNI_GetStaticShortField,
4043         _Jv_JNI_GetStaticIntField,
4044         _Jv_JNI_GetStaticLongField,
4045         _Jv_JNI_GetStaticFloatField,
4046         _Jv_JNI_GetStaticDoubleField,
4047         _Jv_JNI_SetStaticObjectField,
4048         _Jv_JNI_SetStaticBooleanField,
4049         _Jv_JNI_SetStaticByteField,
4050         _Jv_JNI_SetStaticCharField,
4051         _Jv_JNI_SetStaticShortField,
4052         _Jv_JNI_SetStaticIntField,
4053         _Jv_JNI_SetStaticLongField,
4054         _Jv_JNI_SetStaticFloatField,
4055         _Jv_JNI_SetStaticDoubleField,
4056
4057         jni_NewString,
4058         jni_GetStringLength,
4059         jni_GetStringChars,
4060         _Jv_JNI_ReleaseStringChars,
4061
4062         jni_NewStringUTF,
4063         jni_GetStringUTFLength,
4064         _Jv_JNI_GetStringUTFChars,
4065         _Jv_JNI_ReleaseStringUTFChars,
4066
4067         _Jv_JNI_GetArrayLength,
4068
4069         _Jv_JNI_NewObjectArray,
4070         _Jv_JNI_GetObjectArrayElement,
4071         _Jv_JNI_SetObjectArrayElement,
4072
4073         _Jv_JNI_NewBooleanArray,
4074         _Jv_JNI_NewByteArray,
4075         _Jv_JNI_NewCharArray,
4076         _Jv_JNI_NewShortArray,
4077         _Jv_JNI_NewIntArray,
4078         _Jv_JNI_NewLongArray,
4079         _Jv_JNI_NewFloatArray,
4080         _Jv_JNI_NewDoubleArray,
4081
4082         _Jv_JNI_GetBooleanArrayElements,
4083         _Jv_JNI_GetByteArrayElements,
4084         _Jv_JNI_GetCharArrayElements,
4085         _Jv_JNI_GetShortArrayElements,
4086         _Jv_JNI_GetIntArrayElements,
4087         _Jv_JNI_GetLongArrayElements,
4088         _Jv_JNI_GetFloatArrayElements,
4089         _Jv_JNI_GetDoubleArrayElements,
4090
4091         _Jv_JNI_ReleaseBooleanArrayElements,
4092         _Jv_JNI_ReleaseByteArrayElements,
4093         _Jv_JNI_ReleaseCharArrayElements,
4094         _Jv_JNI_ReleaseShortArrayElements,
4095         _Jv_JNI_ReleaseIntArrayElements,
4096         _Jv_JNI_ReleaseLongArrayElements,
4097         _Jv_JNI_ReleaseFloatArrayElements,
4098         _Jv_JNI_ReleaseDoubleArrayElements,
4099
4100         _Jv_JNI_GetBooleanArrayRegion,
4101         _Jv_JNI_GetByteArrayRegion,
4102         _Jv_JNI_GetCharArrayRegion,
4103         _Jv_JNI_GetShortArrayRegion,
4104         _Jv_JNI_GetIntArrayRegion,
4105         _Jv_JNI_GetLongArrayRegion,
4106         _Jv_JNI_GetFloatArrayRegion,
4107         _Jv_JNI_GetDoubleArrayRegion,
4108         _Jv_JNI_SetBooleanArrayRegion,
4109         _Jv_JNI_SetByteArrayRegion,
4110         _Jv_JNI_SetCharArrayRegion,
4111         _Jv_JNI_SetShortArrayRegion,
4112         _Jv_JNI_SetIntArrayRegion,
4113         _Jv_JNI_SetLongArrayRegion,
4114         _Jv_JNI_SetFloatArrayRegion,
4115         _Jv_JNI_SetDoubleArrayRegion,
4116
4117         jni_RegisterNatives,
4118         _Jv_JNI_UnregisterNatives,
4119
4120         _Jv_JNI_MonitorEnter,
4121         _Jv_JNI_MonitorExit,
4122
4123         _Jv_JNI_GetJavaVM,
4124
4125         /* New JNI 1.2 functions. */
4126
4127         jni_GetStringRegion,
4128         jni_GetStringUTFRegion,
4129
4130         jni_GetPrimitiveArrayCritical,
4131         jni_ReleasePrimitiveArrayCritical,
4132
4133         _Jv_JNI_GetStringCritical,
4134         _Jv_JNI_ReleaseStringCritical,
4135
4136         _Jv_JNI_NewWeakGlobalRef,
4137         _Jv_JNI_DeleteWeakGlobalRef,
4138
4139         _Jv_JNI_ExceptionCheck,
4140
4141         /* New JNI 1.4 functions. */
4142
4143         jni_NewDirectByteBuffer,
4144         jni_GetDirectBufferAddress,
4145         jni_GetDirectBufferCapacity,
4146
4147         /* New JNI 1.6 functions. */
4148
4149         jni_GetObjectRefType
4150 };
4151
4152
4153 /* Invocation API Functions ***************************************************/
4154
4155 /* JNI_GetDefaultJavaVMInitArgs ************************************************
4156
4157    Returns a default configuration for the Java VM.
4158
4159 *******************************************************************************/
4160
4161 jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
4162 {
4163         JavaVMInitArgs *_vm_args;
4164
4165         _vm_args = (JavaVMInitArgs *) vm_args;
4166
4167         /* GNU classpath currently supports JNI 1.2 */
4168
4169         switch (_vm_args->version) {
4170         case JNI_VERSION_1_1:
4171                 _vm_args->version = JNI_VERSION_1_1;
4172                 break;
4173
4174         case JNI_VERSION_1_2:
4175         case JNI_VERSION_1_4:
4176                 _vm_args->ignoreUnrecognized = JNI_FALSE;
4177                 _vm_args->options = NULL;
4178                 _vm_args->nOptions = 0;
4179                 break;
4180
4181         case JNI_VERSION_CACAO:
4182                 // We reveal ourselves by accepting this version number,
4183                 // this actually means we are using the supported JNI version.
4184                 _vm_args->version = JNI_VERSION_SUPPORTED;
4185                 break;
4186
4187         default:
4188                 return JNI_ERR;
4189         }
4190
4191         return JNI_OK;
4192 }
4193
4194
4195 /* JNI_GetCreatedJavaVMs *******************************************************
4196
4197    Returns all Java VMs that have been created. Pointers to VMs are written in
4198    the buffer vmBuf in the order they are created. At most bufLen number of
4199    entries will be written. The total number of created VMs is returned in
4200    *nVMs.
4201
4202 *******************************************************************************/
4203
4204 jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
4205 {
4206         TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
4207
4208         if (bufLen <= 0)
4209                 return JNI_ERR;
4210
4211         // We currently only support 1 VM running.
4212
4213         vmBuf[0] = VM::get_current()->get_javavm();
4214         *nVMs    = 1;
4215
4216     return JNI_OK;
4217 }
4218
4219
4220 /* JNI_CreateJavaVM ************************************************************
4221
4222    Loads and initializes a Java VM. The current thread becomes the main thread.
4223    Sets the env argument to the JNI interface pointer of the main thread.
4224
4225 *******************************************************************************/
4226
4227 jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
4228 {
4229         TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
4230
4231         /* actually create the JVM */
4232
4233         if (!VM_create(p_vm, p_env, vm_args))
4234                 return JNI_ERR;
4235
4236         return JNI_OK;
4237 }
4238
4239 } // extern "C"
4240
4241
4242 /*
4243  * These are local overrides for various environment variables in Emacs.
4244  * Please do not remove this and leave it at the end of the file, where
4245  * Emacs will automagically detect them.
4246  * ---------------------------------------------------------------------
4247  * Local variables:
4248  * mode: c++
4249  * indent-tabs-mode: t
4250  * c-basic-offset: 4
4251  * tab-width: 4
4252  * End:
4253  * vim:noexpandtab:sw=4:ts=4:
4254  */