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
16 // Define this before including jni.h.
17 #define __GCJ_JNI_IMPL__
21 #include <java-assert.h>
24 #include <java/lang/Class.h>
25 #include <java/lang/ClassLoader.h>
26 #include <java/lang/Throwable.h>
27 #include <java/lang/ArrayIndexOutOfBoundsException.h>
28 #include <java/lang/StringIndexOutOfBoundsException.h>
29 #include <java/lang/AbstractMethodError.h>
30 #include <java/lang/InstantiationException.h>
31 #include <java/lang/NoSuchFieldError.h>
32 #include <java/lang/NoSuchMethodError.h>
33 #include <java/lang/reflect/Constructor.h>
34 #include <java/lang/reflect/Method.h>
35 #include <java/lang/reflect/Modifier.h>
36 #include <java/lang/OutOfMemoryError.h>
37 #include <java/util/Hashtable.h>
38 #include <java/lang/Integer.h>
40 #include <gcj/method.h>
41 #include <gcj/field.h>
43 #include <java-interp.h>
45 #define ClassClass _CL_Q34java4lang5Class
46 extern java::lang::Class ClassClass;
47 #define ObjectClass _CL_Q34java4lang6Object
48 extern java::lang::Class ObjectClass;
50 #define MethodClass _CL_Q44java4lang7reflect6Method
51 extern java::lang::Class MethodClass;
53 // This enum is used to select different template instantiations in
54 // the invocation code.
63 // Forward declaration.
64 extern struct JNINativeInterface _Jv_JNIFunctions;
66 // Number of slots in the default frame. The VM must allow at least
70 // This structure is used to keep track of local references.
71 struct _Jv_JNI_LocalFrame
73 // This is true if this frame object represents a pushed frame (eg
74 // from PushLocalFrame).
77 // Number of elements in frame.
80 // Next frame in chain.
81 _Jv_JNI_LocalFrame *next;
83 // The elements. These are allocated using the C "struct hack".
87 // This holds a reference count for all local and global references.
88 static java::util::Hashtable *ref_table;
95 ref_table = new java::util::Hashtable;
98 // Tell the GC that a certain pointer is live.
100 mark_for_gc (jobject obj)
102 JvSynchronize sync (ref_table);
104 using namespace java::lang;
105 Integer *refcount = (Integer *) ref_table->get (obj);
106 jint val = (refcount == NULL) ? 0 : refcount->intValue ();
107 ref_table->put (obj, new Integer (val + 1));
112 unmark_for_gc (jobject obj)
114 JvSynchronize sync (ref_table);
116 using namespace java::lang;
117 Integer *refcount = (Integer *) ref_table->get (obj);
119 jint val = refcount->intValue () - 1;
121 ref_table->remove (obj);
123 ref_table->put (obj, new Integer (val));
129 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
136 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
142 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
144 _Jv_JNI_LocalFrame *frame;
146 for (frame = env->locals; frame != NULL; frame = frame->next)
148 for (int i = 0; i < FRAME_SIZE; ++i)
150 if (frame->vec[i] == obj)
152 frame->vec[i] = NULL;
158 // Don't go past a marked frame.
159 JvAssert (! frame->marker);
166 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
168 // It is easier to just always allocate a new frame of the requested
169 // size. This isn't the most efficient thing, but for now we don't
170 // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
172 _Jv_JNI_LocalFrame *frame
173 = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
174 + size * sizeof (jobject));
177 // FIXME: exception processing.
178 env->ex = new java::lang::OutOfMemoryError;
182 frame->marker = true;
184 memset (&frame->vec[0], 0, size * sizeof (jobject));
185 frame->next = env->locals;
192 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
194 jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
198 // The new frame is on top.
199 env->locals->marker = true;
205 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
207 // Try to find an open slot somewhere in the topmost frame.
208 _Jv_JNI_LocalFrame *frame = env->locals;
209 bool done = false, set = false;
210 while (frame != NULL && ! done)
212 for (int i = 0; i < frame->size; ++i)
213 if (frame->vec[i] == NULL)
224 // No slots, so we allocate a new frame. According to the spec
225 // we could just die here. FIXME: return value.
226 _Jv_JNI_EnsureLocalCapacity (env, 16);
227 // We know the first element of the new frame will be ok.
228 env->locals->vec[0] = obj;
236 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
238 _Jv_JNI_LocalFrame *rf = env->locals;
241 while (rf != NULL && ! done)
243 for (int i = 0; i < rf->size; ++i)
244 if (rf->vec[i] != NULL)
245 unmark_for_gc (rf->vec[i]);
247 // If the frame we just freed is the marker frame, we are done.
250 _Jv_JNI_LocalFrame *n = rf->next;
251 // When N==NULL, we've reached the stack-allocated frame, and we
252 // must not free it. However, we must be sure to clear all its
253 // elements, since we might conceivably reuse it.
256 memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
264 return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
267 // This function is used from other template functions. It wraps the
268 // return value appropriately; we specialize it so that object returns
269 // are turned into local references.
272 wrap_value (JNIEnv *, T value)
279 wrap_value (JNIEnv *env, jobject value)
281 return _Jv_JNI_NewLocalRef (env, value);
287 _Jv_JNI_GetVersion (JNIEnv *)
289 return JNI_VERSION_1_2;
293 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
294 const jbyte *buf, jsize bufLen)
296 jbyteArray bytes = JvNewByteArray (bufLen);
297 jbyte *elts = elements (bytes);
298 memcpy (elts, buf, bufLen * sizeof (jbyte));
300 java::lang::ClassLoader *l
301 = reinterpret_cast<java::lang::ClassLoader *> (loader);
303 // FIXME: exception processing.
304 jclass result = l->defineClass (bytes, 0, bufLen);
305 return (jclass) _Jv_JNI_NewLocalRef (env, result);
309 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
311 // FIXME: assume that NAME isn't too long.
312 int len = strlen (name);
314 for (int i = 0; i <= len; ++i)
315 s[i] = (name[i] == '/') ? '.' : name[i];
316 jstring n = JvNewStringUTF (s);
318 java::lang::ClassLoader *loader;
319 if (env->klass == NULL)
321 // FIXME: should use getBaseClassLoader, but we don't have that
323 loader = java::lang::ClassLoader::getSystemClassLoader ();
326 loader = env->klass->getClassLoader ();
328 // FIXME: exception processing.
329 jclass r = loader->findClass (n);
331 return (jclass) _Jv_JNI_NewLocalRef (env, r);
335 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
337 return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
341 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
343 return clazz1->isAssignableFrom (clazz2);
347 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
354 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
356 using namespace java::lang::reflect;
358 JArray<jclass> *argtypes
359 = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
361 jclass *elts = elements (argtypes);
362 elts[0] = &StringClass;
364 // FIXME: exception processing.
365 Constructor *cons = clazz->getConstructor (argtypes);
367 jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
368 jobject *velts = elements (values);
369 velts[0] = JvNewStringUTF (message);
371 // FIXME: exception processing.
372 jobject obj = cons->newInstance (values);
374 env->ex = reinterpret_cast<jthrowable> (obj);
379 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
381 return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
385 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
388 env->ex->printStackTrace();
392 _Jv_JNI_ExceptionClear (JNIEnv *env)
398 _Jv_JNI_ExceptionCheck (JNIEnv *env)
400 return env->ex != NULL;
404 _Jv_JNI_FatalError (JNIEnv *, const char *message)
412 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
418 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
421 using namespace java::lang::reflect;
422 if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
423 env->ex = new java::lang::InstantiationException ();
426 // FIXME: exception processing.
427 // FIXME: will this work for String?
428 obj = JvAllocObject (clazz);
431 return _Jv_JNI_NewLocalRef (env, obj);
435 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
437 return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
441 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
443 return clazz->isInstance(obj);
449 // This section concerns method invocation.
452 template<jboolean is_static>
454 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
455 const char *name, const char *sig)
457 // FIXME: exception processing.
458 _Jv_InitClass (clazz);
460 _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
461 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
463 JvAssert (! clazz->isPrimitive());
465 using namespace java::lang::reflect;
467 while (clazz != NULL)
469 jint count = JvNumMethods (clazz);
470 jmethodID meth = JvGetFirstMethod (clazz);
472 for (jint i = 0; i < count; ++i)
474 if (((is_static && Modifier::isStatic (meth->accflags))
475 || (! is_static && ! Modifier::isStatic (meth->accflags)))
476 && _Jv_equalUtf8Consts (meth->name, name_u)
477 && _Jv_equalUtf8Consts (meth->signature, sig_u))
480 meth = meth->getNextMethod();
483 clazz = clazz->getSuperclass ();
486 env->ex = new java::lang::NoSuchMethodError ();
490 // This is a helper function which turns a va_list into an array of
491 // `jvalue's. It needs signature information in order to do its work.
492 // The array of values must already be allocated.
494 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
496 jclass *arg_elts = elements (arg_types);
497 for (int i = 0; i < arg_types->length; ++i)
499 if (arg_elts[i] == JvPrimClass (byte))
500 values[i].b = va_arg (vargs, jbyte);
501 else if (arg_elts[i] == JvPrimClass (short))
502 values[i].s = va_arg (vargs, jshort);
503 else if (arg_elts[i] == JvPrimClass (int))
504 values[i].i = va_arg (vargs, jint);
505 else if (arg_elts[i] == JvPrimClass (long))
506 values[i].j = va_arg (vargs, jlong);
507 else if (arg_elts[i] == JvPrimClass (float))
508 values[i].f = va_arg (vargs, jfloat);
509 else if (arg_elts[i] == JvPrimClass (double))
510 values[i].d = va_arg (vargs, jdouble);
511 else if (arg_elts[i] == JvPrimClass (boolean))
512 values[i].z = va_arg (vargs, jboolean);
513 else if (arg_elts[i] == JvPrimClass (char))
514 values[i].c = va_arg (vargs, jchar);
518 values[i].l = va_arg (vargs, jobject);
523 // This can call any sort of method: virtual, "nonvirtual", static, or
525 template<typename T, invocation_type style>
527 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
528 jmethodID id, va_list vargs)
531 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
533 jclass decl_class = klass ? klass : obj->getClass ();
534 JvAssert (decl_class != NULL);
537 JArray<jclass> *arg_types;
538 // FIXME: exception processing.
539 _Jv_GetTypesFromSignature (id, decl_class,
540 &arg_types, &return_type);
542 jvalue args[arg_types->length];
543 array_from_valist (args, arg_types, vargs);
546 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
547 style == constructor,
548 arg_types, args, &result);
553 // We cheat a little here. FIXME.
554 return wrap_value (env, * (T *) &result);
557 template<typename T, invocation_type style>
559 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
560 jmethodID method, ...)
565 va_start (args, method);
566 result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
572 template<typename T, invocation_type style>
574 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
575 jmethodID id, jvalue *args)
578 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
580 jclass decl_class = klass ? klass : obj->getClass ();
581 JvAssert (decl_class != NULL);
584 JArray<jclass> *arg_types;
585 // FIXME: exception processing.
586 _Jv_GetTypesFromSignature (id, decl_class,
587 &arg_types, &return_type);
590 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
591 style == constructor,
592 arg_types, args, &result);
597 // We cheat a little here. FIXME.
598 return wrap_value (env, * (T *) &result);
601 template<invocation_type style>
603 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
604 jmethodID id, va_list vargs)
607 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
609 jclass decl_class = klass ? klass : obj->getClass ();
610 JvAssert (decl_class != NULL);
613 JArray<jclass> *arg_types;
614 // FIXME: exception processing.
615 _Jv_GetTypesFromSignature (id, decl_class,
616 &arg_types, &return_type);
618 jvalue args[arg_types->length];
619 array_from_valist (args, arg_types, vargs);
621 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
622 style == constructor,
623 arg_types, args, NULL);
629 template<invocation_type style>
631 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
632 jmethodID method, ...)
636 va_start (args, method);
637 _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
641 template<invocation_type style>
643 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
644 jmethodID id, jvalue *args)
647 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
649 jclass decl_class = klass ? klass : obj->getClass ();
650 JvAssert (decl_class != NULL);
653 JArray<jclass> *arg_types;
654 // FIXME: exception processing.
655 _Jv_GetTypesFromSignature (id, decl_class,
656 &arg_types, &return_type);
658 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
659 style == constructor,
660 arg_types, args, NULL);
666 // Functions with this signature are used to implement functions in
667 // the CallMethod family.
670 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
672 return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
675 // Functions with this signature are used to implement functions in
676 // the CallMethod family.
679 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
685 result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
691 // Functions with this signature are used to implement functions in
692 // the CallMethod family.
695 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
697 return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
701 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
703 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
707 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
712 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
717 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
719 _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
722 // Functions with this signature are used to implement functions in
723 // the CallStaticMethod family.
726 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
727 jmethodID id, va_list args)
729 return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
732 // Functions with this signature are used to implement functions in
733 // the CallStaticMethod family.
736 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
742 result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
749 // Functions with this signature are used to implement functions in
750 // the CallStaticMethod family.
753 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
756 return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
760 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
763 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
767 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
772 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
777 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
780 _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
784 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
785 jmethodID id, va_list args)
787 return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
792 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
798 result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
806 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
809 return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
817 _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
819 T *ptr = (T *) ((char *) obj + field->getOffset ());
820 return wrap_value (env, *ptr);
825 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
827 T *ptr = (T *) ((char *) obj + field->getOffset ());
831 template<jboolean is_static>
833 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
834 const char *name, const char *sig)
836 // FIXME: exception processing.
837 _Jv_InitClass (clazz);
839 _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
841 jclass field_class = NULL;
843 field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
846 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
847 field_class = _Jv_FindClass (sig_u, NULL);
850 // FIXME: what if field_class == NULL?
852 while (clazz != NULL)
854 jint count = (is_static
855 ? JvNumStaticFields (clazz)
856 : JvNumInstanceFields (clazz));
857 jfieldID field = (is_static
858 ? JvGetFirstStaticField (clazz)
859 : JvGetFirstInstanceField (clazz));
860 for (jint i = 0; i < count; ++i)
862 // The field is resolved as a side effect of class
864 JvAssert (field->isResolved ());
866 _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
868 if (_Jv_equalUtf8Consts (f_name, a_name)
869 && field->getClass() == field_class)
872 field = field->getNextField ();
875 clazz = clazz->getSuperclass ();
878 env->ex = new java::lang::NoSuchFieldError ();
884 _Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
886 T *ptr = (T *) field->u.addr;
887 return wrap_value (env, *ptr);
892 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
894 T *ptr = (T *) field->u.addr;
899 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
901 // FIXME: exception processing.
902 jstring r = _Jv_NewString (unichars, len);
903 return (jstring) _Jv_JNI_NewLocalRef (env, r);
907 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
909 return string->length();
913 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
915 jchar *result = _Jv_GetStringChars (string);
916 mark_for_gc (string);
919 return (const jchar *) result;
923 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
925 unmark_for_gc (string);
929 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
931 // FIXME: exception processing.
932 jstring result = JvNewStringUTF (bytes);
933 return (jstring) _Jv_JNI_NewLocalRef (env, result);
937 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
939 return JvGetStringUTFLength (string);
943 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
945 jsize len = JvGetStringUTFLength (string);
946 // FIXME: exception processing.
947 char *r = (char *) _Jv_Malloc (len + 1);
948 JvGetStringUTFRegion (string, 0, len, r);
954 return (const char *) r;
958 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
960 _Jv_Free ((void *) utf);
964 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
967 jchar *result = _Jv_GetStringChars (string);
968 if (start < 0 || start > string->length ()
969 || len < 0 || start + len > string->length ())
970 env->ex = new java::lang::StringIndexOutOfBoundsException ();
972 memcpy (buf, &result[start], len * sizeof (jchar));
976 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
977 jsize len, char *buf)
979 if (start < 0 || start > str->length ()
980 || len < 0 || start + len > str->length ())
981 env->ex = new java::lang::StringIndexOutOfBoundsException ();
983 _Jv_GetStringUTFRegion (str, start, len, buf);
987 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
989 jchar *result = _Jv_GetStringChars (str);
996 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1002 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1004 return array->length;
1008 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1011 // FIXME: exception processing.
1012 jarray result = JvNewObjectArray (length, elementClass, init);
1013 return (jarray) _Jv_JNI_NewLocalRef (env, result);
1017 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1019 jobject *elts = elements (array);
1020 return _Jv_JNI_NewLocalRef (env, elts[index]);
1024 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1027 // FIXME: exception processing.
1028 _Jv_CheckArrayStore (array, value);
1029 jobject *elts = elements (array);
1030 elts[index] = value;
1033 template<typename T, jclass K>
1035 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1037 // FIXME: exception processing.
1038 return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1039 _Jv_NewPrimArray (K, length));
1042 template<typename T>
1044 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1047 T *elts = elements (array);
1050 // We elect never to copy.
1053 mark_for_gc (array);
1057 template<typename T>
1059 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1060 T *, jint /* mode */)
1062 // Note that we ignore MODE. We can do this because we never copy
1063 // the array elements. My reading of the JNI documentation is that
1064 // this is an option for the implementor.
1065 unmark_for_gc (array);
1068 template<typename T>
1070 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1071 jsize start, jsize len,
1074 if (start < 0 || len >= array->length || start + len >= array->length)
1077 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1081 T *elts = elements (array) + start;
1082 memcpy (buf, elts, len * sizeof (T));
1086 template<typename T>
1088 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1089 jsize start, jsize len, T *buf)
1091 if (start < 0 || len >= array->length || start + len >= array->length)
1094 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1098 T *elts = elements (array) + start;
1099 memcpy (elts, buf, len * sizeof (T));
1104 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1107 // FIXME: does this work?
1108 jclass klass = array->getClass()->getComponentType();
1109 JvAssert (klass->isPrimitive ());
1110 char *r = _Jv_GetArrayElementFromElementType (array, klass);
1117 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1123 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1125 // FIXME: exception processing.
1126 jint r = _Jv_MonitorEnter (obj);
1131 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1133 // FIXME: exception processing.
1134 jint r = _Jv_MonitorExit (obj);
1140 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1143 // FIXME: exception processing.
1144 java::lang::reflect::Field *field = new java::lang::reflect::Field();
1145 field->declaringClass = cls;
1146 field->offset = (char*) fieldID - (char *) cls->fields;
1147 field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1148 return _Jv_JNI_NewLocalRef (env, field);
1153 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1155 using namespace java::lang::reflect;
1157 Field *field = reinterpret_cast<Field *> (f);
1158 return _Jv_FromReflectedField (field);
1162 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1165 using namespace java::lang::reflect;
1168 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1171 if (_Jv_equalUtf8Consts (id->name, init_name))
1174 Constructor *cons = new Constructor ();
1175 cons->offset = (char *) id - (char *) &klass->methods;
1176 cons->declaringClass = klass;
1181 Method *meth = new Method ();
1182 meth->offset = (char *) id - (char *) &klass->methods;
1183 meth->declaringClass = klass;
1187 return _Jv_JNI_NewLocalRef (env, result);
1191 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1193 using namespace java::lang::reflect;
1194 if ((&MethodClass)->isInstance (method))
1195 return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1197 _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1204 // Add a character to the buffer, encoding properly.
1206 add_char (char *buf, jchar c, int *here)
1210 buf[(*here)++] = '_';
1211 buf[(*here)++] = '1';
1215 buf[(*here)++] = '_';
1216 buf[(*here)++] = '2';
1220 buf[(*here)++] = '_';
1221 buf[(*here)++] = '3';
1224 buf[(*here)++] = '_';
1225 if ((c >= '0' && c <= '9')
1226 || (c >= 'a' && c <= 'z')
1227 || (c >= 'A' && c <= 'Z'))
1228 buf[(*here)++] = (char) c;
1231 // "Unicode" character.
1232 buf[(*here)++] = '_';
1233 buf[(*here)++] = '0';
1234 for (int i = 0; i < 4; ++i)
1237 buf[(*here) + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
1244 // Compute a mangled name for a native function. This computes the
1245 // long name, and also returns an index which indicates where a NUL
1246 // can be placed to create the short name. This function assumes that
1247 // the buffer is large enough for its results.
1249 mangled_name (jclass klass, _Jv_Utf8Const *func_name,
1250 _Jv_Utf8Const *signature, char *buf, int *long_start)
1252 strcpy (buf, "Java_");
1255 // Add fully qualified class name.
1256 jchar *chars = _Jv_GetStringChars (klass->getName ());
1257 jint len = klass->getName ()->length ();
1258 for (int i = 0; i < len; ++i)
1259 add_char (buf, chars[i], &here);
1261 // Don't use add_char because we need a literal `_'.
1264 const unsigned char *fn = (const unsigned char *) func_name->data;
1265 const unsigned char *limit = fn + func_name->length;
1266 for (int i = 0; ; ++i)
1268 int ch = UTF8_GET (fn, limit);
1271 add_char (buf, ch, &here);
1274 // This is where the long signature begins.
1279 const unsigned char *sig = (const unsigned char *) signature->data;
1280 limit = sig + signature->length;
1281 JvAssert (signature[0] == '(');
1282 for (int i = 1; ; ++i)
1284 int ch = UTF8_GET (sig, limit);
1285 if (ch == ')' || ch < 0)
1287 add_char (buf, ch, &here);
1293 // This function is the stub which is used to turn an ordinary (CNI)
1294 // method call into a JNI call.
1296 _Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this)
1298 _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
1301 _Jv_JNI_LocalFrame *frame
1302 = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1303 + FRAME_SIZE * sizeof (jobject));
1305 env.p = &_Jv_JNIFunctions;
1307 env.klass = _this->defining_class;
1310 frame->marker = true;
1312 frame->size = FRAME_SIZE;
1313 for (int i = 0; i < frame->size; ++i)
1314 frame->vec[i] = NULL;
1316 // FIXME: we should mark every reference parameter as a local. For
1317 // now we assume a conservative GC, and we assume that the
1318 // references are on the stack somewhere.
1320 // We cache the value that we find, of course, but if we don't find
1321 // a value we don't cache that fact -- we might subsequently load a
1322 // library which finds the function in question.
1323 if (_this->function == NULL)
1325 char buf[10 + 6 * (_this->self->name->length
1326 + _this->self->signature->length)];
1328 mangled_name (_this->defining_class, _this->self->name,
1329 _this->self->signature, buf, &long_start);
1330 char c = buf[long_start];
1331 buf[long_start] = '\0';
1332 _this->function = _Jv_FindSymbolInExecutable (buf);
1333 if (_this->function == NULL)
1335 buf[long_start] = c;
1336 _this->function = _Jv_FindSymbolInExecutable (buf);
1337 if (_this->function == NULL)
1339 jstring str = JvNewStringUTF (_this->self->name->data);
1340 JvThrow (new java::lang::AbstractMethodError (str));
1345 // The actual call to the JNI function.
1346 // FIXME: if this is a static function we must include the class!
1347 ffi_raw_call (cif, (void (*) (...)) _this->function, ret, args);
1351 _Jv_JNI_PopLocalFrame (&env, NULL);
1353 while (env.locals != frame);
1359 #endif /* INTERPRETER */
1363 #define NOT_IMPL NULL
1364 #define RESERVED NULL
1366 struct JNINativeInterface _Jv_JNIFunctions =
1373 _Jv_JNI_DefineClass,
1375 _Jv_JNI_FromReflectedMethod,
1376 _Jv_JNI_FromReflectedField,
1377 _Jv_JNI_ToReflectedMethod,
1378 _Jv_JNI_GetSuperclass,
1379 _Jv_JNI_IsAssignableFrom,
1380 _Jv_JNI_ToReflectedField,
1383 _Jv_JNI_ExceptionOccurred,
1384 _Jv_JNI_ExceptionDescribe,
1385 _Jv_JNI_ExceptionClear,
1388 _Jv_JNI_PushLocalFrame,
1389 _Jv_JNI_PopLocalFrame,
1390 _Jv_JNI_NewGlobalRef,
1391 _Jv_JNI_DeleteGlobalRef,
1392 _Jv_JNI_DeleteLocalRef,
1394 _Jv_JNI_IsSameObject,
1396 _Jv_JNI_NewLocalRef,
1397 _Jv_JNI_EnsureLocalCapacity,
1399 _Jv_JNI_AllocObject,
1403 _Jv_JNI_GetObjectClass,
1404 _Jv_JNI_IsInstanceOf,
1405 _Jv_JNI_GetAnyMethodID<false>,
1407 _Jv_JNI_CallMethod<jobject>,
1408 _Jv_JNI_CallMethodV<jobject>,
1409 _Jv_JNI_CallMethodA<jobject>,
1410 _Jv_JNI_CallMethod<jboolean>,
1411 _Jv_JNI_CallMethodV<jboolean>,
1412 _Jv_JNI_CallMethodA<jboolean>,
1413 _Jv_JNI_CallMethod<jbyte>,
1414 _Jv_JNI_CallMethodV<jbyte>,
1415 _Jv_JNI_CallMethodA<jbyte>,
1416 _Jv_JNI_CallMethod<jchar>,
1417 _Jv_JNI_CallMethodV<jchar>,
1418 _Jv_JNI_CallMethodA<jchar>,
1419 _Jv_JNI_CallMethod<jshort>,
1420 _Jv_JNI_CallMethodV<jshort>,
1421 _Jv_JNI_CallMethodA<jshort>,
1422 _Jv_JNI_CallMethod<jint>,
1423 _Jv_JNI_CallMethodV<jint>,
1424 _Jv_JNI_CallMethodA<jint>,
1425 _Jv_JNI_CallMethod<jlong>,
1426 _Jv_JNI_CallMethodV<jlong>,
1427 _Jv_JNI_CallMethodA<jlong>,
1428 _Jv_JNI_CallMethod<jfloat>,
1429 _Jv_JNI_CallMethodV<jfloat>,
1430 _Jv_JNI_CallMethodA<jfloat>,
1431 _Jv_JNI_CallMethod<jdouble>,
1432 _Jv_JNI_CallMethodV<jdouble>,
1433 _Jv_JNI_CallMethodA<jdouble>,
1434 _Jv_JNI_CallVoidMethod,
1435 _Jv_JNI_CallVoidMethodV,
1436 _Jv_JNI_CallVoidMethodA,
1438 // Nonvirtual method invocation functions follow.
1439 _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1440 _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1441 _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1442 _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1443 _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1444 _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1445 _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1446 _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1447 _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1448 _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1449 _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1450 _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1451 _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1452 _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1453 _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1454 _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1455 _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1456 _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1457 _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1458 _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1459 _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1460 _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1461 _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1462 _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1463 _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1464 _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1465 _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1466 _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1467 _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1468 _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1470 _Jv_JNI_GetAnyFieldID<false>,
1471 _Jv_JNI_GetField<jobject>,
1472 _Jv_JNI_GetField<jboolean>,
1473 _Jv_JNI_GetField<jbyte>,
1474 _Jv_JNI_GetField<jchar>,
1475 _Jv_JNI_GetField<jshort>,
1476 _Jv_JNI_GetField<jint>,
1477 _Jv_JNI_GetField<jlong>,
1478 _Jv_JNI_GetField<jfloat>,
1479 _Jv_JNI_GetField<jdouble>,
1489 _Jv_JNI_GetAnyMethodID<true>,
1491 _Jv_JNI_CallStaticMethod<jobject>,
1492 _Jv_JNI_CallStaticMethodV<jobject>,
1493 _Jv_JNI_CallStaticMethodA<jobject>,
1494 _Jv_JNI_CallStaticMethod<jboolean>,
1495 _Jv_JNI_CallStaticMethodV<jboolean>,
1496 _Jv_JNI_CallStaticMethodA<jboolean>,
1497 _Jv_JNI_CallStaticMethod<jbyte>,
1498 _Jv_JNI_CallStaticMethodV<jbyte>,
1499 _Jv_JNI_CallStaticMethodA<jbyte>,
1500 _Jv_JNI_CallStaticMethod<jchar>,
1501 _Jv_JNI_CallStaticMethodV<jchar>,
1502 _Jv_JNI_CallStaticMethodA<jchar>,
1503 _Jv_JNI_CallStaticMethod<jshort>,
1504 _Jv_JNI_CallStaticMethodV<jshort>,
1505 _Jv_JNI_CallStaticMethodA<jshort>,
1506 _Jv_JNI_CallStaticMethod<jint>,
1507 _Jv_JNI_CallStaticMethodV<jint>,
1508 _Jv_JNI_CallStaticMethodA<jint>,
1509 _Jv_JNI_CallStaticMethod<jlong>,
1510 _Jv_JNI_CallStaticMethodV<jlong>,
1511 _Jv_JNI_CallStaticMethodA<jlong>,
1512 _Jv_JNI_CallStaticMethod<jfloat>,
1513 _Jv_JNI_CallStaticMethodV<jfloat>,
1514 _Jv_JNI_CallStaticMethodA<jfloat>,
1515 _Jv_JNI_CallStaticMethod<jdouble>,
1516 _Jv_JNI_CallStaticMethodV<jdouble>,
1517 _Jv_JNI_CallStaticMethodA<jdouble>,
1518 _Jv_JNI_CallStaticVoidMethod,
1519 _Jv_JNI_CallStaticVoidMethodV,
1520 _Jv_JNI_CallStaticVoidMethodA,
1522 _Jv_JNI_GetAnyFieldID<true>,
1523 _Jv_JNI_GetStaticField<jobject>,
1524 _Jv_JNI_GetStaticField<jboolean>,
1525 _Jv_JNI_GetStaticField<jbyte>,
1526 _Jv_JNI_GetStaticField<jchar>,
1527 _Jv_JNI_GetStaticField<jshort>,
1528 _Jv_JNI_GetStaticField<jint>,
1529 _Jv_JNI_GetStaticField<jlong>,
1530 _Jv_JNI_GetStaticField<jfloat>,
1531 _Jv_JNI_GetStaticField<jdouble>,
1532 _Jv_JNI_SetStaticField,
1533 _Jv_JNI_SetStaticField,
1534 _Jv_JNI_SetStaticField,
1535 _Jv_JNI_SetStaticField,
1536 _Jv_JNI_SetStaticField,
1537 _Jv_JNI_SetStaticField,
1538 _Jv_JNI_SetStaticField,
1539 _Jv_JNI_SetStaticField,
1540 _Jv_JNI_SetStaticField,
1542 _Jv_JNI_GetStringLength,
1543 _Jv_JNI_GetStringChars,
1544 _Jv_JNI_ReleaseStringChars,
1545 _Jv_JNI_NewStringUTF,
1546 _Jv_JNI_GetStringUTFLength,
1547 _Jv_JNI_GetStringUTFChars,
1548 _Jv_JNI_ReleaseStringUTFChars,
1549 _Jv_JNI_GetArrayLength,
1550 _Jv_JNI_NewObjectArray,
1551 _Jv_JNI_GetObjectArrayElement,
1552 _Jv_JNI_SetObjectArrayElement,
1553 _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1554 _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1555 _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1556 _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1557 _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1558 _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1559 _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1560 _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
1561 _Jv_JNI_GetPrimitiveArrayElements,
1562 _Jv_JNI_GetPrimitiveArrayElements,
1563 _Jv_JNI_GetPrimitiveArrayElements,
1564 _Jv_JNI_GetPrimitiveArrayElements,
1565 _Jv_JNI_GetPrimitiveArrayElements,
1566 _Jv_JNI_GetPrimitiveArrayElements,
1567 _Jv_JNI_GetPrimitiveArrayElements,
1568 _Jv_JNI_GetPrimitiveArrayElements,
1569 _Jv_JNI_ReleasePrimitiveArrayElements,
1570 _Jv_JNI_ReleasePrimitiveArrayElements,
1571 _Jv_JNI_ReleasePrimitiveArrayElements,
1572 _Jv_JNI_ReleasePrimitiveArrayElements,
1573 _Jv_JNI_ReleasePrimitiveArrayElements,
1574 _Jv_JNI_ReleasePrimitiveArrayElements,
1575 _Jv_JNI_ReleasePrimitiveArrayElements,
1576 _Jv_JNI_ReleasePrimitiveArrayElements,
1577 _Jv_JNI_GetPrimitiveArrayRegion,
1578 _Jv_JNI_GetPrimitiveArrayRegion,
1579 _Jv_JNI_GetPrimitiveArrayRegion,
1580 _Jv_JNI_GetPrimitiveArrayRegion,
1581 _Jv_JNI_GetPrimitiveArrayRegion,
1582 _Jv_JNI_GetPrimitiveArrayRegion,
1583 _Jv_JNI_GetPrimitiveArrayRegion,
1584 _Jv_JNI_GetPrimitiveArrayRegion,
1585 _Jv_JNI_SetPrimitiveArrayRegion,
1586 _Jv_JNI_SetPrimitiveArrayRegion,
1587 _Jv_JNI_SetPrimitiveArrayRegion,
1588 _Jv_JNI_SetPrimitiveArrayRegion,
1589 _Jv_JNI_SetPrimitiveArrayRegion,
1590 _Jv_JNI_SetPrimitiveArrayRegion,
1591 _Jv_JNI_SetPrimitiveArrayRegion,
1592 _Jv_JNI_SetPrimitiveArrayRegion,
1593 NOT_IMPL /* RegisterNatives */,
1594 NOT_IMPL /* UnregisterNatives */,
1595 _Jv_JNI_MonitorEnter,
1596 _Jv_JNI_MonitorExit,
1597 NOT_IMPL /* GetJavaVM */,
1599 _Jv_JNI_GetStringRegion,
1600 _Jv_JNI_GetStringUTFRegion,
1601 _Jv_JNI_GetPrimitiveArrayCritical,
1602 _Jv_JNI_ReleasePrimitiveArrayCritical,
1603 _Jv_JNI_GetStringCritical,
1604 _Jv_JNI_ReleaseStringCritical,
1606 NOT_IMPL /* newweakglobalref */,
1607 NOT_IMPL /* deleteweakglobalref */,
1609 _Jv_JNI_ExceptionCheck