source: branches/libc-0.6/src/gcc/libjava/jni.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 72.9 KB
Line 
1// jni.cc - JNI implementation, including the jump table.
2
3/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include <stdio.h>
14#include <stddef.h>
15#include <string.h>
16
17#include <gcj/cni.h>
18#include <jvm.h>
19#include <java-assert.h>
20#include <jni.h>
21#ifdef ENABLE_JVMPI
22#include <jvmpi.h>
23#endif
24
25#include <java/lang/Class.h>
26#include <java/lang/ClassLoader.h>
27#include <java/lang/Throwable.h>
28#include <java/lang/ArrayIndexOutOfBoundsException.h>
29#include <java/lang/StringIndexOutOfBoundsException.h>
30#include <java/lang/UnsatisfiedLinkError.h>
31#include <java/lang/InstantiationException.h>
32#include <java/lang/NoSuchFieldError.h>
33#include <java/lang/NoSuchMethodError.h>
34#include <java/lang/reflect/Constructor.h>
35#include <java/lang/reflect/Method.h>
36#include <java/lang/reflect/Modifier.h>
37#include <java/lang/OutOfMemoryError.h>
38#include <java/util/IdentityHashMap.h>
39#include <java/lang/Integer.h>
40#include <java/lang/ThreadGroup.h>
41#include <java/lang/Thread.h>
42
43#include <gcj/method.h>
44#include <gcj/field.h>
45
46#include <java-interp.h>
47#include <java-threads.h>
48
49using namespace gcj;
50
51// This enum is used to select different template instantiations in
52// the invocation code.
53enum invocation_type
54{
55 normal,
56 nonvirtual,
57 static_type,
58 constructor
59};
60
61// Forward declarations.
62extern struct JNINativeInterface _Jv_JNIFunctions;
63extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions;
64
65// Number of slots in the default frame. The VM must allow at least
66// 16.
67#define FRAME_SIZE 32
68
69// Mark value indicating this is an overflow frame.
70#define MARK_NONE 0
71// Mark value indicating this is a user frame.
72#define MARK_USER 1
73// Mark value indicating this is a system frame.
74#define MARK_SYSTEM 2
75
76// This structure is used to keep track of local references.
77struct _Jv_JNI_LocalFrame
78{
79 // This is true if this frame object represents a pushed frame (eg
80 // from PushLocalFrame).
81 int marker : 2;
82
83 // Number of elements in frame.
84 int size : 30;
85
86 // Next frame in chain.
87 _Jv_JNI_LocalFrame *next;
88
89 // The elements. These are allocated using the C "struct hack".
90 jobject vec[0];
91};
92
93// This holds a reference count for all local references.
94static java::util::IdentityHashMap *local_ref_table;
95// This holds a reference count for all global references.
96static java::util::IdentityHashMap *global_ref_table;
97
98// The only VM.
99static JavaVM *the_vm;
100
101#ifdef ENABLE_JVMPI
102// The only JVMPI interface description.
103static JVMPI_Interface _Jv_JVMPI_Interface;
104
105static jint
106jvmpiEnableEvent (jint event_type, void *)
107{
108 switch (event_type)
109 {
110 case JVMPI_EVENT_OBJECT_ALLOC:
111 _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
112 break;
113
114 case JVMPI_EVENT_THREAD_START:
115 _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
116 break;
117
118 case JVMPI_EVENT_THREAD_END:
119 _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
120 break;
121
122 default:
123 return JVMPI_NOT_AVAILABLE;
124 }
125
126 return JVMPI_SUCCESS;
127}
128
129static jint
130jvmpiDisableEvent (jint event_type, void *)
131{
132 switch (event_type)
133 {
134 case JVMPI_EVENT_OBJECT_ALLOC:
135 _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
136 break;
137
138 default:
139 return JVMPI_NOT_AVAILABLE;
140 }
141
142 return JVMPI_SUCCESS;
143}
144#endif
145
146
147
148
149void
150_Jv_JNI_Init (void)
151{
152 local_ref_table = new java::util::IdentityHashMap;
153 global_ref_table = new java::util::IdentityHashMap;
154
155#ifdef ENABLE_JVMPI
156 _Jv_JVMPI_Interface.version = 1;
157 _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
158 _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent;
159 _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC;
160 _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC;
161 _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC;
162#endif
163}
164
165// Tell the GC that a certain pointer is live.
166static void
167mark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
168{
169 JvSynchronize sync (ref_table);
170
171 using namespace java::lang;
172 Integer *refcount = (Integer *) ref_table->get (obj);
173 jint val = (refcount == NULL) ? 0 : refcount->intValue ();
174 // FIXME: what about out of memory error?
175 ref_table->put (obj, new Integer (val + 1));
176}
177
178// Unmark a pointer.
179static void
180unmark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
181{
182 JvSynchronize sync (ref_table);
183
184 using namespace java::lang;
185 Integer *refcount = (Integer *) ref_table->get (obj);
186 JvAssert (refcount);
187 jint val = refcount->intValue () - 1;
188 JvAssert (val >= 0);
189 if (val == 0)
190 ref_table->remove (obj);
191 else
192 // FIXME: what about out of memory error?
193 ref_table->put (obj, new Integer (val));
194}
195
196// "Unwrap" some random non-reference type. This exists to simplify
197// other template functions.
198template<typename T>
199static T
200unwrap (T val)
201{
202 return val;
203}
204
205// Unwrap a weak reference, if required.
206template<typename T>
207static T *
208unwrap (T *obj)
209{
210 using namespace gnu::gcj::runtime;
211 // We can compare the class directly because JNIWeakRef is `final'.
212 // Doing it this way is much faster.
213 if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
214 return obj;
215 JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
216 return reinterpret_cast<T *> (wr->get ());
217}
218
219
220
221
222static jobject
223(JNICALL _Jv_JNI_NewGlobalRef) (JNIEnv *, jobject obj)
224{
225 // This seems weird but I think it is correct.
226 obj = unwrap (obj);
227 mark_for_gc (obj, global_ref_table);
228 return obj;
229}
230
231static void
232(JNICALL _Jv_JNI_DeleteGlobalRef) (JNIEnv *, jobject obj)
233{
234 // This seems weird but I think it is correct.
235 obj = unwrap (obj);
236 unmark_for_gc (obj, global_ref_table);
237}
238
239static void
240(JNICALL _Jv_JNI_DeleteLocalRef) (JNIEnv *env, jobject obj)
241{
242 _Jv_JNI_LocalFrame *frame;
243
244 // This seems weird but I think it is correct.
245 obj = unwrap (obj);
246
247 for (frame = env->locals; frame != NULL; frame = frame->next)
248 {
249 for (int i = 0; i < frame->size; ++i)
250 {
251 if (frame->vec[i] == obj)
252 {
253 frame->vec[i] = NULL;
254 unmark_for_gc (obj, local_ref_table);
255 return;
256 }
257 }
258
259 // Don't go past a marked frame.
260 JvAssert (frame->marker == MARK_NONE);
261 }
262
263 JvAssert (0);
264}
265
266static jint
267(JNICALL _Jv_JNI_EnsureLocalCapacity) (JNIEnv *env, jint size)
268{
269 // It is easier to just always allocate a new frame of the requested
270 // size. This isn't the most efficient thing, but for now we don't
271 // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
272
273 _Jv_JNI_LocalFrame *frame;
274 try
275 {
276 frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
277 + size * sizeof (jobject));
278 }
279 catch (jthrowable t)
280 {
281 env->ex = t;
282 return JNI_ERR;
283 }
284
285 frame->marker = MARK_NONE;
286 frame->size = size;
287 memset (&frame->vec[0], 0, size * sizeof (jobject));
288 frame->next = env->locals;
289 env->locals = frame;
290
291 return 0;
292}
293
294static jint
295(JNICALL _Jv_JNI_PushLocalFrame) (JNIEnv *env, jint size)
296{
297 jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
298 if (r < 0)
299 return r;
300
301 // The new frame is on top.
302 env->locals->marker = MARK_USER;
303
304 return 0;
305}
306
307static jobject
308(JNICALL _Jv_JNI_NewLocalRef) (JNIEnv *env, jobject obj)
309{
310 // This seems weird but I think it is correct.
311 obj = unwrap (obj);
312
313 // Try to find an open slot somewhere in the topmost frame.
314 _Jv_JNI_LocalFrame *frame = env->locals;
315 bool done = false, set = false;
316 for (; frame != NULL && ! done; frame = frame->next)
317 {
318 for (int i = 0; i < frame->size; ++i)
319 {
320 if (frame->vec[i] == NULL)
321 {
322 set = true;
323 done = true;
324 frame->vec[i] = obj;
325 break;
326 }
327 }
328
329 // If we found a slot, or if the frame we just searched is the
330 // mark frame, then we are done.
331 if (done || frame == NULL || frame->marker != MARK_NONE)
332 break;
333 }
334
335 if (! set)
336 {
337 // No slots, so we allocate a new frame. According to the spec
338 // we could just die here. FIXME: return value.
339 _Jv_JNI_EnsureLocalCapacity (env, 16);
340 // We know the first element of the new frame will be ok.
341 env->locals->vec[0] = obj;
342 }
343
344 mark_for_gc (obj, local_ref_table);
345 return obj;
346}
347
348static jobject
349(JNICALL _Jv_JNI_PopLocalFrame) (JNIEnv *env, jobject result, int stop)
350{
351 _Jv_JNI_LocalFrame *rf = env->locals;
352
353 bool done = false;
354 while (rf != NULL && ! done)
355 {
356 for (int i = 0; i < rf->size; ++i)
357 if (rf->vec[i] != NULL)
358 unmark_for_gc (rf->vec[i], local_ref_table);
359
360 // If the frame we just freed is the marker frame, we are done.
361 done = (rf->marker == stop);
362
363 _Jv_JNI_LocalFrame *n = rf->next;
364 // When N==NULL, we've reached the stack-allocated frame, and we
365 // must not free it. However, we must be sure to clear all its
366 // elements, since we might conceivably reuse it.
367 if (n == NULL)
368 {
369 memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
370 break;
371 }
372
373 _Jv_Free (rf);
374 rf = n;
375 }
376
377 // Update the local frame information.
378 env->locals = rf;
379
380 return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
381}
382
383static jobject
384(JNICALL _Jv_JNI_PopLocalFrame) (JNIEnv *env, jobject result)
385{
386 return _Jv_JNI_PopLocalFrame (env, result, MARK_USER);
387}
388
389// Pop a `system' frame from the stack. This is `extern "C"' as it is
390// used by the compiler.
391extern "C" void
392_Jv_JNI_PopSystemFrame (JNIEnv *env)
393{
394 _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
395
396 if (env->ex)
397 {
398 jthrowable t = env->ex;
399 env->ex = NULL;
400 throw t;
401 }
402}
403
404// This function is used from other template functions. It wraps the
405// return value appropriately; we specialize it so that object returns
406// are turned into local references.
407template<typename T>
408static T
409wrap_value (JNIEnv *, T value)
410{
411 return value;
412}
413
414// This specialization is used for jobject, jclass, jstring, jarray,
415// etc.
416template<typename T>
417static T *
418wrap_value (JNIEnv *env, T *value)
419{
420 return (value == NULL
421 ? value
422 : (T *) _Jv_JNI_NewLocalRef (env, (jobject) value));
423}
424
425
426
427
428static jint
429(JNICALL _Jv_JNI_GetVersion) (JNIEnv *)
430{
431 return JNI_VERSION_1_4;
432}
433
434static jclass
435(JNICALL _Jv_JNI_DefineClass) (JNIEnv *env, const char *name, jobject loader,
436 const jbyte *buf, jsize bufLen)
437{
438 try
439 {
440 loader = unwrap (loader);
441
442 jstring sname = JvNewStringUTF (name);
443 jbyteArray bytes = JvNewByteArray (bufLen);
444
445 jbyte *elts = elements (bytes);
446 memcpy (elts, buf, bufLen * sizeof (jbyte));
447
448 java::lang::ClassLoader *l
449 = reinterpret_cast<java::lang::ClassLoader *> (loader);
450
451 jclass result = l->defineClass (sname, bytes, 0, bufLen);
452 return (jclass) wrap_value (env, result);
453 }
454 catch (jthrowable t)
455 {
456 env->ex = t;
457 return NULL;
458 }
459}
460
461static jclass
462(JNICALL _Jv_JNI_FindClass) (JNIEnv *env, const char *name)
463{
464 // FIXME: assume that NAME isn't too long.
465 int len = strlen (name);
466 char s[len + 1];
467 for (int i = 0; i <= len; ++i)
468 s[i] = (name[i] == '/') ? '.' : name[i];
469
470 jclass r = NULL;
471 try
472 {
473 // This might throw an out of memory exception.
474 jstring n = JvNewStringUTF (s);
475
476 java::lang::ClassLoader *loader = NULL;
477 if (env->klass != NULL)
478 loader = env->klass->getClassLoader ();
479
480 if (loader == NULL)
481 {
482 // FIXME: should use getBaseClassLoader, but we don't have that
483 // yet.
484 loader = java::lang::ClassLoader::getSystemClassLoader ();
485 }
486
487 r = loader->loadClass (n);
488 }
489 catch (jthrowable t)
490 {
491 env->ex = t;
492 }
493
494 return (jclass) wrap_value (env, r);
495}
496
497static jclass
498(JNICALL _Jv_JNI_GetSuperclass) (JNIEnv *env, jclass clazz)
499{
500 return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
501}
502
503static jboolean
504(JNICALL _Jv_JNI_IsAssignableFrom) (JNIEnv *, jclass clazz1, jclass clazz2)
505{
506 return unwrap (clazz1)->isAssignableFrom (unwrap (clazz2));
507}
508
509static jint
510(JNICALL _Jv_JNI_Throw) (JNIEnv *env, jthrowable obj)
511{
512 // We check in case the user did some funky cast.
513 obj = unwrap (obj);
514 JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
515 env->ex = obj;
516 return 0;
517}
518
519static jint
520(JNICALL _Jv_JNI_ThrowNew) (JNIEnv *env, jclass clazz, const char *message)
521{
522 using namespace java::lang::reflect;
523
524 clazz = unwrap (clazz);
525 JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
526
527 int r = JNI_OK;
528 try
529 {
530 JArray<jclass> *argtypes
531 = (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
532 NULL);
533
534 jclass *elts = elements (argtypes);
535 elts[0] = &StringClass;
536
537 Constructor *cons = clazz->getConstructor (argtypes);
538
539 jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
540 jobject *velts = elements (values);
541 velts[0] = JvNewStringUTF (message);
542
543 jobject obj = cons->newInstance (values);
544
545 env->ex = reinterpret_cast<jthrowable> (obj);
546 }
547 catch (jthrowable t)
548 {
549 env->ex = t;
550 r = JNI_ERR;
551 }
552
553 return r;
554}
555
556static jthrowable
557(JNICALL _Jv_JNI_ExceptionOccurred) (JNIEnv *env)
558{
559 return (jthrowable) wrap_value (env, env->ex);
560}
561
562static void
563(JNICALL _Jv_JNI_ExceptionDescribe) (JNIEnv *env)
564{
565 if (env->ex != NULL)
566 env->ex->printStackTrace();
567}
568
569static void
570(JNICALL _Jv_JNI_ExceptionClear) (JNIEnv *env)
571{
572 env->ex = NULL;
573}
574
575static jboolean
576(JNICALL _Jv_JNI_ExceptionCheck) (JNIEnv *env)
577{
578 return env->ex != NULL;
579}
580
581static void
582(JNICALL _Jv_JNI_FatalError) (JNIEnv *, const char *message)
583{
584 JvFail (message);
585}
586
587
588
589
590static jboolean
591(JNICALL _Jv_JNI_IsSameObject) (JNIEnv *, jobject obj1, jobject obj2)
592{
593 return unwrap (obj1) == unwrap (obj2);
594}
595
596static jobject
597(JNICALL _Jv_JNI_AllocObject) (JNIEnv *env, jclass clazz)
598{
599 jobject obj = NULL;
600 using namespace java::lang::reflect;
601
602 try
603 {
604 clazz = unwrap (clazz);
605 JvAssert (clazz && ! clazz->isArray ());
606 if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
607 env->ex = new java::lang::InstantiationException ();
608 else
609 obj = JvAllocObject (clazz);
610 }
611 catch (jthrowable t)
612 {
613 env->ex = t;
614 }
615
616 return wrap_value (env, obj);
617}
618
619static jclass
620(JNICALL _Jv_JNI_GetObjectClass) (JNIEnv *env, jobject obj)
621{
622 obj = unwrap (obj);
623 JvAssert (obj);
624 return (jclass) wrap_value (env, obj->getClass());
625}
626
627static jboolean
628(JNICALL _Jv_JNI_IsInstanceOf) (JNIEnv *, jobject obj, jclass clazz)
629{
630 return unwrap (clazz)->isInstance(unwrap (obj));
631}
632
633
634
635
636//
637// This section concerns method invocation.
638//
639
640template<jboolean is_static>
641static jmethodID
642(JNICALL _Jv_JNI_GetAnyMethodID) (JNIEnv *env, jclass clazz,
643 const char *name, const char *sig)
644{
645 try
646 {
647 clazz = unwrap (clazz);
648 _Jv_InitClass (clazz);
649
650 _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
651
652 // FIXME: assume that SIG isn't too long.
653 int len = strlen (sig);
654 char s[len + 1];
655 for (int i = 0; i <= len; ++i)
656 s[i] = (sig[i] == '/') ? '.' : sig[i];
657 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1);
658
659 JvAssert (! clazz->isPrimitive());
660
661 using namespace java::lang::reflect;
662
663 while (clazz != NULL)
664 {
665 jint count = JvNumMethods (clazz);
666 jmethodID meth = JvGetFirstMethod (clazz);
667
668 for (jint i = 0; i < count; ++i)
669 {
670 if (((is_static && Modifier::isStatic (meth->accflags))
671 || (! is_static && ! Modifier::isStatic (meth->accflags)))
672 && _Jv_equalUtf8Consts (meth->name, name_u)
673 && _Jv_equalUtf8Consts (meth->signature, sig_u))
674 return meth;
675
676 meth = meth->getNextMethod();
677 }
678
679 clazz = clazz->getSuperclass ();
680 }
681
682 env->ex = new java::lang::NoSuchMethodError ();
683 }
684 catch (jthrowable t)
685 {
686 env->ex = t;
687 }
688
689 return NULL;
690}
691
692// This is a helper function which turns a va_list into an array of
693// `jvalue's. It needs signature information in order to do its work.
694// The array of values must already be allocated.
695static void
696array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
697{
698 jclass *arg_elts = elements (arg_types);
699 for (int i = 0; i < arg_types->length; ++i)
700 {
701 // Here we assume that sizeof(int) >= sizeof(jint), because we
702 // use `int' when decoding the varargs. Likewise for
703 // float, and double. Also we assume that sizeof(jlong) >=
704 // sizeof(int), i.e. that jlong values are not further
705 // promoted.
706 JvAssert (sizeof (int) >= sizeof (jint));
707 JvAssert (sizeof (jlong) >= sizeof (int));
708 JvAssert (sizeof (double) >= sizeof (jfloat));
709 JvAssert (sizeof (double) >= sizeof (jdouble));
710 if (arg_elts[i] == JvPrimClass (byte))
711 values[i].b = (jbyte) va_arg (vargs, int);
712 else if (arg_elts[i] == JvPrimClass (short))
713 values[i].s = (jshort) va_arg (vargs, int);
714 else if (arg_elts[i] == JvPrimClass (int))
715 values[i].i = (jint) va_arg (vargs, int);
716 else if (arg_elts[i] == JvPrimClass (long))
717 values[i].j = (jlong) va_arg (vargs, jlong);
718 else if (arg_elts[i] == JvPrimClass (float))
719 values[i].f = (jfloat) va_arg (vargs, double);
720 else if (arg_elts[i] == JvPrimClass (double))
721 values[i].d = (jdouble) va_arg (vargs, double);
722 else if (arg_elts[i] == JvPrimClass (boolean))
723 values[i].z = (jboolean) va_arg (vargs, int);
724 else if (arg_elts[i] == JvPrimClass (char))
725 values[i].c = (jchar) va_arg (vargs, int);
726 else
727 {
728 // An object.
729 values[i].l = unwrap (va_arg (vargs, jobject));
730 }
731 }
732}
733
734// This can call any sort of method: virtual, "nonvirtual", static, or
735// constructor.
736template<typename T, invocation_type style>
737static T
738(JNICALL _Jv_JNI_CallAnyMethodV) (JNIEnv *env, jobject obj, jclass klass,
739 jmethodID id, va_list vargs)
740{
741 obj = unwrap (obj);
742 klass = unwrap (klass);
743
744 if (style == normal)
745 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
746
747 jclass decl_class = klass ? klass : obj->getClass ();
748 JvAssert (decl_class != NULL);
749
750 jclass return_type;
751 JArray<jclass> *arg_types;
752
753 try
754 {
755 _Jv_GetTypesFromSignature (id, decl_class,
756 &arg_types, &return_type);
757
758 jvalue args[arg_types->length];
759 array_from_valist (args, arg_types, vargs);
760
761 // For constructors we need to pass the Class we are instantiating.
762 if (style == constructor)
763 return_type = klass;
764
765 jvalue result;
766 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
767 style == constructor,
768 arg_types, args, &result);
769
770 if (ex != NULL)
771 env->ex = ex;
772
773 // We cheat a little here. FIXME.
774 return wrap_value (env, * (T *) &result);
775 }
776 catch (jthrowable t)
777 {
778 env->ex = t;
779 }
780
781 return wrap_value (env, (T) 0);
782}
783
784template<typename T, invocation_type style>
785static T
786(JNICALL _Jv_JNI_CallAnyMethod) (JNIEnv *env, jobject obj, jclass klass,
787 jmethodID method, ...)
788{
789 va_list args;
790 T result;
791
792 va_start (args, method);
793 result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
794 va_end (args);
795
796 return result;
797}
798
799template<typename T, invocation_type style>
800static T
801(JNICALL _Jv_JNI_CallAnyMethodA) (JNIEnv *env, jobject obj, jclass klass,
802 jmethodID id, jvalue *args)
803{
804 obj = unwrap (obj);
805 klass = unwrap (klass);
806
807 if (style == normal)
808 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
809
810 jclass decl_class = klass ? klass : obj->getClass ();
811 JvAssert (decl_class != NULL);
812
813 jclass return_type;
814 JArray<jclass> *arg_types;
815 try
816 {
817 _Jv_GetTypesFromSignature (id, decl_class,
818 &arg_types, &return_type);
819
820 // For constructors we need to pass the Class we are instantiating.
821 if (style == constructor)
822 return_type = klass;
823
824 // Unwrap arguments as required. Eww.
825 jclass *type_elts = elements (arg_types);
826 jvalue arg_copy[arg_types->length];
827 for (int i = 0; i < arg_types->length; ++i)
828 {
829 if (type_elts[i]->isPrimitive ())
830 arg_copy[i] = args[i];
831 else
832 arg_copy[i].l = unwrap (args[i].l);
833 }
834
835 jvalue result;
836 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
837 style == constructor,
838 arg_types, arg_copy, &result);
839
840 if (ex != NULL)
841 env->ex = ex;
842
843 // We cheat a little here. FIXME.
844 return wrap_value (env, * (T *) &result);
845 }
846 catch (jthrowable t)
847 {
848 env->ex = t;
849 }
850
851 return wrap_value (env, (T) 0);
852}
853
854template<invocation_type style>
855static void
856(JNICALL _Jv_JNI_CallAnyVoidMethodV) (JNIEnv *env, jobject obj, jclass klass,
857 jmethodID id, va_list vargs)
858{
859 obj = unwrap (obj);
860 klass = unwrap (klass);
861
862 if (style == normal)
863 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
864
865 jclass decl_class = klass ? klass : obj->getClass ();
866 JvAssert (decl_class != NULL);
867
868 jclass return_type;
869 JArray<jclass> *arg_types;
870 try
871 {
872 _Jv_GetTypesFromSignature (id, decl_class,
873 &arg_types, &return_type);
874
875 jvalue args[arg_types->length];
876 array_from_valist (args, arg_types, vargs);
877
878 // For constructors we need to pass the Class we are instantiating.
879 if (style == constructor)
880 return_type = klass;
881
882 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
883 style == constructor,
884 arg_types, args, NULL);
885
886 if (ex != NULL)
887 env->ex = ex;
888 }
889 catch (jthrowable t)
890 {
891 env->ex = t;
892 }
893}
894
895template<invocation_type style>
896static void
897(JNICALL _Jv_JNI_CallAnyVoidMethod) (JNIEnv *env, jobject obj, jclass klass,
898 jmethodID method, ...)
899{
900 va_list args;
901
902 va_start (args, method);
903 _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
904 va_end (args);
905}
906
907template<invocation_type style>
908static void
909(JNICALL _Jv_JNI_CallAnyVoidMethodA) (JNIEnv *env, jobject obj, jclass klass,
910 jmethodID id, jvalue *args)
911{
912 if (style == normal)
913 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
914
915 jclass decl_class = klass ? klass : obj->getClass ();
916 JvAssert (decl_class != NULL);
917
918 jclass return_type;
919 JArray<jclass> *arg_types;
920 try
921 {
922 _Jv_GetTypesFromSignature (id, decl_class,
923 &arg_types, &return_type);
924
925 // Unwrap arguments as required. Eww.
926 jclass *type_elts = elements (arg_types);
927 jvalue arg_copy[arg_types->length];
928 for (int i = 0; i < arg_types->length; ++i)
929 {
930 if (type_elts[i]->isPrimitive ())
931 arg_copy[i] = args[i];
932 else
933 arg_copy[i].l = unwrap (args[i].l);
934 }
935
936 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
937 style == constructor,
938 arg_types, args, NULL);
939
940 if (ex != NULL)
941 env->ex = ex;
942 }
943 catch (jthrowable t)
944 {
945 env->ex = t;
946 }
947}
948
949// Functions with this signature are used to implement functions in
950// the CallMethod family.
951template<typename T>
952static T
953(JNICALL _Jv_JNI_CallMethodV) (JNIEnv *env, jobject obj,
954 jmethodID id, va_list args)
955{
956 return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
957}
958
959// Functions with this signature are used to implement functions in
960// the CallMethod family.
961template<typename T>
962static T
963(JNICALL _Jv_JNI_CallMethod) (JNIEnv *env, jobject obj, jmethodID id, ...)
964{
965 va_list args;
966 T result;
967
968 va_start (args, id);
969 result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
970 va_end (args);
971
972 return result;
973}
974
975// Functions with this signature are used to implement functions in
976// the CallMethod family.
977template<typename T>
978static T
979(JNICALL _Jv_JNI_CallMethodA) (JNIEnv *env, jobject obj,
980 jmethodID id, jvalue *args)
981{
982 return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
983}
984
985static void
986(JNICALL _Jv_JNI_CallVoidMethodV) (JNIEnv *env, jobject obj,
987 jmethodID id, va_list args)
988{
989 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
990}
991
992static void
993(JNICALL _Jv_JNI_CallVoidMethod) (JNIEnv *env, jobject obj, jmethodID id, ...)
994{
995 va_list args;
996
997 va_start (args, id);
998 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
999 va_end (args);
1000}
1001
1002static void
1003(JNICALL _Jv_JNI_CallVoidMethodA) (JNIEnv *env, jobject obj,
1004 jmethodID id, jvalue *args)
1005{
1006 _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
1007}
1008
1009// Functions with this signature are used to implement functions in
1010// the CallStaticMethod family.
1011template<typename T>
1012static T
1013(JNICALL _Jv_JNI_CallStaticMethodV) (JNIEnv *env, jclass klass,
1014 jmethodID id, va_list args)
1015{
1016 JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1017 JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1018
1019 return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
1020}
1021
1022// Functions with this signature are used to implement functions in
1023// the CallStaticMethod family.
1024template<typename T>
1025static T
1026(JNICALL _Jv_JNI_CallStaticMethod) (JNIEnv *env, jclass klass,
1027 jmethodID id, ...)
1028{
1029 va_list args;
1030 T result;
1031
1032 JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1033 JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1034
1035 va_start (args, id);
1036 result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
1037 id, args);
1038 va_end (args);
1039
1040 return result;
1041}
1042
1043// Functions with this signature are used to implement functions in
1044// the CallStaticMethod family.
1045template<typename T>
1046static T
1047(JNICALL _Jv_JNI_CallStaticMethodA) (JNIEnv *env, jclass klass, jmethodID id,
1048 jvalue *args)
1049{
1050 JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
1051 JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
1052
1053 return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
1054}
1055
1056static void
1057(JNICALL _Jv_JNI_CallStaticVoidMethodV) (JNIEnv *env, jclass klass,
1058 jmethodID id, va_list args)
1059{
1060 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1061}
1062
1063static void
1064(JNICALL _Jv_JNI_CallStaticVoidMethod) (JNIEnv *env, jclass klass,
1065 jmethodID id, ...)
1066{
1067 va_list args;
1068
1069 va_start (args, id);
1070 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
1071 va_end (args);
1072}
1073
1074static void
1075(JNICALL _Jv_JNI_CallStaticVoidMethodA) (JNIEnv *env, jclass klass,
1076 jmethodID id, jvalue *args)
1077{
1078 _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
1079}
1080
1081static jobject
1082(JNICALL _Jv_JNI_NewObjectV) (JNIEnv *env, jclass klass,
1083 jmethodID id, va_list args)
1084{
1085 JvAssert (klass && ! klass->isArray ());
1086 JvAssert (! strcmp (id->name->data, "<init>")
1087 && id->signature->length > 2
1088 && id->signature->data[0] == '('
1089 && ! strcmp (&id->signature->data[id->signature->length - 2],
1090 ")V"));
1091
1092 return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1093 id, args);
1094}
1095
1096static jobject
1097(JNICALL _Jv_JNI_NewObject) (JNIEnv *env, jclass klass, jmethodID id, ...)
1098{
1099 JvAssert (klass && ! klass->isArray ());
1100 JvAssert (! strcmp (id->name->data, "<init>")
1101 && id->signature->length > 2
1102 && id->signature->data[0] == '('
1103 && ! strcmp (&id->signature->data[id->signature->length - 2],
1104 ")V"));
1105
1106 va_list args;
1107 jobject result;
1108
1109 va_start (args, id);
1110 result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
1111 id, args);
1112 va_end (args);
1113
1114 return result;
1115}
1116
1117static jobject
1118(JNICALL _Jv_JNI_NewObjectA) (JNIEnv *env, jclass klass, jmethodID id,
1119 jvalue *args)
1120{
1121 JvAssert (klass && ! klass->isArray ());
1122 JvAssert (! strcmp (id->name->data, "<init>")
1123 && id->signature->length > 2
1124 && id->signature->data[0] == '('
1125 && ! strcmp (&id->signature->data[id->signature->length - 2],
1126 ")V"));
1127
1128 return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
1129 id, args);
1130}
1131
1132
1133
1134
1135template<typename T>
1136static T
1137(JNICALL _Jv_JNI_GetField) (JNIEnv *env, jobject obj, jfieldID field)
1138{
1139 obj = unwrap (obj);
1140 JvAssert (obj);
1141 T *ptr = (T *) ((char *) obj + field->getOffset ());
1142 return wrap_value (env, *ptr);
1143}
1144
1145template<typename T>
1146static void
1147(JNICALL _Jv_JNI_SetField) (JNIEnv *, jobject obj, jfieldID field, T value)
1148{
1149 obj = unwrap (obj);
1150 value = unwrap (value);
1151
1152 JvAssert (obj);
1153 T *ptr = (T *) ((char *) obj + field->getOffset ());
1154 *ptr = value;
1155}
1156
1157template<jboolean is_static>
1158static jfieldID
1159(JNICALL _Jv_JNI_GetAnyFieldID) (JNIEnv *env, jclass clazz,
1160 const char *name, const char *sig)
1161{
1162 try
1163 {
1164 clazz = unwrap (clazz);
1165
1166 _Jv_InitClass (clazz);
1167
1168 _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
1169
1170 // FIXME: assume that SIG isn't too long.
1171 int len = strlen (sig);
1172 char s[len + 1];
1173 for (int i = 0; i <= len; ++i)
1174 s[i] = (sig[i] == '/') ? '.' : sig[i];
1175 jclass field_class = _Jv_FindClassFromSignature ((char *) s, NULL);
1176
1177 // FIXME: what if field_class == NULL?
1178
1179 java::lang::ClassLoader *loader = clazz->getClassLoader ();
1180 while (clazz != NULL)
1181 {
1182 // We acquire the class lock so that fields aren't resolved
1183 // while we are running.
1184 JvSynchronize sync (clazz);
1185
1186 jint count = (is_static
1187 ? JvNumStaticFields (clazz)
1188 : JvNumInstanceFields (clazz));
1189 jfieldID field = (is_static
1190 ? JvGetFirstStaticField (clazz)
1191 : JvGetFirstInstanceField (clazz));
1192 for (jint i = 0; i < count; ++i)
1193 {
1194 _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
1195
1196 // The field might be resolved or it might not be. It
1197 // is much simpler to always resolve it.
1198 _Jv_ResolveField (field, loader);
1199 if (_Jv_equalUtf8Consts (f_name, a_name)
1200 && field->getClass() == field_class)
1201 return field;
1202
1203 field = field->getNextField ();
1204 }
1205
1206 clazz = clazz->getSuperclass ();
1207 }
1208
1209 env->ex = new java::lang::NoSuchFieldError ();
1210 }
1211 catch (jthrowable t)
1212 {
1213 env->ex = t;
1214 }
1215 return NULL;
1216}
1217
1218template<typename T>
1219static T
1220(JNICALL _Jv_JNI_GetStaticField) (JNIEnv *env, jclass, jfieldID field)
1221{
1222 T *ptr = (T *) field->u.addr;
1223 return wrap_value (env, *ptr);
1224}
1225
1226template<typename T>
1227static void
1228(JNICALL _Jv_JNI_SetStaticField) (JNIEnv *, jclass, jfieldID field, T value)
1229{
1230 value = unwrap (value);
1231 T *ptr = (T *) field->u.addr;
1232 *ptr = value;
1233}
1234
1235static jstring
1236(JNICALL _Jv_JNI_NewString) (JNIEnv *env, const jchar *unichars, jsize len)
1237{
1238 try
1239 {
1240 jstring r = _Jv_NewString (unichars, len);
1241 return (jstring) wrap_value (env, r);
1242 }
1243 catch (jthrowable t)
1244 {
1245 env->ex = t;
1246 return NULL;
1247 }
1248}
1249
1250static jsize
1251(JNICALL _Jv_JNI_GetStringLength) (JNIEnv *, jstring string)
1252{
1253 return unwrap (string)->length();
1254}
1255
1256static const jchar *
1257(JNICALL _Jv_JNI_GetStringChars) (JNIEnv *, jstring string, jboolean *isCopy)
1258{
1259 string = unwrap (string);
1260 jchar *result = _Jv_GetStringChars (string);
1261 mark_for_gc (string, global_ref_table);
1262 if (isCopy)
1263 *isCopy = false;
1264 return (const jchar *) result;
1265}
1266
1267static void
1268(JNICALL _Jv_JNI_ReleaseStringChars) (JNIEnv *, jstring string, const jchar *)
1269{
1270 unmark_for_gc (unwrap (string), global_ref_table);
1271}
1272
1273static jstring
1274(JNICALL _Jv_JNI_NewStringUTF) (JNIEnv *env, const char *bytes)
1275{
1276 try
1277 {
1278 jstring result = JvNewStringUTF (bytes);
1279 return (jstring) wrap_value (env, result);
1280 }
1281 catch (jthrowable t)
1282 {
1283 env->ex = t;
1284 return NULL;
1285 }
1286}
1287
1288static jsize
1289(JNICALL _Jv_JNI_GetStringUTFLength) (JNIEnv *, jstring string)
1290{
1291 return JvGetStringUTFLength (unwrap (string));
1292}
1293
1294static const char *
1295(JNICALL _Jv_JNI_GetStringUTFChars) (JNIEnv *env, jstring string,
1296 jboolean *isCopy)
1297{
1298 string = unwrap (string);
1299 jsize len = JvGetStringUTFLength (string);
1300 try
1301 {
1302 char *r = (char *) _Jv_Malloc (len + 1);
1303 JvGetStringUTFRegion (string, 0, len, r);
1304 r[len] = '\0';
1305
1306 if (isCopy)
1307 *isCopy = true;
1308
1309 return (const char *) r;
1310 }
1311 catch (jthrowable t)
1312 {
1313 env->ex = t;
1314 return NULL;
1315 }
1316}
1317
1318static void
1319(JNICALL _Jv_JNI_ReleaseStringUTFChars) (JNIEnv *, jstring, const char *utf)
1320{
1321 _Jv_Free ((void *) utf);
1322}
1323
1324static void
1325(JNICALL _Jv_JNI_GetStringRegion) (JNIEnv *env, jstring string, jsize start,
1326 jsize len, jchar *buf)
1327{
1328 string = unwrap (string);
1329 jchar *result = _Jv_GetStringChars (string);
1330 if (start < 0 || start > string->length ()
1331 || len < 0 || start + len > string->length ())
1332 {
1333 try
1334 {
1335 env->ex = new java::lang::StringIndexOutOfBoundsException ();
1336 }
1337 catch (jthrowable t)
1338 {
1339 env->ex = t;
1340 }
1341 }
1342 else
1343 memcpy (buf, &result[start], len * sizeof (jchar));
1344}
1345
1346static void
1347(JNICALL _Jv_JNI_GetStringUTFRegion) (JNIEnv *env, jstring str, jsize start,
1348 jsize len, char *buf)
1349{
1350 str = unwrap (str);
1351
1352 if (start < 0 || start > str->length ()
1353 || len < 0 || start + len > str->length ())
1354 {
1355 try
1356 {
1357 env->ex = new java::lang::StringIndexOutOfBoundsException ();
1358 }
1359 catch (jthrowable t)
1360 {
1361 env->ex = t;
1362 }
1363 }
1364 else
1365 _Jv_GetStringUTFRegion (str, start, len, buf);
1366}
1367
1368static const jchar *
1369(JNICALL _Jv_JNI_GetStringCritical) (JNIEnv *, jstring str, jboolean *isCopy)
1370{
1371 jchar *result = _Jv_GetStringChars (unwrap (str));
1372 if (isCopy)
1373 *isCopy = false;
1374 return result;
1375}
1376
1377static void
1378(JNICALL _Jv_JNI_ReleaseStringCritical) (JNIEnv *, jstring, const jchar *)
1379{
1380 // Nothing.
1381}
1382
1383static jsize
1384(JNICALL _Jv_JNI_GetArrayLength) (JNIEnv *, jarray array)
1385{
1386 return unwrap (array)->length;
1387}
1388
1389static jarray
1390(JNICALL _Jv_JNI_NewObjectArray) (JNIEnv *env, jsize length,
1391 jclass elementClass, jobject init)
1392{
1393 try
1394 {
1395 elementClass = unwrap (elementClass);
1396 init = unwrap (init);
1397
1398 _Jv_CheckCast (elementClass, init);
1399 jarray result = JvNewObjectArray (length, elementClass, init);
1400 return (jarray) wrap_value (env, result);
1401 }
1402 catch (jthrowable t)
1403 {
1404 env->ex = t;
1405 return NULL;
1406 }
1407}
1408
1409static jobject
1410(JNICALL _Jv_JNI_GetObjectArrayElement) (JNIEnv *env, jobjectArray array,
1411 jsize index)
1412{
1413 if ((unsigned) index >= (unsigned) array->length)
1414 _Jv_ThrowBadArrayIndex (index);
1415 jobject *elts = elements (unwrap (array));
1416 return wrap_value (env, elts[index]);
1417}
1418
1419static void
1420(JNICALL _Jv_JNI_SetObjectArrayElement) (JNIEnv *env, jobjectArray array,
1421 jsize index, jobject value)
1422{
1423 try
1424 {
1425 array = unwrap (array);
1426 value = unwrap (value);
1427
1428 _Jv_CheckArrayStore (array, value);
1429 if ((unsigned) index >= (unsigned) array->length)
1430 _Jv_ThrowBadArrayIndex (index);
1431 jobject *elts = elements (array);
1432 elts[index] = value;
1433 }
1434 catch (jthrowable t)
1435 {
1436 env->ex = t;
1437 }
1438}
1439
1440template<typename T, jclass K>
1441static JArray<T> *
1442(JNICALL _Jv_JNI_NewPrimitiveArray) (JNIEnv *env, jsize length)
1443{
1444 try
1445 {
1446 return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
1447 }
1448 catch (jthrowable t)
1449 {
1450 env->ex = t;
1451 return NULL;
1452 }
1453}
1454
1455template<typename T>
1456static T *
1457(JNICALL _Jv_JNI_GetPrimitiveArrayElements) (JNIEnv *, JArray<T> *array,
1458 jboolean *isCopy)
1459{
1460 array = unwrap (array);
1461 T *elts = elements (array);
1462 if (isCopy)
1463 {
1464 // We elect never to copy.
1465 *isCopy = false;
1466 }
1467 mark_for_gc (array, global_ref_table);
1468 return elts;
1469}
1470
1471template<typename T>
1472static void
1473(JNICALL _Jv_JNI_ReleasePrimitiveArrayElements) (JNIEnv *, JArray<T> *array,
1474 T *, jint /* mode */)
1475{
1476 array = unwrap (array);
1477 // Note that we ignore MODE. We can do this because we never copy
1478 // the array elements. My reading of the JNI documentation is that
1479 // this is an option for the implementor.
1480 unmark_for_gc (array, global_ref_table);
1481}
1482
1483template<typename T>
1484static void
1485(JNICALL _Jv_JNI_GetPrimitiveArrayRegion) (JNIEnv *env, JArray<T> *array,
1486 jsize start, jsize len,
1487 T *buf)
1488{
1489 array = unwrap (array);
1490
1491 // The cast to unsigned lets us save a comparison.
1492 if (start < 0 || len < 0
1493 || (unsigned long) (start + len) > (unsigned long) array->length)
1494 {
1495 try
1496 {
1497 // FIXME: index.
1498 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1499 }
1500 catch (jthrowable t)
1501 {
1502 // Could have thown out of memory error.
1503 env->ex = t;
1504 }
1505 }
1506 else
1507 {
1508 T *elts = elements (array) + start;
1509 memcpy (buf, elts, len * sizeof (T));
1510 }
1511}
1512
1513template<typename T>
1514static void
1515(JNICALL _Jv_JNI_SetPrimitiveArrayRegion) (JNIEnv *env, JArray<T> *array,
1516 jsize start, jsize len, T *buf)
1517{
1518 array = unwrap (array);
1519
1520 // The cast to unsigned lets us save a comparison.
1521 if (start < 0 || len < 0
1522 || (unsigned long) (start + len) > (unsigned long) array->length)
1523 {
1524 try
1525 {
1526 // FIXME: index.
1527 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1528 }
1529 catch (jthrowable t)
1530 {
1531 env->ex = t;
1532 }
1533 }
1534 else
1535 {
1536 T *elts = elements (array) + start;
1537 memcpy (elts, buf, len * sizeof (T));
1538 }
1539}
1540
1541static void *
1542(JNICALL _Jv_JNI_GetPrimitiveArrayCritical) (JNIEnv *, jarray array,
1543 jboolean *isCopy)
1544{
1545 array = unwrap (array);
1546 // FIXME: does this work?
1547 jclass klass = array->getClass()->getComponentType();
1548 JvAssert (klass->isPrimitive ());
1549 char *r = _Jv_GetArrayElementFromElementType (array, klass);
1550 if (isCopy)
1551 *isCopy = false;
1552 return r;
1553}
1554
1555static void
1556(JNICALL _Jv_JNI_ReleasePrimitiveArrayCritical) (JNIEnv *, jarray, void *, jint)
1557{
1558 // Nothing.
1559}
1560
1561static jint
1562(JNICALL _Jv_JNI_MonitorEnter) (JNIEnv *env, jobject obj)
1563{
1564 try
1565 {
1566 _Jv_MonitorEnter (unwrap (obj));
1567 return 0;
1568 }
1569 catch (jthrowable t)
1570 {
1571 env->ex = t;
1572 }
1573 return JNI_ERR;
1574}
1575
1576static jint
1577(JNICALL _Jv_JNI_MonitorExit) (JNIEnv *env, jobject obj)
1578{
1579 try
1580 {
1581 _Jv_MonitorExit (unwrap (obj));
1582 return 0;
1583 }
1584 catch (jthrowable t)
1585 {
1586 env->ex = t;
1587 }
1588 return JNI_ERR;
1589}
1590
1591// JDK 1.2
1592jobject
1593(JNICALL _Jv_JNI_ToReflectedField) (JNIEnv *env, jclass cls, jfieldID fieldID,
1594 jboolean)
1595{
1596 try
1597 {
1598 cls = unwrap (cls);
1599 java::lang::reflect::Field *field = new java::lang::reflect::Field();
1600 field->declaringClass = cls;
1601 field->offset = (char*) fieldID - (char *) cls->fields;
1602 field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1603 return wrap_value (env, field);
1604 }
1605 catch (jthrowable t)
1606 {
1607 env->ex = t;
1608 }
1609 return NULL;
1610}
1611
1612// JDK 1.2
1613static jfieldID
1614(JNICALL _Jv_JNI_FromReflectedField) (JNIEnv *, jobject f)
1615{
1616 using namespace java::lang::reflect;
1617
1618 f = unwrap (f);
1619 Field *field = reinterpret_cast<Field *> (f);
1620 return _Jv_FromReflectedField (field);
1621}
1622
1623jobject
1624(JNICALL _Jv_JNI_ToReflectedMethod) (JNIEnv *env, jclass klass, jmethodID id,
1625 jboolean)
1626{
1627 using namespace java::lang::reflect;
1628
1629 jobject result = NULL;
1630 klass = unwrap (klass);
1631
1632 try
1633 {
1634 if (_Jv_equalUtf8Consts (id->name, init_name))
1635 {
1636 // A constructor.
1637 Constructor *cons = new Constructor ();
1638 cons->offset = (char *) id - (char *) &klass->methods;
1639 cons->declaringClass = klass;
1640 result = cons;
1641 }
1642 else
1643 {
1644 Method *meth = new Method ();
1645 meth->offset = (char *) id - (char *) &klass->methods;
1646 meth->declaringClass = klass;
1647 result = meth;
1648 }
1649 }
1650 catch (jthrowable t)
1651 {
1652 env->ex = t;
1653 }
1654
1655 return wrap_value (env, result);
1656}
1657
1658static jmethodID
1659(JNICALL _Jv_JNI_FromReflectedMethod) (JNIEnv *, jobject method)
1660{
1661 using namespace java::lang::reflect;
1662 method = unwrap (method);
1663 if (Method::class$.isInstance (method))
1664 return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1665 return
1666 _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1667}
1668
1669// JDK 1.2.
1670jweak
1671(JNICALL _Jv_JNI_NewWeakGlobalRef) (JNIEnv *env, jobject obj)
1672{
1673 using namespace gnu::gcj::runtime;
1674 JNIWeakRef *ref = NULL;
1675
1676 try
1677 {
1678 // This seems weird but I think it is correct.
1679 obj = unwrap (obj);
1680 ref = new JNIWeakRef (obj);
1681 mark_for_gc (ref, global_ref_table);
1682 }
1683 catch (jthrowable t)
1684 {
1685 env->ex = t;
1686 }
1687
1688 return reinterpret_cast<jweak> (ref);
1689}
1690
1691void
1692(JNICALL _Jv_JNI_DeleteWeakGlobalRef) (JNIEnv *, jweak obj)
1693{
1694 using namespace gnu::gcj::runtime;
1695 JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
1696 unmark_for_gc (ref, global_ref_table);
1697 ref->clear ();
1698}
1699
1700
1701
1702
1703// Direct byte buffers.
1704
1705static jobject
1706(JNICALL _Jv_JNI_NewDirectByteBuffer) (JNIEnv *, void *, jlong)
1707{
1708 // For now we don't support this.
1709 return NULL;
1710}
1711
1712static void *
1713(JNICALL _Jv_JNI_GetDirectBufferAddress) (JNIEnv *, jobject)
1714{
1715 // For now we don't support this.
1716 return NULL;
1717}
1718
1719static jlong
1720(JNICALL _Jv_JNI_GetDirectBufferCapacity) (JNIEnv *, jobject)
1721{
1722 // For now we don't support this.
1723 return -1;
1724}
1725
1726
1727
1728
1729// Hash table of native methods.
1730static JNINativeMethod *nathash;
1731// Number of slots used.
1732static int nathash_count = 0;
1733// Number of slots available. Must be power of 2.
1734static int nathash_size = 0;
1735
1736#define DELETED_ENTRY ((char *) (~0))
1737
1738// Compute a hash value for a native method descriptor.
1739static int
1740hash (const JNINativeMethod *method)
1741{
1742 char *ptr;
1743 int hash = 0;
1744
1745 ptr = method->name;
1746 while (*ptr)
1747 hash = (31 * hash) + *ptr++;
1748
1749 ptr = method->signature;
1750 while (*ptr)
1751 hash = (31 * hash) + *ptr++;
1752
1753 return hash;
1754}
1755
1756// Find the slot where a native method goes.
1757static JNINativeMethod *
1758nathash_find_slot (const JNINativeMethod *method)
1759{
1760 jint h = hash (method);
1761 int step = (h ^ (h >> 16)) | 1;
1762 int w = h & (nathash_size - 1);
1763 int del = -1;
1764
1765 for (;;)
1766 {
1767 JNINativeMethod *slotp = &nathash[w];
1768 if (slotp->name == NULL)
1769 {
1770 if (del >= 0)
1771 return &nathash[del];
1772 else
1773 return slotp;
1774 }
1775 else if (slotp->name == DELETED_ENTRY)
1776 del = w;
1777 else if (! strcmp (slotp->name, method->name)
1778 && ! strcmp (slotp->signature, method->signature))
1779 return slotp;
1780 w = (w + step) & (nathash_size - 1);
1781 }
1782}
1783
1784// Find a method. Return NULL if it isn't in the hash table.
1785static void *
1786nathash_find (JNINativeMethod *method)
1787{
1788 if (nathash == NULL)
1789 return NULL;
1790 JNINativeMethod *slot = nathash_find_slot (method);
1791 if (slot->name == NULL || slot->name == DELETED_ENTRY)
1792 return NULL;
1793 return slot->fnPtr;
1794}
1795
1796static void
1797natrehash ()
1798{
1799 if (nathash == NULL)
1800 {
1801 nathash_size = 1024;
1802 nathash =
1803 (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1804 * sizeof (JNINativeMethod));
1805 memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1806 }
1807 else
1808 {
1809 int savesize = nathash_size;
1810 JNINativeMethod *savehash = nathash;
1811 nathash_size *= 2;
1812 nathash =
1813 (JNINativeMethod *) _Jv_AllocBytes (nathash_size
1814 * sizeof (JNINativeMethod));
1815 memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
1816
1817 for (int i = 0; i < savesize; ++i)
1818 {
1819 if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
1820 {
1821 JNINativeMethod *slot = nathash_find_slot (&savehash[i]);
1822 *slot = savehash[i];
1823 }
1824 }
1825 }
1826}
1827
1828static void
1829nathash_add (const JNINativeMethod *method)
1830{
1831 if (3 * nathash_count >= 2 * nathash_size)
1832 natrehash ();
1833 JNINativeMethod *slot = nathash_find_slot (method);
1834 // If the slot has a real entry in it, then there is no work to do.
1835 if (slot->name != NULL && slot->name != DELETED_ENTRY)
1836 return;
1837 // FIXME
1838 slot->name = strdup (method->name);
1839 slot->signature = strdup (method->signature);
1840 slot->fnPtr = method->fnPtr;
1841}
1842
1843static jint
1844(JNICALL _Jv_JNI_RegisterNatives) (JNIEnv *env, jclass klass,
1845 const JNINativeMethod *methods,
1846 jint nMethods)
1847{
1848 // Synchronize while we do the work. This must match
1849 // synchronization in some other functions that manipulate or use
1850 // the nathash table.
1851 JvSynchronize sync (global_ref_table);
1852
1853 // Look at each descriptor given us, and find the corresponding
1854 // method in the class.
1855 for (int j = 0; j < nMethods; ++j)
1856 {
1857 bool found = false;
1858
1859 _Jv_Method *imeths = JvGetFirstMethod (klass);
1860 for (int i = 0; i < JvNumMethods (klass); ++i)
1861 {
1862 _Jv_Method *self = &imeths[i];
1863
1864 if (! strcmp (self->name->data, methods[j].name)
1865 && ! strcmp (self->signature->data, methods[j].signature))
1866 {
1867 if (! (self->accflags
1868 & java::lang::reflect::Modifier::NATIVE))
1869 break;
1870
1871 // Found a match that is native.
1872 found = true;
1873 nathash_add (&methods[j]);
1874
1875 break;
1876 }
1877 }
1878
1879 if (! found)
1880 {
1881 jstring m = JvNewStringUTF (methods[j].name);
1882 try
1883 {
1884 env->ex =new java::lang::NoSuchMethodError (m);
1885 }
1886 catch (jthrowable t)
1887 {
1888 env->ex = t;
1889 }
1890 return JNI_ERR;
1891 }
1892 }
1893
1894 return JNI_OK;
1895}
1896
1897static jint
1898(JNICALL _Jv_JNI_UnregisterNatives) (JNIEnv *, jclass)
1899{
1900 // FIXME -- we could implement this.
1901 return JNI_ERR;
1902}
1903
1904
1905
1906
1907// Add a character to the buffer, encoding properly.
1908static void
1909add_char (char *buf, jchar c, int *here)
1910{
1911 if (c == '_')
1912 {
1913 buf[(*here)++] = '_';
1914 buf[(*here)++] = '1';
1915 }
1916 else if (c == ';')
1917 {
1918 buf[(*here)++] = '_';
1919 buf[(*here)++] = '2';
1920 }
1921 else if (c == '[')
1922 {
1923 buf[(*here)++] = '_';
1924 buf[(*here)++] = '3';
1925 }
1926
1927 // Also check for `.' here because we might be passed an internal
1928 // qualified class name like `foo.bar'.
1929 else if (c == '/' || c == '.')
1930 buf[(*here)++] = '_';
1931 else if ((c >= '0' && c <= '9')
1932 || (c >= 'a' && c <= 'z')
1933 || (c >= 'A' && c <= 'Z'))
1934 buf[(*here)++] = (char) c;
1935 else
1936 {
1937 // "Unicode" character.
1938 buf[(*here)++] = '_';
1939 buf[(*here)++] = '0';
1940 for (int i = 0; i < 4; ++i)
1941 {
1942 int val = c & 0x0f;
1943 buf[(*here) + 3 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
1944 c >>= 4;
1945 }
1946 *here += 4;
1947 }
1948}
1949
1950// Compute a mangled name for a native function. This computes the
1951// long name, and also returns an index which indicates where a NUL
1952// can be placed to create the short name. This function assumes that
1953// the buffer is large enough for its results.
1954static void
1955mangled_name (jclass klass, _Jv_Utf8Const *func_name,
1956 _Jv_Utf8Const *signature, char *buf, int *long_start)
1957{
1958 strcpy (buf, "Java_");
1959 int here = 5;
1960
1961 // Add fully qualified class name.
1962 jchar *chars = _Jv_GetStringChars (klass->getName ());
1963 jint len = klass->getName ()->length ();
1964 for (int i = 0; i < len; ++i)
1965 add_char (buf, chars[i], &here);
1966
1967 // Don't use add_char because we need a literal `_'.
1968 buf[here++] = '_';
1969
1970 const unsigned char *fn = (const unsigned char *) func_name->data;
1971 const unsigned char *limit = fn + func_name->length;
1972 for (int i = 0; ; ++i)
1973 {
1974 int ch = UTF8_GET (fn, limit);
1975 if (ch < 0)
1976 break;
1977 add_char (buf, ch, &here);
1978 }
1979
1980 // This is where the long signature begins.
1981 *long_start = here;
1982 buf[here++] = '_';
1983 buf[here++] = '_';
1984
1985 const unsigned char *sig = (const unsigned char *) signature->data;
1986 limit = sig + signature->length;
1987 JvAssert (sig[0] == '(');
1988 ++sig;
1989 while (1)
1990 {
1991 int ch = UTF8_GET (sig, limit);
1992 if (ch == ')' || ch < 0)
1993 break;
1994 add_char (buf, ch, &here);
1995 }
1996
1997 buf[here] = '\0';
1998}
1999
2000// Return the current thread's JNIEnv; if one does not exist, create
2001// it. Also create a new system frame for use. This is `extern "C"'
2002// because the compiler calls it.
2003extern "C" JNIEnv *
2004_Jv_GetJNIEnvNewFrame (jclass klass)
2005{
2006 JNIEnv *env = _Jv_GetCurrentJNIEnv ();
2007 if (env == NULL)
2008 {
2009 env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
2010 env->p = &_Jv_JNIFunctions;
2011 env->klass = klass;
2012 env->locals = NULL;
2013 // We set env->ex below.
2014
2015 _Jv_SetCurrentJNIEnv (env);
2016 }
2017
2018 _Jv_JNI_LocalFrame *frame
2019 = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2020 + (FRAME_SIZE
2021 * sizeof (jobject)));
2022
2023 frame->marker = MARK_SYSTEM;
2024 frame->size = FRAME_SIZE;
2025 frame->next = env->locals;
2026
2027 for (int i = 0; i < frame->size; ++i)
2028 frame->vec[i] = NULL;
2029
2030 env->locals = frame;
2031 env->ex = NULL;
2032
2033 return env;
2034}
2035
2036// Return the function which implements a particular JNI method. If
2037// we can't find the function, we throw the appropriate exception.
2038// This is `extern "C"' because the compiler uses it.
2039extern "C" void *
2040_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
2041 _Jv_Utf8Const *signature, int args_size)
2042{
2043 char buf[10 + 6 * (name->length + signature->length) + 12];
2044 int long_start;
2045 void *function;
2046
2047 // Synchronize on something convenient. Right now we use the hash.
2048 JvSynchronize sync (global_ref_table);
2049
2050 // First see if we have an override in the hash table.
2051 strncpy (buf, name->data, name->length);
2052 buf[name->length] = '\0';
2053 strncpy (buf + name->length + 1, signature->data, signature->length);
2054 buf[name->length + signature->length + 1] = '\0';
2055 JNINativeMethod meth;
2056 meth.name = buf;
2057 meth.signature = buf + name->length + 1;
2058 function = nathash_find (&meth);
2059 if (function != NULL)
2060 return function;
2061
2062 // If there was no override, then look in the symbol table.
2063 buf[0] = '_';
2064 mangled_name (klass, name, signature, buf + 1, &long_start);
2065 char c = buf[long_start + 1];
2066 buf[long_start + 1] = '\0';
2067
2068 function = _Jv_FindSymbolInExecutable (buf + 1);
2069#ifdef WIN32
2070 // On Win32, we use the "stdcall" calling convention (see JNICALL
2071 // in jni.h).
2072 //
2073 // For a function named 'fooBar' that takes 'nn' bytes as arguments,
2074 // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it
2075 // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to
2076 // take care of all these variations here.
2077
2078 char asz_buf[12]; /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
2079 char long_nm_sv[11]; /* Ditto, except for the '\0'. */
2080
2081 if (function == NULL)
2082 {
2083 // We have tried searching for the 'fooBar' form (BCC) - now
2084 // try the others.
2085
2086 // First, save the part of the long name that will be damaged
2087 // by appending '@nn'.
2088 memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
2089
2090 sprintf (asz_buf, "@%d", args_size);
2091 strcat (buf, asz_buf);
2092
2093 // Search for the '_fooBar@nn' form (MSVC).
2094 function = _Jv_FindSymbolInExecutable (buf);
2095
2096 if (function == NULL)
2097 {
2098 // Search for the 'fooBar@nn' form (MinGW GCC).
2099 function = _Jv_FindSymbolInExecutable (buf + 1);
2100 }
2101 }
2102#else /* WIN32 */
2103 args_size; /* Dummy statement to avoid unused parameter warning */
2104#endif /* ! WIN32 */
2105
2106 if (function == NULL)
2107 {
2108 buf[long_start + 1] = c;
2109#ifdef WIN32
2110 // Restore the part of the long name that was damaged by
2111 // appending the '@nn'.
2112 memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
2113#endif /* WIN32 */
2114 function = _Jv_FindSymbolInExecutable (buf + 1);
2115 if (function == NULL)
2116 {
2117#ifdef WIN32
2118 strcat (buf, asz_buf);
2119 function = _Jv_FindSymbolInExecutable (buf);
2120 if (function == NULL)
2121 function = _Jv_FindSymbolInExecutable (buf + 1);
2122
2123 if (function == NULL)
2124#endif /* WIN32 */
2125 {
2126 jstring str = JvNewStringUTF (name->data);
2127 throw new java::lang::UnsatisfiedLinkError (str);
2128 }
2129 }
2130 }
2131
2132 return function;
2133}
2134
2135#ifdef INTERPRETER
2136
2137// This function is the stub which is used to turn an ordinary (CNI)
2138// method call into a JNI call.
2139void
2140_Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this)
2141{
2142 _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
2143
2144 JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class);
2145
2146 // FIXME: we should mark every reference parameter as a local. For
2147 // now we assume a conservative GC, and we assume that the
2148 // references are on the stack somewhere.
2149
2150 // We cache the value that we find, of course, but if we don't find
2151 // a value we don't cache that fact -- we might subsequently load a
2152 // library which finds the function in question.
2153 {
2154 // Synchronize on a convenient object to ensure sanity in case two
2155 // threads reach this point for the same function at the same
2156 // time.
2157 JvSynchronize sync (global_ref_table);
2158 if (_this->function == NULL)
2159 {
2160 int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
2161
2162 if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
2163 args_size += sizeof (_this->defining_class);
2164
2165 _this->function = _Jv_LookupJNIMethod (_this->defining_class,
2166 _this->self->name,
2167 _this->self->signature,
2168 args_size);
2169 }
2170 }
2171
2172 JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0);
2173 ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)];
2174 int offset = 0;
2175
2176 // First argument is always the environment pointer.
2177 real_args[offset++].ptr = env;
2178
2179 // For a static method, we pass in the Class. For non-static
2180 // methods, the `this' argument is already handled.
2181 if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2182 real_args[offset++].ptr = _this->defining_class;
2183
2184 // In libgcj, the callee synchronizes.
2185 jobject sync = NULL;
2186 if ((_this->self->accflags & java::lang::reflect::Modifier::SYNCHRONIZED))
2187 {
2188 if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
2189 sync = _this->defining_class;
2190 else
2191 sync = (jobject) args[0].ptr;
2192 _Jv_MonitorEnter (sync);
2193 }
2194
2195 // Copy over passed-in arguments.
2196 memcpy (&real_args[offset], args, _this->args_raw_size);
2197
2198 // The actual call to the JNI function.
2199 ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
2200 ret, real_args);
2201
2202 if (sync != NULL)
2203 _Jv_MonitorExit (sync);
2204
2205 _Jv_JNI_PopSystemFrame (env);
2206}
2207
2208#endif /* INTERPRETER */
2209
2210
2211
2212
2213//
2214// Invocation API.
2215//
2216
2217// An internal helper function.
2218static jint
2219_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
2220 void *args, jboolean is_daemon)
2221{
2222 JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (args);
2223 java::lang::ThreadGroup *group = NULL;
2224
2225 if (attach)
2226 {
2227 // FIXME: do we really want to support 1.1?
2228 if (attach->version != JNI_VERSION_1_4
2229 && attach->version != JNI_VERSION_1_2
2230 && attach->version != JNI_VERSION_1_1)
2231 return JNI_EVERSION;
2232
2233 JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
2234 group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
2235 }
2236
2237 // Attaching an already-attached thread is a no-op.
2238 if (_Jv_GetCurrentJNIEnv () != NULL)
2239 return 0;
2240
2241 JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
2242 if (env == NULL)
2243 return JNI_ERR;
2244 env->p = &_Jv_JNIFunctions;
2245 env->ex = NULL;
2246 env->klass = NULL;
2247 env->locals
2248 = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
2249 + (FRAME_SIZE
2250 * sizeof (jobject)));
2251 if (env->locals == NULL)
2252 {
2253 _Jv_Free (env);
2254 return JNI_ERR;
2255 }
2256
2257 env->locals->marker = MARK_SYSTEM;
2258 env->locals->size = FRAME_SIZE;
2259 env->locals->next = NULL;
2260
2261 for (int i = 0; i < env->locals->size; ++i)
2262 env->locals->vec[i] = NULL;
2263
2264 *penv = reinterpret_cast<void *> (env);
2265
2266 // This thread might already be a Java thread -- this function might
2267 // have been called simply to set the new JNIEnv.
2268 if (_Jv_ThreadCurrent () == NULL)
2269 {
2270 try
2271 {
2272 if (is_daemon)
2273 _Jv_AttachCurrentThreadAsDaemon (name, group);
2274 else
2275 _Jv_AttachCurrentThread (name, group);
2276 }
2277 catch (jthrowable t)
2278 {
2279 return JNI_ERR;
2280 }
2281 }
2282 _Jv_SetCurrentJNIEnv (env);
2283
2284 return 0;
2285}
2286
2287// This is the one actually used by JNI.
2288static jint
2289(JNICALL _Jv_JNI_AttachCurrentThread) (JavaVM *vm, void **penv, void *args)
2290{
2291 return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, false);
2292}
2293
2294static jint
2295(JNICALL _Jv_JNI_AttachCurrentThreadAsDaemon) (JavaVM *vm, void **penv,
2296 void *args)
2297{
2298 return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, true);
2299}
2300
2301static jint
2302(JNICALL _Jv_JNI_DestroyJavaVM) (JavaVM *vm)
2303{
2304 JvAssert (the_vm && vm == the_vm);
2305
2306 JNIEnv *env;
2307 if (_Jv_ThreadCurrent () != NULL)
2308 {
2309 jstring main_name;
2310 // This sucks.
2311 try
2312 {
2313 main_name = JvNewStringLatin1 ("main");
2314 }
2315 catch (jthrowable t)
2316 {
2317 return JNI_ERR;
2318 }
2319
2320 jint r = _Jv_JNI_AttachCurrentThread (vm, main_name,
2321 reinterpret_cast<void **> (&env),
2322 NULL, false);
2323 if (r < 0)
2324 return r;
2325 }
2326 else
2327 env = _Jv_GetCurrentJNIEnv ();
2328
2329 _Jv_ThreadWait ();
2330
2331 // Docs say that this always returns an error code.
2332 return JNI_ERR;
2333}
2334
2335jint
2336(JNICALL _Jv_JNI_DetachCurrentThread) (JavaVM *)
2337{
2338 jint code = _Jv_DetachCurrentThread ();
2339 return code ? JNI_EDETACHED : 0;
2340}
2341
2342static jint
2343(JNICALL _Jv_JNI_GetEnv) (JavaVM *, void **penv, jint version)
2344{
2345 if (_Jv_ThreadCurrent () == NULL)
2346 {
2347 *penv = NULL;
2348 return JNI_EDETACHED;
2349 }
2350
2351#ifdef ENABLE_JVMPI
2352 // Handle JVMPI requests.
2353 if (version == JVMPI_VERSION_1)
2354 {
2355 *penv = (void *) &_Jv_JVMPI_Interface;
2356 return 0;
2357 }
2358#endif
2359
2360 // FIXME: do we really want to support 1.1?
2361 if (version != JNI_VERSION_1_4 && version != JNI_VERSION_1_2
2362 && version != JNI_VERSION_1_1)
2363 {
2364 *penv = NULL;
2365 return JNI_EVERSION;
2366 }
2367
2368 *penv = (void *) _Jv_GetCurrentJNIEnv ();
2369 return 0;
2370}
2371
2372JNIEXPORT jint JNICALL
2373JNI_GetDefaultJavaVMInitArgs (void *args)
2374{
2375 jint version = * (jint *) args;
2376 // Here we only support 1.2 and 1.4.
2377 if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
2378 return JNI_EVERSION;
2379
2380 JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2381 ia->version = JNI_VERSION_1_4;
2382 ia->nOptions = 0;
2383 ia->options = NULL;
2384 ia->ignoreUnrecognized = true;
2385
2386 return 0;
2387}
2388
2389JNIEXPORT jint JNICALL
2390JNI_CreateJavaVM (JavaVM **vm, void **penv, void *args)
2391{
2392 JvAssert (! the_vm);
2393
2394 _Jv_CreateJavaVM (NULL);
2395
2396 // FIXME: synchronize
2397 JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2398 if (nvm == NULL)
2399 return JNI_ERR;
2400 nvm->functions = &_Jv_JNI_InvokeFunctions;
2401
2402 // Parse the arguments.
2403 if (args != NULL)
2404 {
2405 jint version = * (jint *) args;
2406 // We only support 1.2 and 1.4.
2407 if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4)
2408 return JNI_EVERSION;
2409 JavaVMInitArgs *ia = reinterpret_cast<JavaVMInitArgs *> (args);
2410 for (int i = 0; i < ia->nOptions; ++i)
2411 {
2412 if (! strcmp (ia->options[i].optionString, "vfprintf")
2413 || ! strcmp (ia->options[i].optionString, "exit")
2414 || ! strcmp (ia->options[i].optionString, "abort"))
2415 {
2416 // We are required to recognize these, but for now we
2417 // don't handle them in any way. FIXME.
2418 continue;
2419 }
2420 else if (! strncmp (ia->options[i].optionString,
2421 "-verbose", sizeof ("-verbose") - 1))
2422 {
2423 // We don't do anything with this option either. We
2424 // might want to make sure the argument is valid, but we
2425 // don't really care all that much for now.
2426 continue;
2427 }
2428 else if (! strncmp (ia->options[i].optionString, "-D", 2))
2429 {
2430 // FIXME.
2431 continue;
2432 }
2433 else if (ia->ignoreUnrecognized)
2434 {
2435 if (ia->options[i].optionString[0] == '_'
2436 || ! strncmp (ia->options[i].optionString, "-X", 2))
2437 continue;
2438 }
2439
2440 return JNI_ERR;
2441 }
2442 }
2443
2444 jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL);
2445 if (r < 0)
2446 return r;
2447
2448 the_vm = nvm;
2449 *vm = the_vm;
2450
2451 return 0;
2452}
2453
2454JNIEXPORT jint JNICALL
2455JNI_GetCreatedJavaVMs (JavaVM **vm_buffer, jsize buf_len, jsize *n_vms)
2456{
2457 if (buf_len <= 0)
2458 return JNI_ERR;
2459
2460 // We only support a single VM.
2461 if (the_vm != NULL)
2462 {
2463 vm_buffer[0] = the_vm;
2464 *n_vms = 1;
2465 }
2466 else
2467 *n_vms = 0;
2468 return 0;
2469}
2470
2471JavaVM *
2472_Jv_GetJavaVM ()
2473{
2474 // FIXME: synchronize
2475 if (! the_vm)
2476 {
2477 JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
2478 if (nvm != NULL)
2479 nvm->functions = &_Jv_JNI_InvokeFunctions;
2480 the_vm = nvm;
2481 }
2482
2483 // If this is a Java thread, we want to make sure it has an
2484 // associated JNIEnv.
2485 if (_Jv_ThreadCurrent () != NULL)
2486 {
2487 void *ignore;
2488 _Jv_JNI_AttachCurrentThread (the_vm, &ignore, NULL);
2489 }
2490
2491 return the_vm;
2492}
2493
2494static jint
2495(JNICALL _Jv_JNI_GetJavaVM) (JNIEnv *, JavaVM **vm)
2496{
2497 *vm = _Jv_GetJavaVM ();
2498 return *vm == NULL ? JNI_ERR : JNI_OK;
2499}
2500
2501
2502
2503
2504#define RESERVED NULL
2505
2506struct JNINativeInterface _Jv_JNIFunctions =
2507{
2508 RESERVED,
2509 RESERVED,
2510 RESERVED,
2511 RESERVED,
2512 _Jv_JNI_GetVersion, // GetVersion
2513 _Jv_JNI_DefineClass, // DefineClass
2514 _Jv_JNI_FindClass, // FindClass
2515 _Jv_JNI_FromReflectedMethod, // FromReflectedMethod
2516 _Jv_JNI_FromReflectedField, // FromReflectedField
2517 _Jv_JNI_ToReflectedMethod, // ToReflectedMethod
2518 _Jv_JNI_GetSuperclass, // GetSuperclass
2519 _Jv_JNI_IsAssignableFrom, // IsAssignableFrom
2520 _Jv_JNI_ToReflectedField, // ToReflectedField
2521 _Jv_JNI_Throw, // Throw
2522 _Jv_JNI_ThrowNew, // ThrowNew
2523 _Jv_JNI_ExceptionOccurred, // ExceptionOccurred
2524 _Jv_JNI_ExceptionDescribe, // ExceptionDescribe
2525 _Jv_JNI_ExceptionClear, // ExceptionClear
2526 _Jv_JNI_FatalError, // FatalError
2527
2528 _Jv_JNI_PushLocalFrame, // PushLocalFrame
2529 _Jv_JNI_PopLocalFrame, // PopLocalFrame
2530 _Jv_JNI_NewGlobalRef, // NewGlobalRef
2531 _Jv_JNI_DeleteGlobalRef, // DeleteGlobalRef
2532 _Jv_JNI_DeleteLocalRef, // DeleteLocalRef
2533
2534 _Jv_JNI_IsSameObject, // IsSameObject
2535
2536 _Jv_JNI_NewLocalRef, // NewLocalRef
2537 _Jv_JNI_EnsureLocalCapacity, // EnsureLocalCapacity
2538
2539 _Jv_JNI_AllocObject, // AllocObject
2540 _Jv_JNI_NewObject, // NewObject
2541 _Jv_JNI_NewObjectV, // NewObjectV
2542 _Jv_JNI_NewObjectA, // NewObjectA
2543 _Jv_JNI_GetObjectClass, // GetObjectClass
2544 _Jv_JNI_IsInstanceOf, // IsInstanceOf
2545 _Jv_JNI_GetAnyMethodID<false>, // GetMethodID
2546
2547 _Jv_JNI_CallMethod<jobject>, // CallObjectMethod
2548 _Jv_JNI_CallMethodV<jobject>, // CallObjectMethodV
2549 _Jv_JNI_CallMethodA<jobject>, // CallObjectMethodA
2550 _Jv_JNI_CallMethod<jboolean>, // CallBooleanMethod
2551 _Jv_JNI_CallMethodV<jboolean>, // CallBooleanMethodV
2552 _Jv_JNI_CallMethodA<jboolean>, // CallBooleanMethodA
2553 _Jv_JNI_CallMethod<jbyte>, // CallByteMethod
2554 _Jv_JNI_CallMethodV<jbyte>, // CallByteMethodV
2555 _Jv_JNI_CallMethodA<jbyte>, // CallByteMethodA
2556 _Jv_JNI_CallMethod<jchar>, // CallCharMethod
2557 _Jv_JNI_CallMethodV<jchar>, // CallCharMethodV
2558 _Jv_JNI_CallMethodA<jchar>, // CallCharMethodA
2559 _Jv_JNI_CallMethod<jshort>, // CallShortMethod
2560 _Jv_JNI_CallMethodV<jshort>, // CallShortMethodV
2561 _Jv_JNI_CallMethodA<jshort>, // CallShortMethodA
2562 _Jv_JNI_CallMethod<jint>, // CallIntMethod
2563 _Jv_JNI_CallMethodV<jint>, // CallIntMethodV
2564 _Jv_JNI_CallMethodA<jint>, // CallIntMethodA
2565 _Jv_JNI_CallMethod<jlong>, // CallLongMethod
2566 _Jv_JNI_CallMethodV<jlong>, // CallLongMethodV
2567 _Jv_JNI_CallMethodA<jlong>, // CallLongMethodA
2568 _Jv_JNI_CallMethod<jfloat>, // CallFloatMethod
2569 _Jv_JNI_CallMethodV<jfloat>, // CallFloatMethodV
2570 _Jv_JNI_CallMethodA<jfloat>, // CallFloatMethodA
2571 _Jv_JNI_CallMethod<jdouble>, // CallDoubleMethod
2572 _Jv_JNI_CallMethodV<jdouble>, // CallDoubleMethodV
2573 _Jv_JNI_CallMethodA<jdouble>, // CallDoubleMethodA
2574 _Jv_JNI_CallVoidMethod, // CallVoidMethod
2575 _Jv_JNI_CallVoidMethodV, // CallVoidMethodV
2576 _Jv_JNI_CallVoidMethodA, // CallVoidMethodA
2577
2578 // Nonvirtual method invocation functions follow.
2579 _Jv_JNI_CallAnyMethod<jobject, nonvirtual>, // CallNonvirtualObjectMethod
2580 _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>, // CallNonvirtualObjectMethodV
2581 _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>, // CallNonvirtualObjectMethodA
2582 _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>, // CallNonvirtualBooleanMethod
2583 _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodV
2584 _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodA
2585 _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>, // CallNonvirtualByteMethod
2586 _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>, // CallNonvirtualByteMethodV
2587 _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>, // CallNonvirtualByteMethodA
2588 _Jv_JNI_CallAnyMethod<jchar, nonvirtual>, // CallNonvirtualCharMethod
2589 _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>, // CallNonvirtualCharMethodV
2590 _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>, // CallNonvirtualCharMethodA
2591 _Jv_JNI_CallAnyMethod<jshort, nonvirtual>, // CallNonvirtualShortMethod
2592 _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>, // CallNonvirtualShortMethodV
2593 _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>, // CallNonvirtualShortMethodA
2594 _Jv_JNI_CallAnyMethod<jint, nonvirtual>, // CallNonvirtualIntMethod
2595 _Jv_JNI_CallAnyMethodV<jint, nonvirtual>, // CallNonvirtualIntMethodV
2596 _Jv_JNI_CallAnyMethodA<jint, nonvirtual>, // CallNonvirtualIntMethodA
2597 _Jv_JNI_CallAnyMethod<jlong, nonvirtual>, // CallNonvirtualLongMethod
2598 _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>, // CallNonvirtualLongMethodV
2599 _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>, // CallNonvirtualLongMethodA
2600 _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>, // CallNonvirtualFloatMethod
2601 _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>, // CallNonvirtualFloatMethodV
2602 _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>, // CallNonvirtualFloatMethodA
2603 _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>, // CallNonvirtualDoubleMethod
2604 _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>, // CallNonvirtualDoubleMethodV
2605 _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>, // CallNonvirtualDoubleMethodA
2606 _Jv_JNI_CallAnyVoidMethod<nonvirtual>, // CallNonvirtualVoidMethod
2607 _Jv_JNI_CallAnyVoidMethodV<nonvirtual>, // CallNonvirtualVoidMethodV
2608 _Jv_JNI_CallAnyVoidMethodA<nonvirtual>, // CallNonvirtualVoidMethodA
2609
2610 _Jv_JNI_GetAnyFieldID<false>, // GetFieldID
2611 _Jv_JNI_GetField<jobject>, // GetObjectField
2612 _Jv_JNI_GetField<jboolean>, // GetBooleanField
2613 _Jv_JNI_GetField<jbyte>, // GetByteField
2614 _Jv_JNI_GetField<jchar>, // GetCharField
2615 _Jv_JNI_GetField<jshort>, // GetShortField
2616 _Jv_JNI_GetField<jint>, // GetIntField
2617 _Jv_JNI_GetField<jlong>, // GetLongField
2618 _Jv_JNI_GetField<jfloat>, // GetFloatField
2619 _Jv_JNI_GetField<jdouble>, // GetDoubleField
2620 _Jv_JNI_SetField, // SetObjectField
2621 _Jv_JNI_SetField, // SetBooleanField
2622 _Jv_JNI_SetField, // SetByteField
2623 _Jv_JNI_SetField, // SetCharField
2624 _Jv_JNI_SetField, // SetShortField
2625 _Jv_JNI_SetField, // SetIntField
2626 _Jv_JNI_SetField, // SetLongField
2627 _Jv_JNI_SetField, // SetFloatField
2628 _Jv_JNI_SetField, // SetDoubleField
2629 _Jv_JNI_GetAnyMethodID<true>, // GetStaticMethodID
2630
2631 _Jv_JNI_CallStaticMethod<jobject>, // CallStaticObjectMethod
2632 _Jv_JNI_CallStaticMethodV<jobject>, // CallStaticObjectMethodV
2633 _Jv_JNI_CallStaticMethodA<jobject>, // CallStaticObjectMethodA
2634 _Jv_JNI_CallStaticMethod<jboolean>, // CallStaticBooleanMethod
2635 _Jv_JNI_CallStaticMethodV<jboolean>, // CallStaticBooleanMethodV
2636 _Jv_JNI_CallStaticMethodA<jboolean>, // CallStaticBooleanMethodA
2637 _Jv_JNI_CallStaticMethod<jbyte>, // CallStaticByteMethod
2638 _Jv_JNI_CallStaticMethodV<jbyte>, // CallStaticByteMethodV
2639 _Jv_JNI_CallStaticMethodA<jbyte>, // CallStaticByteMethodA
2640 _Jv_JNI_CallStaticMethod<jchar>, // CallStaticCharMethod
2641 _Jv_JNI_CallStaticMethodV<jchar>, // CallStaticCharMethodV
2642 _Jv_JNI_CallStaticMethodA<jchar>, // CallStaticCharMethodA
2643 _Jv_JNI_CallStaticMethod<jshort>, // CallStaticShortMethod
2644 _Jv_JNI_CallStaticMethodV<jshort>, // CallStaticShortMethodV
2645 _Jv_JNI_CallStaticMethodA<jshort>, // CallStaticShortMethodA
2646 _Jv_JNI_CallStaticMethod<jint>, // CallStaticIntMethod
2647 _Jv_JNI_CallStaticMethodV<jint>, // CallStaticIntMethodV
2648 _Jv_JNI_CallStaticMethodA<jint>, // CallStaticIntMethodA
2649 _Jv_JNI_CallStaticMethod<jlong>, // CallStaticLongMethod
2650 _Jv_JNI_CallStaticMethodV<jlong>, // CallStaticLongMethodV
2651 _Jv_JNI_CallStaticMethodA<jlong>, // CallStaticLongMethodA
2652 _Jv_JNI_CallStaticMethod<jfloat>, // CallStaticFloatMethod
2653 _Jv_JNI_CallStaticMethodV<jfloat>, // CallStaticFloatMethodV
2654 _Jv_JNI_CallStaticMethodA<jfloat>, // CallStaticFloatMethodA
2655 _Jv_JNI_CallStaticMethod<jdouble>, // CallStaticDoubleMethod
2656 _Jv_JNI_CallStaticMethodV<jdouble>, // CallStaticDoubleMethodV
2657 _Jv_JNI_CallStaticMethodA<jdouble>, // CallStaticDoubleMethodA
2658 _Jv_JNI_CallStaticVoidMethod, // CallStaticVoidMethod
2659 _Jv_JNI_CallStaticVoidMethodV, // CallStaticVoidMethodV
2660 _Jv_JNI_CallStaticVoidMethodA, // CallStaticVoidMethodA
2661
2662 _Jv_JNI_GetAnyFieldID<true>, // GetStaticFieldID
2663 _Jv_JNI_GetStaticField<jobject>, // GetStaticObjectField
2664 _Jv_JNI_GetStaticField<jboolean>, // GetStaticBooleanField
2665 _Jv_JNI_GetStaticField<jbyte>, // GetStaticByteField
2666 _Jv_JNI_GetStaticField<jchar>, // GetStaticCharField
2667 _Jv_JNI_GetStaticField<jshort>, // GetStaticShortField
2668 _Jv_JNI_GetStaticField<jint>, // GetStaticIntField
2669 _Jv_JNI_GetStaticField<jlong>, // GetStaticLongField
2670 _Jv_JNI_GetStaticField<jfloat>, // GetStaticFloatField
2671 _Jv_JNI_GetStaticField<jdouble>, // GetStaticDoubleField
2672 _Jv_JNI_SetStaticField, // SetStaticObjectField
2673 _Jv_JNI_SetStaticField, // SetStaticBooleanField
2674 _Jv_JNI_SetStaticField, // SetStaticByteField
2675 _Jv_JNI_SetStaticField, // SetStaticCharField
2676 _Jv_JNI_SetStaticField, // SetStaticShortField
2677 _Jv_JNI_SetStaticField, // SetStaticIntField
2678 _Jv_JNI_SetStaticField, // SetStaticLongField
2679 _Jv_JNI_SetStaticField, // SetStaticFloatField
2680 _Jv_JNI_SetStaticField, // SetStaticDoubleField
2681 _Jv_JNI_NewString, // NewString
2682 _Jv_JNI_GetStringLength, // GetStringLength
2683 _Jv_JNI_GetStringChars, // GetStringChars
2684 _Jv_JNI_ReleaseStringChars, // ReleaseStringChars
2685 _Jv_JNI_NewStringUTF, // NewStringUTF
2686 _Jv_JNI_GetStringUTFLength, // GetStringUTFLength
2687 _Jv_JNI_GetStringUTFChars, // GetStringUTFChars
2688 _Jv_JNI_ReleaseStringUTFChars, // ReleaseStringUTFChars
2689 _Jv_JNI_GetArrayLength, // GetArrayLength
2690 _Jv_JNI_NewObjectArray, // NewObjectArray
2691 _Jv_JNI_GetObjectArrayElement, // GetObjectArrayElement
2692 _Jv_JNI_SetObjectArrayElement, // SetObjectArrayElement
2693 _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
2694 // NewBooleanArray
2695 _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>, // NewByteArray
2696 _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>, // NewCharArray
2697 _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>, // NewShortArray
2698 _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>, // NewIntArray
2699 _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>, // NewLongArray
2700 _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>, // NewFloatArray
2701 _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>, // NewDoubleArray
2702 _Jv_JNI_GetPrimitiveArrayElements, // GetBooleanArrayElements
2703 _Jv_JNI_GetPrimitiveArrayElements, // GetByteArrayElements
2704 _Jv_JNI_GetPrimitiveArrayElements, // GetCharArrayElements
2705 _Jv_JNI_GetPrimitiveArrayElements, // GetShortArrayElements
2706 _Jv_JNI_GetPrimitiveArrayElements, // GetIntArrayElements
2707 _Jv_JNI_GetPrimitiveArrayElements, // GetLongArrayElements
2708 _Jv_JNI_GetPrimitiveArrayElements, // GetFloatArrayElements
2709 _Jv_JNI_GetPrimitiveArrayElements, // GetDoubleArrayElements
2710 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseBooleanArrayElements
2711 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseByteArrayElements
2712 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseCharArrayElements
2713 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseShortArrayElements
2714 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseIntArrayElements
2715 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseLongArrayElements
2716 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseFloatArrayElements
2717 _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseDoubleArrayElements
2718 _Jv_JNI_GetPrimitiveArrayRegion, // GetBooleanArrayRegion
2719 _Jv_JNI_GetPrimitiveArrayRegion, // GetByteArrayRegion
2720 _Jv_JNI_GetPrimitiveArrayRegion, // GetCharArrayRegion
2721 _Jv_JNI_GetPrimitiveArrayRegion, // GetShortArrayRegion
2722 _Jv_JNI_GetPrimitiveArrayRegion, // GetIntArrayRegion
2723 _Jv_JNI_GetPrimitiveArrayRegion, // GetLongArrayRegion
2724 _Jv_JNI_GetPrimitiveArrayRegion, // GetFloatArrayRegion
2725 _Jv_JNI_GetPrimitiveArrayRegion, // GetDoubleArrayRegion
2726 _Jv_JNI_SetPrimitiveArrayRegion, // SetBooleanArrayRegion
2727 _Jv_JNI_SetPrimitiveArrayRegion, // SetByteArrayRegion
2728 _Jv_JNI_SetPrimitiveArrayRegion, // SetCharArrayRegion
2729 _Jv_JNI_SetPrimitiveArrayRegion, // SetShortArrayRegion
2730 _Jv_JNI_SetPrimitiveArrayRegion, // SetIntArrayRegion
2731 _Jv_JNI_SetPrimitiveArrayRegion, // SetLongArrayRegion
2732 _Jv_JNI_SetPrimitiveArrayRegion, // SetFloatArrayRegion
2733 _Jv_JNI_SetPrimitiveArrayRegion, // SetDoubleArrayRegion
2734 _Jv_JNI_RegisterNatives, // RegisterNatives
2735 _Jv_JNI_UnregisterNatives, // UnregisterNatives
2736 _Jv_JNI_MonitorEnter, // MonitorEnter
2737 _Jv_JNI_MonitorExit, // MonitorExit
2738 _Jv_JNI_GetJavaVM, // GetJavaVM
2739
2740 _Jv_JNI_GetStringRegion, // GetStringRegion
2741 _Jv_JNI_GetStringUTFRegion, // GetStringUTFRegion
2742 _Jv_JNI_GetPrimitiveArrayCritical, // GetPrimitiveArrayCritical
2743 _Jv_JNI_ReleasePrimitiveArrayCritical, // ReleasePrimitiveArrayCritical
2744 _Jv_JNI_GetStringCritical, // GetStringCritical
2745 _Jv_JNI_ReleaseStringCritical, // ReleaseStringCritical
2746
2747 _Jv_JNI_NewWeakGlobalRef, // NewWeakGlobalRef
2748 _Jv_JNI_DeleteWeakGlobalRef, // DeleteWeakGlobalRef
2749
2750 _Jv_JNI_ExceptionCheck, // ExceptionCheck
2751
2752 _Jv_JNI_NewDirectByteBuffer, // NewDirectByteBuffer
2753 _Jv_JNI_GetDirectBufferAddress, // GetDirectBufferAddress
2754 _Jv_JNI_GetDirectBufferCapacity // GetDirectBufferCapacity
2755};
2756
2757struct JNIInvokeInterface _Jv_JNI_InvokeFunctions =
2758{
2759 RESERVED,
2760 RESERVED,
2761 RESERVED,
2762
2763 _Jv_JNI_DestroyJavaVM,
2764 _Jv_JNI_AttachCurrentThread,
2765 _Jv_JNI_DetachCurrentThread,
2766 _Jv_JNI_GetEnv,
2767 _Jv_JNI_AttachCurrentThreadAsDaemon
2768};
Note: See TracBrowser for help on using the repository browser.