1 // jni.cc - JNI implementation, including the jump table.
3 /* Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
11 // Note: currently we take the approach of not checking most
12 // arguments. Instead we could do more checking conditionally (e.g.,
13 // if DEBUG is defined). That might be beneficial in some cases,
14 // though to me it seems that one could just as easily use the
22 // Define this before including jni.h.
23 #define __GCJ_JNI_IMPL__
27 #include <java-assert.h>
30 #include <java/lang/Class.h>
31 #include <java/lang/ClassLoader.h>
32 #include <java/lang/Throwable.h>
33 #include <java/lang/ArrayIndexOutOfBoundsException.h>
34 #include <java/lang/StringIndexOutOfBoundsException.h>
35 #include <java/lang/InstantiationException.h>
36 #include <java/lang/NoSuchFieldError.h>
37 #include <java/lang/NoSuchMethodError.h>
38 #include <java/lang/reflect/Constructor.h>
39 #include <java/lang/reflect/Method.h>
40 #include <java/lang/reflect/Modifier.h>
41 #include <java/lang/OutOfMemoryError.h>
42 #include <java/util/Hashtable.h>
43 #include <java/lang/Integer.h>
45 #include <gcj/method.h>
46 #include <gcj/field.h>
48 #define ClassClass _CL_Q34java4lang5Class
49 extern java::lang::Class ClassClass;
50 #define ObjectClass _CL_Q34java4lang6Object
51 extern java::lang::Class ObjectClass;
53 #define MethodClass _CL_Q44java4lang7reflect6Method
54 extern java::lang::Class MethodClass;
56 // This enum is used to select different template instantiations in
57 // the invocation code.
66 // Forward declaration.
67 extern struct JNINativeInterface _Jv_JNIFunctions;
69 // Number of slots in the default frame. The VM must allow at least
73 // This structure is used to keep track of local references.
74 struct _Jv_JNI_LocalFrame
76 // This is true if this frame object represents a pushed frame (eg
77 // from PushLocalFrame).
80 // Number of elements in frame.
83 // Next frame in chain.
84 _Jv_JNI_LocalFrame *next;
86 // The elements. These are allocated using the C "struct hack".
90 // This holds a reference count for all local and global references.
91 static java::util::Hashtable *ref_table;
98 ref_table = new java::util::Hashtable;
101 // Tell the GC that a certain pointer is live.
103 mark_for_gc (jobject obj)
105 JvSynchronize sync (ref_table);
107 using namespace java::lang;
108 Integer *refcount = (Integer *) ref_table->get (obj);
109 jint val = (refcount == NULL) ? 0 : refcount->intValue ();
110 ref_table->put (obj, new Integer (val + 1));
115 unmark_for_gc (jobject obj)
117 JvSynchronize sync (ref_table);
119 using namespace java::lang;
120 Integer *refcount = (Integer *) ref_table->get (obj);
122 jint val = refcount->intValue () - 1;
124 ref_table->remove (obj);
126 ref_table->put (obj, new Integer (val));
132 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
139 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
145 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
147 _Jv_JNI_LocalFrame *frame;
149 for (frame = env->locals; frame != NULL; frame = frame->next)
151 for (int i = 0; i < FRAME_SIZE; ++i)
153 if (frame->vec[i] == obj)
155 frame->vec[i] = NULL;
161 // Don't go past a marked frame.
162 JvAssert (! frame->marker);
169 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
171 // It is easier to just always allocate a new frame of the requested
172 // size. This isn't the most efficient thing, but for now we don't
173 // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
175 _Jv_JNI_LocalFrame *frame
176 = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
177 + size * sizeof (jobject));
180 // FIXME: exception processing.
181 env->ex = new java::lang::OutOfMemoryError;
185 frame->marker = true;
187 memset (&frame->vec[0], 0, size * sizeof (jobject));
188 frame->next = env->locals;
195 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
197 jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
201 // The new frame is on top.
202 env->locals->marker = true;
208 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
210 // Try to find an open slot somewhere in the topmost frame.
211 _Jv_JNI_LocalFrame *frame = env->locals;
212 bool done = false, set = false;
213 while (frame != NULL && ! done)
215 for (int i = 0; i < frame->size; ++i)
216 if (frame->vec[i] == NULL)
227 // No slots, so we allocate a new frame. According to the spec
228 // we could just die here. FIXME: return value.
229 _Jv_JNI_EnsureLocalCapacity (env, 16);
230 // We know the first element of the new frame will be ok.
231 env->locals->vec[0] = obj;
239 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
241 _Jv_JNI_LocalFrame *rf = env->locals;
244 while (rf != NULL && ! done)
246 for (int i = 0; i < rf->size; ++i)
247 if (rf->vec[i] != NULL)
248 unmark_for_gc (rf->vec[i]);
250 // If the frame we just freed is the marker frame, we are done.
253 _Jv_JNI_LocalFrame *n = rf->next;
254 // When N==NULL, we've reached the stack-allocated frame, and we
255 // must not free it. However, we must be sure to clear all its
256 // elements, since we might conceivably reuse it.
258 memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
264 return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
270 _Jv_JNI_GetVersion (JNIEnv *)
272 return JNI_VERSION_1_2;
276 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
277 const jbyte *buf, jsize bufLen)
279 jbyteArray bytes = JvNewByteArray (bufLen);
280 jbyte *elts = elements (bytes);
281 memcpy (elts, buf, bufLen * sizeof (jbyte));
283 java::lang::ClassLoader *l
284 = reinterpret_cast<java::lang::ClassLoader *> (loader);
286 // FIXME: exception processing.
287 jclass result = l->defineClass (bytes, 0, bufLen);
288 return (jclass) _Jv_JNI_NewLocalRef (env, result);
292 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
294 // FIXME: assume that NAME isn't too long.
295 int len = strlen (name);
297 for (int i = 0; i <= len; ++i)
298 s[i] = (name[i] == '/') ? '.' : name[i];
299 jstring n = JvNewStringUTF (s);
301 java::lang::ClassLoader *loader;
302 if (env->klass == NULL)
304 // FIXME: should use getBaseClassLoader, but we don't have that
306 loader = java::lang::ClassLoader::getSystemClassLoader ();
309 loader = env->klass->getClassLoader ();
311 // FIXME: exception processing.
312 jclass r = loader->findClass (n);
314 return (jclass) _Jv_JNI_NewLocalRef (env, r);
318 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
320 return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
324 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
326 return clazz1->isAssignableFrom (clazz2);
330 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
337 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
339 using namespace java::lang::reflect;
341 JArray<jclass> *argtypes
342 = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
344 jclass *elts = elements (argtypes);
345 elts[0] = &StringClass;
347 // FIXME: exception processing.
348 Constructor *cons = clazz->getConstructor (argtypes);
350 jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
351 jobject *velts = elements (values);
352 velts[0] = JvNewStringUTF (message);
354 // FIXME: exception processing.
355 jobject obj = cons->newInstance (values);
357 env->ex = reinterpret_cast<jthrowable> (obj);
362 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
364 return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
368 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
371 env->ex->printStackTrace();
375 _Jv_JNI_ExceptionClear (JNIEnv *env)
381 _Jv_JNI_ExceptionCheck (JNIEnv *env)
383 return env->ex != NULL;
387 _Jv_JNI_FatalError (JNIEnv *, const char *message)
395 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
401 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
404 using namespace java::lang::reflect;
405 if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
406 env->ex = new java::lang::InstantiationException ();
409 // FIXME: exception processing.
410 // FIXME: will this work for String?
411 obj = JvAllocObject (clazz);
414 return _Jv_JNI_NewLocalRef (env, obj);
418 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
420 return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
424 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
426 return clazz->isInstance(obj);
432 // This section concerns method invocation.
435 template<jboolean is_static>
437 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
438 const char *name, const char *sig)
440 // FIXME: exception processing.
441 _Jv_InitClass (clazz);
443 _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
444 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
446 JvAssert (! clazz->isPrimitive());
448 using namespace java::lang::reflect;
450 while (clazz != NULL)
452 jint count = JvNumMethods (clazz);
453 jmethodID meth = JvGetFirstMethod (clazz);
455 for (jint i = 0; i < count; ++i)
457 if (((is_static && Modifier::isStatic (meth->accflags))
458 || (! is_static && ! Modifier::isStatic (meth->accflags)))
459 && _Jv_equalUtf8Consts (meth->name, name_u)
460 && _Jv_equalUtf8Consts (meth->signature, sig_u))
463 meth = meth->getNextMethod();
466 clazz = clazz->getSuperclass ();
469 env->ex = new java::lang::NoSuchMethodError ();
473 // This is a helper function which turns a va_list into an array of
474 // `jvalue's. It needs signature information in order to do its work.
475 // The array of values must already be allocated.
477 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
479 jclass *arg_elts = elements (arg_types);
480 for (int i = 0; i < arg_types->length; ++i)
482 if (arg_elts[i] == JvPrimClass (byte))
483 values[i].b = va_arg (vargs, jbyte);
484 else if (arg_elts[i] == JvPrimClass (short))
485 values[i].s = va_arg (vargs, jshort);
486 else if (arg_elts[i] == JvPrimClass (int))
487 values[i].i = va_arg (vargs, jint);
488 else if (arg_elts[i] == JvPrimClass (long))
489 values[i].j = va_arg (vargs, jlong);
490 else if (arg_elts[i] == JvPrimClass (float))
491 values[i].f = va_arg (vargs, jfloat);
492 else if (arg_elts[i] == JvPrimClass (double))
493 values[i].d = va_arg (vargs, jdouble);
494 else if (arg_elts[i] == JvPrimClass (boolean))
495 values[i].z = va_arg (vargs, jboolean);
496 else if (arg_elts[i] == JvPrimClass (char))
497 values[i].c = va_arg (vargs, jchar);
501 values[i].l = va_arg (vargs, jobject);
506 // This can call any sort of method: virtual, "nonvirtual", static, or
508 template<typename T, invocation_type style>
510 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
511 jmethodID id, va_list vargs)
514 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
516 jclass decl_class = klass ? klass : obj->getClass ();
517 JvAssert (decl_class != NULL);
520 JArray<jclass> *arg_types;
521 // FIXME: exception processing.
522 _Jv_GetTypesFromSignature (id, decl_class,
523 &arg_types, &return_type);
525 jvalue args[arg_types->length];
526 array_from_valist (args, arg_types, vargs);
529 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
530 style == constructor,
531 arg_types, args, &result);
536 if (! return_type->isPrimitive ())
538 // Make sure we create a local reference. The cast hackery is
539 // to avoid problems for template instantations we know won't be
541 return (T) (long long) _Jv_JNI_NewLocalRef (env, result.l);
544 // We cheat a little here. FIXME.
545 return * (T *) &result;
548 template<typename T, invocation_type style>
550 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
551 jmethodID method, ...)
556 va_start (args, method);
557 result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
563 template<typename T, invocation_type style>
565 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
566 jmethodID id, jvalue *args)
569 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
571 jclass decl_class = klass ? klass : obj->getClass ();
572 JvAssert (decl_class != NULL);
575 JArray<jclass> *arg_types;
576 // FIXME: exception processing.
577 _Jv_GetTypesFromSignature (id, decl_class,
578 &arg_types, &return_type);
581 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
582 style == constructor,
583 arg_types, args, &result);
588 if (! return_type->isPrimitive ())
590 // Make sure we create a local reference. The cast hackery is
591 // to avoid problems for template instantations we know won't be
593 return (T) (long long) _Jv_JNI_NewLocalRef (env, result.l);
596 // We cheat a little here. FIXME.
597 return * (T *) &result;
600 template<invocation_type style>
602 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
603 jmethodID id, va_list vargs)
606 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
608 jclass decl_class = klass ? klass : obj->getClass ();
609 JvAssert (decl_class != NULL);
612 JArray<jclass> *arg_types;
613 // FIXME: exception processing.
614 _Jv_GetTypesFromSignature (id, decl_class,
615 &arg_types, &return_type);
617 jvalue args[arg_types->length];
618 array_from_valist (args, arg_types, vargs);
620 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
621 style == constructor,
622 arg_types, args, NULL);
628 template<invocation_type style>
630 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
631 jmethodID method, ...)
635 va_start (args, method);
636 _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
640 template<invocation_type style>
642 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
643 jmethodID id, jvalue *args)
646 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
648 jclass decl_class = klass ? klass : obj->getClass ();
649 JvAssert (decl_class != NULL);
652 JArray<jclass> *arg_types;
653 // FIXME: exception processing.
654 _Jv_GetTypesFromSignature (id, decl_class,
655 &arg_types, &return_type);
657 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
658 style == constructor,
659 arg_types, args, NULL);
665 // Functions with this signature are used to implement functions in
666 // the CallMethod family.
669 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
671 return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
674 // Functions with this signature are used to implement functions in
675 // the CallMethod family.
678 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
684 result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
690 // Functions with this signature are used to implement functions in
691 // the CallMethod family.
694 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
696 return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
700 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
702 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
706 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
711 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
716 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
718 _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
721 // Functions with this signature are used to implement functions in
722 // the CallStaticMethod family.
725 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
726 jmethodID id, va_list args)
728 return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
731 // Functions with this signature are used to implement functions in
732 // the CallStaticMethod family.
735 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
741 result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
748 // Functions with this signature are used to implement functions in
749 // the CallStaticMethod family.
752 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
755 return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
759 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
762 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
766 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
771 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
776 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
779 _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
783 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
784 jmethodID id, va_list args)
786 return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
791 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
797 result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
805 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
808 return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
816 _Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field)
818 T *ptr = (T *) ((char *) obj + field->getOffset ());
824 _Jv_JNI_GetField<jobject> (JNIEnv *env, jobject obj, jfieldID field)
826 jobject *ptr = (jobject *) ((char *) obj + field->getOffset ());
827 return _Jv_JNI_NewLocalRef (env, *ptr);
832 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
834 T *ptr = (T *) ((char *) obj + field->getOffset ());
838 template<jboolean is_static>
840 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
841 const char *name, const char *sig)
843 // FIXME: exception processing.
844 _Jv_InitClass (clazz);
846 _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
848 jclass field_class = NULL;
850 field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
853 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
854 field_class = _Jv_FindClass (sig_u, NULL);
857 // FIXME: what if field_class == NULL?
859 while (clazz != NULL)
861 jint count = (is_static
862 ? JvNumStaticFields (clazz)
863 : JvNumInstanceFields (clazz));
864 jfieldID field = (is_static
865 ? JvGetFirstStaticField (clazz)
866 : JvGetFirstInstanceField (clazz));
867 for (jint i = 0; i < count; ++i)
869 // The field is resolved as a side effect of class
871 JvAssert (field->isResolved ());
873 _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
875 if (_Jv_equalUtf8Consts (f_name, a_name)
876 && field->getClass() == field_class)
879 field = field->getNextField ();
882 clazz = clazz->getSuperclass ();
885 env->ex = new java::lang::NoSuchFieldError ();
889 // FIXME: local reference
892 _Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
894 T *ptr = (T *) field->u.addr;
900 _Jv_JNI_GetStaticField<jobject> (JNIEnv *env, jclass, jfieldID field)
902 jobject *ptr = (jobject *) field->u.addr;
903 return _Jv_JNI_NewLocalRef (env, *ptr);
908 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
910 T *ptr = (T *) field->u.addr;
915 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
917 // FIXME: exception processing.
918 jstring r = _Jv_NewString (unichars, len);
919 return (jstring) _Jv_JNI_NewLocalRef (env, r);
923 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
925 return string->length();
929 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
931 jchar *result = _Jv_GetStringChars (string);
932 mark_for_gc (string);
935 return (const jchar *) result;
939 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
941 unmark_for_gc (string);
945 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
947 // FIXME: exception processing.
948 jstring result = JvNewStringUTF (bytes);
949 return (jstring) _Jv_JNI_NewLocalRef (env, result);
953 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
955 return JvGetStringUTFLength (string);
959 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
961 jsize len = JvGetStringUTFLength (string);
962 // FIXME: exception processing.
963 char *r = (char *) _Jv_Malloc (len + 1);
964 JvGetStringUTFRegion (string, 0, len, r);
970 return (const char *) r;
974 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
976 _Jv_Free ((void *) utf);
980 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
983 jchar *result = _Jv_GetStringChars (string);
984 if (start < 0 || start > string->length ()
985 || len < 0 || start + len > string->length ())
986 env->ex = new java::lang::StringIndexOutOfBoundsException ();
988 memcpy (buf, &result[start], len * sizeof (jchar));
992 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
993 jsize len, char *buf)
995 if (start < 0 || start > str->length ()
996 || len < 0 || start + len > str->length ())
997 env->ex = new java::lang::StringIndexOutOfBoundsException ();
999 _Jv_GetStringUTFRegion (str, start, len, buf);
1002 static const jchar *
1003 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
1005 jchar *result = _Jv_GetStringChars (str);
1012 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1018 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1020 return array->length;
1024 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1027 // FIXME: exception processing.
1028 jarray result = JvNewObjectArray (length, elementClass, init);
1029 return (jarray) _Jv_JNI_NewLocalRef (env, result);
1033 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1035 jobject *elts = elements (array);
1036 return _Jv_JNI_NewLocalRef (env, elts[index]);
1040 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1043 // FIXME: exception processing.
1044 _Jv_CheckArrayStore (array, value);
1045 jobject *elts = elements (array);
1046 elts[index] = value;
1049 template<typename T, jclass K>
1051 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1053 // FIXME: exception processing.
1054 return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1055 _Jv_NewPrimArray (K, length));
1058 template<typename T>
1060 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1063 T *elts = elements (array);
1066 // We elect never to copy.
1069 mark_for_gc (array);
1073 template<typename T>
1075 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1076 T *, jint /* mode */)
1078 // Note that we ignore MODE. We can do this because we never copy
1079 // the array elements. My reading of the JNI documentation is that
1080 // this is an option for the implementor.
1081 unmark_for_gc (array);
1084 template<typename T>
1086 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1087 jsize start, jsize len,
1090 if (start < 0 || len >= array->length || start + len >= array->length)
1093 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1097 T *elts = elements (array) + start;
1098 memcpy (buf, elts, len * sizeof (T));
1102 template<typename T>
1104 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1105 jsize start, jsize len, T *buf)
1107 if (start < 0 || len >= array->length || start + len >= array->length)
1110 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1114 T *elts = elements (array) + start;
1115 memcpy (elts, buf, len * sizeof (T));
1120 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1123 // FIXME: does this work?
1124 jclass klass = array->getClass()->getComponentType();
1125 JvAssert (klass->isPrimitive ());
1126 char *r = _Jv_GetArrayElementFromElementType (array, klass);
1133 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1139 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1141 // FIXME: exception processing.
1142 jint r = _Jv_MonitorEnter (obj);
1147 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1149 // FIXME: exception processing.
1150 jint r = _Jv_MonitorExit (obj);
1156 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1159 // FIXME: exception processing.
1160 java::lang::reflect::Field *field = new java::lang::reflect::Field();
1161 field->declaringClass = cls;
1162 field->offset = (char*) fieldID - (char *) cls->fields;
1163 field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1164 return _Jv_JNI_NewLocalRef (env, field);
1169 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1171 using namespace java::lang::reflect;
1173 Field *field = reinterpret_cast<Field *> (f);
1174 return _Jv_FromReflectedField (field);
1178 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1181 using namespace java::lang::reflect;
1184 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1187 if (_Jv_equalUtf8Consts (id->name, init_name))
1190 Constructor *cons = new Constructor ();
1191 cons->offset = (char *) id - (char *) &klass->methods;
1192 cons->declaringClass = klass;
1197 Method *meth = new Method ();
1198 meth->offset = (char *) id - (char *) &klass->methods;
1199 meth->declaringClass = klass;
1203 return _Jv_JNI_NewLocalRef (env, result);
1207 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1209 using namespace java::lang::reflect;
1210 if ((&MethodClass)->isInstance (method))
1211 return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1213 _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1218 // This function is the stub which is used to turn an ordinary (CNI)
1219 // method call into a JNI call.
1221 template<typename T>
1223 _Jv_JNI_conversion_call (fixme)
1226 _Jv_JNI_LocalFrame *frame
1227 = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1228 + FRAME_SIZE * sizeof (jobject));
1230 env.p = &_Jv_JNIFunctions;
1235 frame->marker = true;
1237 frame->size = FRAME_SIZE;
1238 for (int i = 0; i < frame->size; ++i)
1239 frame->vec[i] = NULL;
1241 T result = FIXME_ffi_call (args);
1243 while (env.locals != NULL)
1244 _Jv_JNI_PopLocalFrame (&env, result);
1255 #define NOT_IMPL NULL
1256 #define RESERVED NULL
1258 struct JNINativeInterface _Jv_JNIFunctions =
1265 _Jv_JNI_DefineClass,
1267 _Jv_JNI_FromReflectedMethod,
1268 _Jv_JNI_FromReflectedField,
1269 _Jv_JNI_ToReflectedMethod,
1270 _Jv_JNI_GetSuperclass,
1271 _Jv_JNI_IsAssignableFrom,
1272 _Jv_JNI_ToReflectedField,
1275 _Jv_JNI_ExceptionOccurred,
1276 _Jv_JNI_ExceptionDescribe,
1277 _Jv_JNI_ExceptionClear,
1280 _Jv_JNI_PushLocalFrame,
1281 _Jv_JNI_PopLocalFrame,
1282 _Jv_JNI_NewGlobalRef,
1283 _Jv_JNI_DeleteGlobalRef,
1284 _Jv_JNI_DeleteLocalRef,
1286 _Jv_JNI_IsSameObject,
1288 _Jv_JNI_NewLocalRef,
1289 _Jv_JNI_EnsureLocalCapacity,
1291 _Jv_JNI_AllocObject,
1295 _Jv_JNI_GetObjectClass,
1296 _Jv_JNI_IsInstanceOf,
1297 _Jv_JNI_GetAnyMethodID<false>,
1299 _Jv_JNI_CallMethod<jobject>,
1300 _Jv_JNI_CallMethodV<jobject>,
1301 _Jv_JNI_CallMethodA<jobject>,
1302 _Jv_JNI_CallMethod<jboolean>,
1303 _Jv_JNI_CallMethodV<jboolean>,
1304 _Jv_JNI_CallMethodA<jboolean>,
1305 _Jv_JNI_CallMethod<jbyte>,
1306 _Jv_JNI_CallMethodV<jbyte>,
1307 _Jv_JNI_CallMethodA<jbyte>,
1308 _Jv_JNI_CallMethod<jchar>,
1309 _Jv_JNI_CallMethodV<jchar>,
1310 _Jv_JNI_CallMethodA<jchar>,
1311 _Jv_JNI_CallMethod<jshort>,
1312 _Jv_JNI_CallMethodV<jshort>,
1313 _Jv_JNI_CallMethodA<jshort>,
1314 _Jv_JNI_CallMethod<jint>,
1315 _Jv_JNI_CallMethodV<jint>,
1316 _Jv_JNI_CallMethodA<jint>,
1317 _Jv_JNI_CallMethod<jlong>,
1318 _Jv_JNI_CallMethodV<jlong>,
1319 _Jv_JNI_CallMethodA<jlong>,
1320 _Jv_JNI_CallMethod<jfloat>,
1321 _Jv_JNI_CallMethodV<jfloat>,
1322 _Jv_JNI_CallMethodA<jfloat>,
1323 _Jv_JNI_CallMethod<jdouble>,
1324 _Jv_JNI_CallMethodV<jdouble>,
1325 _Jv_JNI_CallMethodA<jdouble>,
1326 _Jv_JNI_CallVoidMethod,
1327 _Jv_JNI_CallVoidMethodV,
1328 _Jv_JNI_CallVoidMethodA,
1330 // Nonvirtual method invocation functions follow.
1331 _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1332 _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1333 _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1334 _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1335 _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1336 _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1337 _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1338 _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1339 _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1340 _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1341 _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1342 _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1343 _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1344 _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1345 _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1346 _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1347 _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1348 _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1349 _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1350 _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1351 _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1352 _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1353 _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1354 _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1355 _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1356 _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1357 _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1358 _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1359 _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1360 _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1362 _Jv_JNI_GetAnyFieldID<false>,
1363 _Jv_JNI_GetField<jobject>,
1364 _Jv_JNI_GetField<jboolean>,
1365 _Jv_JNI_GetField<jbyte>,
1366 _Jv_JNI_GetField<jchar>,
1367 _Jv_JNI_GetField<jshort>,
1368 _Jv_JNI_GetField<jint>,
1369 _Jv_JNI_GetField<jlong>,
1370 _Jv_JNI_GetField<jfloat>,
1371 _Jv_JNI_GetField<jdouble>,
1381 _Jv_JNI_GetAnyMethodID<true>,
1383 _Jv_JNI_CallStaticMethod<jobject>,
1384 _Jv_JNI_CallStaticMethodV<jobject>,
1385 _Jv_JNI_CallStaticMethodA<jobject>,
1386 _Jv_JNI_CallStaticMethod<jboolean>,
1387 _Jv_JNI_CallStaticMethodV<jboolean>,
1388 _Jv_JNI_CallStaticMethodA<jboolean>,
1389 _Jv_JNI_CallStaticMethod<jbyte>,
1390 _Jv_JNI_CallStaticMethodV<jbyte>,
1391 _Jv_JNI_CallStaticMethodA<jbyte>,
1392 _Jv_JNI_CallStaticMethod<jchar>,
1393 _Jv_JNI_CallStaticMethodV<jchar>,
1394 _Jv_JNI_CallStaticMethodA<jchar>,
1395 _Jv_JNI_CallStaticMethod<jshort>,
1396 _Jv_JNI_CallStaticMethodV<jshort>,
1397 _Jv_JNI_CallStaticMethodA<jshort>,
1398 _Jv_JNI_CallStaticMethod<jint>,
1399 _Jv_JNI_CallStaticMethodV<jint>,
1400 _Jv_JNI_CallStaticMethodA<jint>,
1401 _Jv_JNI_CallStaticMethod<jlong>,
1402 _Jv_JNI_CallStaticMethodV<jlong>,
1403 _Jv_JNI_CallStaticMethodA<jlong>,
1404 _Jv_JNI_CallStaticMethod<jfloat>,
1405 _Jv_JNI_CallStaticMethodV<jfloat>,
1406 _Jv_JNI_CallStaticMethodA<jfloat>,
1407 _Jv_JNI_CallStaticMethod<jdouble>,
1408 _Jv_JNI_CallStaticMethodV<jdouble>,
1409 _Jv_JNI_CallStaticMethodA<jdouble>,
1410 _Jv_JNI_CallStaticVoidMethod,
1411 _Jv_JNI_CallStaticVoidMethodV,
1412 _Jv_JNI_CallStaticVoidMethodA,
1414 _Jv_JNI_GetAnyFieldID<true>,
1415 _Jv_JNI_GetStaticField<jobject>,
1416 _Jv_JNI_GetStaticField<jboolean>,
1417 _Jv_JNI_GetStaticField<jbyte>,
1418 _Jv_JNI_GetStaticField<jchar>,
1419 _Jv_JNI_GetStaticField<jshort>,
1420 _Jv_JNI_GetStaticField<jint>,
1421 _Jv_JNI_GetStaticField<jlong>,
1422 _Jv_JNI_GetStaticField<jfloat>,
1423 _Jv_JNI_GetStaticField<jdouble>,
1424 _Jv_JNI_SetStaticField,
1425 _Jv_JNI_SetStaticField,
1426 _Jv_JNI_SetStaticField,
1427 _Jv_JNI_SetStaticField,
1428 _Jv_JNI_SetStaticField,
1429 _Jv_JNI_SetStaticField,
1430 _Jv_JNI_SetStaticField,
1431 _Jv_JNI_SetStaticField,
1432 _Jv_JNI_SetStaticField,
1434 _Jv_JNI_GetStringLength,
1435 _Jv_JNI_GetStringChars,
1436 _Jv_JNI_ReleaseStringChars,
1437 _Jv_JNI_NewStringUTF,
1438 _Jv_JNI_GetStringUTFLength,
1439 _Jv_JNI_GetStringUTFChars,
1440 _Jv_JNI_ReleaseStringUTFChars,
1441 _Jv_JNI_GetArrayLength,
1442 _Jv_JNI_NewObjectArray,
1443 _Jv_JNI_GetObjectArrayElement,
1444 _Jv_JNI_SetObjectArrayElement,
1445 _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1446 _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1447 _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1448 _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1449 _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1450 _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1451 _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1452 _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1453 _Jv_JNI_GetPrimitiveArrayElements,
1454 _Jv_JNI_GetPrimitiveArrayElements,
1455 _Jv_JNI_GetPrimitiveArrayElements,
1456 _Jv_JNI_GetPrimitiveArrayElements,
1457 _Jv_JNI_GetPrimitiveArrayElements,
1458 _Jv_JNI_GetPrimitiveArrayElements,
1459 _Jv_JNI_GetPrimitiveArrayElements,
1460 _Jv_JNI_GetPrimitiveArrayElements,
1461 _Jv_JNI_ReleasePrimitiveArrayElements,
1462 _Jv_JNI_ReleasePrimitiveArrayElements,
1463 _Jv_JNI_ReleasePrimitiveArrayElements,
1464 _Jv_JNI_ReleasePrimitiveArrayElements,
1465 _Jv_JNI_ReleasePrimitiveArrayElements,
1466 _Jv_JNI_ReleasePrimitiveArrayElements,
1467 _Jv_JNI_ReleasePrimitiveArrayElements,
1468 _Jv_JNI_ReleasePrimitiveArrayElements,
1469 _Jv_JNI_GetPrimitiveArrayRegion,
1470 _Jv_JNI_GetPrimitiveArrayRegion,
1471 _Jv_JNI_GetPrimitiveArrayRegion,
1472 _Jv_JNI_GetPrimitiveArrayRegion,
1473 _Jv_JNI_GetPrimitiveArrayRegion,
1474 _Jv_JNI_GetPrimitiveArrayRegion,
1475 _Jv_JNI_GetPrimitiveArrayRegion,
1476 _Jv_JNI_GetPrimitiveArrayRegion,
1477 _Jv_JNI_SetPrimitiveArrayRegion,
1478 _Jv_JNI_SetPrimitiveArrayRegion,
1479 _Jv_JNI_SetPrimitiveArrayRegion,
1480 _Jv_JNI_SetPrimitiveArrayRegion,
1481 _Jv_JNI_SetPrimitiveArrayRegion,
1482 _Jv_JNI_SetPrimitiveArrayRegion,
1483 _Jv_JNI_SetPrimitiveArrayRegion,
1484 _Jv_JNI_SetPrimitiveArrayRegion,
1485 NOT_IMPL /* RegisterNatives */,
1486 NOT_IMPL /* UnregisterNatives */,
1487 _Jv_JNI_MonitorEnter,
1488 _Jv_JNI_MonitorExit,
1489 NOT_IMPL /* GetJavaVM */,
1491 _Jv_JNI_GetStringRegion,
1492 _Jv_JNI_GetStringUTFRegion,
1493 _Jv_JNI_GetPrimitiveArrayCritical,
1494 _Jv_JNI_ReleasePrimitiveArrayCritical,
1495 _Jv_JNI_GetStringCritical,
1496 _Jv_JNI_ReleaseStringCritical,
1498 NOT_IMPL /* newweakglobalref */,
1499 NOT_IMPL /* deleteweakglobalref */,
1501 _Jv_JNI_ExceptionCheck