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/AbstractMethodError.h>
36 #include <java/lang/InstantiationException.h>
37 #include <java/lang/NoSuchFieldError.h>
38 #include <java/lang/NoSuchMethodError.h>
39 #include <java/lang/reflect/Constructor.h>
40 #include <java/lang/reflect/Method.h>
41 #include <java/lang/reflect/Modifier.h>
42 #include <java/lang/OutOfMemoryError.h>
43 #include <java/util/Hashtable.h>
44 #include <java/lang/Integer.h>
46 #include <gcj/method.h>
47 #include <gcj/field.h>
49 #include <java-interp.h>
51 #define ClassClass _CL_Q34java4lang5Class
52 extern java::lang::Class ClassClass;
53 #define ObjectClass _CL_Q34java4lang6Object
54 extern java::lang::Class ObjectClass;
56 #define MethodClass _CL_Q44java4lang7reflect6Method
57 extern java::lang::Class MethodClass;
59 // This enum is used to select different template instantiations in
60 // the invocation code.
69 // Forward declaration.
70 extern struct JNINativeInterface _Jv_JNIFunctions;
72 // Number of slots in the default frame. The VM must allow at least
76 // This structure is used to keep track of local references.
77 struct _Jv_JNI_LocalFrame
79 // This is true if this frame object represents a pushed frame (eg
80 // from PushLocalFrame).
83 // Number of elements in frame.
86 // Next frame in chain.
87 _Jv_JNI_LocalFrame *next;
89 // The elements. These are allocated using the C "struct hack".
93 // This holds a reference count for all local and global references.
94 static java::util::Hashtable *ref_table;
101 ref_table = new java::util::Hashtable;
104 // Tell the GC that a certain pointer is live.
106 mark_for_gc (jobject obj)
108 JvSynchronize sync (ref_table);
110 using namespace java::lang;
111 Integer *refcount = (Integer *) ref_table->get (obj);
112 jint val = (refcount == NULL) ? 0 : refcount->intValue ();
113 ref_table->put (obj, new Integer (val + 1));
118 unmark_for_gc (jobject obj)
120 JvSynchronize sync (ref_table);
122 using namespace java::lang;
123 Integer *refcount = (Integer *) ref_table->get (obj);
125 jint val = refcount->intValue () - 1;
127 ref_table->remove (obj);
129 ref_table->put (obj, new Integer (val));
135 _Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
142 _Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
148 _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
150 _Jv_JNI_LocalFrame *frame;
152 for (frame = env->locals; frame != NULL; frame = frame->next)
154 for (int i = 0; i < FRAME_SIZE; ++i)
156 if (frame->vec[i] == obj)
158 frame->vec[i] = NULL;
164 // Don't go past a marked frame.
165 JvAssert (! frame->marker);
172 _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
174 // It is easier to just always allocate a new frame of the requested
175 // size. This isn't the most efficient thing, but for now we don't
176 // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
178 _Jv_JNI_LocalFrame *frame
179 = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
180 + size * sizeof (jobject));
183 // FIXME: exception processing.
184 env->ex = new java::lang::OutOfMemoryError;
188 frame->marker = true;
190 memset (&frame->vec[0], 0, size * sizeof (jobject));
191 frame->next = env->locals;
198 _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
200 jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
204 // The new frame is on top.
205 env->locals->marker = true;
211 _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
213 // Try to find an open slot somewhere in the topmost frame.
214 _Jv_JNI_LocalFrame *frame = env->locals;
215 bool done = false, set = false;
216 while (frame != NULL && ! done)
218 for (int i = 0; i < frame->size; ++i)
219 if (frame->vec[i] == NULL)
230 // No slots, so we allocate a new frame. According to the spec
231 // we could just die here. FIXME: return value.
232 _Jv_JNI_EnsureLocalCapacity (env, 16);
233 // We know the first element of the new frame will be ok.
234 env->locals->vec[0] = obj;
242 _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
244 _Jv_JNI_LocalFrame *rf = env->locals;
247 while (rf != NULL && ! done)
249 for (int i = 0; i < rf->size; ++i)
250 if (rf->vec[i] != NULL)
251 unmark_for_gc (rf->vec[i]);
253 // If the frame we just freed is the marker frame, we are done.
256 _Jv_JNI_LocalFrame *n = rf->next;
257 // When N==NULL, we've reached the stack-allocated frame, and we
258 // must not free it. However, we must be sure to clear all its
259 // elements, since we might conceivably reuse it.
262 memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
270 return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
273 // This function is used from other template functions. It wraps the
274 // return value appropriately; we specialize it so that object returns
275 // are turned into local references.
278 wrap_value (JNIEnv *, T value)
285 wrap_value (JNIEnv *env, jobject value)
287 return _Jv_JNI_NewLocalRef (env, value);
293 _Jv_JNI_GetVersion (JNIEnv *)
295 return JNI_VERSION_1_2;
299 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
300 const jbyte *buf, jsize bufLen)
302 jbyteArray bytes = JvNewByteArray (bufLen);
303 jbyte *elts = elements (bytes);
304 memcpy (elts, buf, bufLen * sizeof (jbyte));
306 java::lang::ClassLoader *l
307 = reinterpret_cast<java::lang::ClassLoader *> (loader);
309 // FIXME: exception processing.
310 jclass result = l->defineClass (bytes, 0, bufLen);
311 return (jclass) _Jv_JNI_NewLocalRef (env, result);
315 _Jv_JNI_FindClass (JNIEnv *env, const char *name)
317 // FIXME: assume that NAME isn't too long.
318 int len = strlen (name);
320 for (int i = 0; i <= len; ++i)
321 s[i] = (name[i] == '/') ? '.' : name[i];
322 jstring n = JvNewStringUTF (s);
324 java::lang::ClassLoader *loader;
325 if (env->klass == NULL)
327 // FIXME: should use getBaseClassLoader, but we don't have that
329 loader = java::lang::ClassLoader::getSystemClassLoader ();
332 loader = env->klass->getClassLoader ();
334 // FIXME: exception processing.
335 jclass r = loader->findClass (n);
337 return (jclass) _Jv_JNI_NewLocalRef (env, r);
341 _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
343 return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
347 _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
349 return clazz1->isAssignableFrom (clazz2);
353 _Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
360 _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
362 using namespace java::lang::reflect;
364 JArray<jclass> *argtypes
365 = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
367 jclass *elts = elements (argtypes);
368 elts[0] = &StringClass;
370 // FIXME: exception processing.
371 Constructor *cons = clazz->getConstructor (argtypes);
373 jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
374 jobject *velts = elements (values);
375 velts[0] = JvNewStringUTF (message);
377 // FIXME: exception processing.
378 jobject obj = cons->newInstance (values);
380 env->ex = reinterpret_cast<jthrowable> (obj);
385 _Jv_JNI_ExceptionOccurred (JNIEnv *env)
387 return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
391 _Jv_JNI_ExceptionDescribe (JNIEnv *env)
394 env->ex->printStackTrace();
398 _Jv_JNI_ExceptionClear (JNIEnv *env)
404 _Jv_JNI_ExceptionCheck (JNIEnv *env)
406 return env->ex != NULL;
410 _Jv_JNI_FatalError (JNIEnv *, const char *message)
418 _Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
424 _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
427 using namespace java::lang::reflect;
428 if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
429 env->ex = new java::lang::InstantiationException ();
432 // FIXME: exception processing.
433 // FIXME: will this work for String?
434 obj = JvAllocObject (clazz);
437 return _Jv_JNI_NewLocalRef (env, obj);
441 _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
443 return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
447 _Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
449 return clazz->isInstance(obj);
455 // This section concerns method invocation.
458 template<jboolean is_static>
460 _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
461 const char *name, const char *sig)
463 // FIXME: exception processing.
464 _Jv_InitClass (clazz);
466 _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
467 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
469 JvAssert (! clazz->isPrimitive());
471 using namespace java::lang::reflect;
473 while (clazz != NULL)
475 jint count = JvNumMethods (clazz);
476 jmethodID meth = JvGetFirstMethod (clazz);
478 for (jint i = 0; i < count; ++i)
480 if (((is_static && Modifier::isStatic (meth->accflags))
481 || (! is_static && ! Modifier::isStatic (meth->accflags)))
482 && _Jv_equalUtf8Consts (meth->name, name_u)
483 && _Jv_equalUtf8Consts (meth->signature, sig_u))
486 meth = meth->getNextMethod();
489 clazz = clazz->getSuperclass ();
492 env->ex = new java::lang::NoSuchMethodError ();
496 // This is a helper function which turns a va_list into an array of
497 // `jvalue's. It needs signature information in order to do its work.
498 // The array of values must already be allocated.
500 array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
502 jclass *arg_elts = elements (arg_types);
503 for (int i = 0; i < arg_types->length; ++i)
505 if (arg_elts[i] == JvPrimClass (byte))
506 values[i].b = va_arg (vargs, jbyte);
507 else if (arg_elts[i] == JvPrimClass (short))
508 values[i].s = va_arg (vargs, jshort);
509 else if (arg_elts[i] == JvPrimClass (int))
510 values[i].i = va_arg (vargs, jint);
511 else if (arg_elts[i] == JvPrimClass (long))
512 values[i].j = va_arg (vargs, jlong);
513 else if (arg_elts[i] == JvPrimClass (float))
514 values[i].f = va_arg (vargs, jfloat);
515 else if (arg_elts[i] == JvPrimClass (double))
516 values[i].d = va_arg (vargs, jdouble);
517 else if (arg_elts[i] == JvPrimClass (boolean))
518 values[i].z = va_arg (vargs, jboolean);
519 else if (arg_elts[i] == JvPrimClass (char))
520 values[i].c = va_arg (vargs, jchar);
524 values[i].l = va_arg (vargs, jobject);
529 // This can call any sort of method: virtual, "nonvirtual", static, or
531 template<typename T, invocation_type style>
533 _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
534 jmethodID id, va_list vargs)
537 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
539 jclass decl_class = klass ? klass : obj->getClass ();
540 JvAssert (decl_class != NULL);
543 JArray<jclass> *arg_types;
544 // FIXME: exception processing.
545 _Jv_GetTypesFromSignature (id, decl_class,
546 &arg_types, &return_type);
548 jvalue args[arg_types->length];
549 array_from_valist (args, arg_types, vargs);
552 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
553 style == constructor,
554 arg_types, args, &result);
559 // We cheat a little here. FIXME.
560 return wrap_value (env, * (T *) &result);
563 template<typename T, invocation_type style>
565 _Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
566 jmethodID method, ...)
571 va_start (args, method);
572 result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
578 template<typename T, invocation_type style>
580 _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
581 jmethodID id, jvalue *args)
584 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
586 jclass decl_class = klass ? klass : obj->getClass ();
587 JvAssert (decl_class != NULL);
590 JArray<jclass> *arg_types;
591 // FIXME: exception processing.
592 _Jv_GetTypesFromSignature (id, decl_class,
593 &arg_types, &return_type);
596 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
597 style == constructor,
598 arg_types, args, &result);
603 // We cheat a little here. FIXME.
604 return wrap_value (env, * (T *) &result);
607 template<invocation_type style>
609 _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
610 jmethodID id, va_list vargs)
613 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
615 jclass decl_class = klass ? klass : obj->getClass ();
616 JvAssert (decl_class != NULL);
619 JArray<jclass> *arg_types;
620 // FIXME: exception processing.
621 _Jv_GetTypesFromSignature (id, decl_class,
622 &arg_types, &return_type);
624 jvalue args[arg_types->length];
625 array_from_valist (args, arg_types, vargs);
627 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
628 style == constructor,
629 arg_types, args, NULL);
635 template<invocation_type style>
637 _Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
638 jmethodID method, ...)
642 va_start (args, method);
643 _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
647 template<invocation_type style>
649 _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
650 jmethodID id, jvalue *args)
653 id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
655 jclass decl_class = klass ? klass : obj->getClass ();
656 JvAssert (decl_class != NULL);
659 JArray<jclass> *arg_types;
660 // FIXME: exception processing.
661 _Jv_GetTypesFromSignature (id, decl_class,
662 &arg_types, &return_type);
664 jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
665 style == constructor,
666 arg_types, args, NULL);
672 // Functions with this signature are used to implement functions in
673 // the CallMethod family.
676 _Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
678 return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
681 // Functions with this signature are used to implement functions in
682 // the CallMethod family.
685 _Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
691 result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
697 // Functions with this signature are used to implement functions in
698 // the CallMethod family.
701 _Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
703 return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
707 _Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
709 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
713 _Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
718 _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
723 _Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
725 _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
728 // Functions with this signature are used to implement functions in
729 // the CallStaticMethod family.
732 _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
733 jmethodID id, va_list args)
735 return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
738 // Functions with this signature are used to implement functions in
739 // the CallStaticMethod family.
742 _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
748 result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
755 // Functions with this signature are used to implement functions in
756 // the CallStaticMethod family.
759 _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
762 return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
766 _Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
769 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
773 _Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
778 _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
783 _Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
786 _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
790 _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
791 jmethodID id, va_list args)
793 return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
798 _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
804 result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
812 _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
815 return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
823 _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
825 T *ptr = (T *) ((char *) obj + field->getOffset ());
826 return wrap_value (env, *ptr);
831 _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
833 T *ptr = (T *) ((char *) obj + field->getOffset ());
837 template<jboolean is_static>
839 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
840 const char *name, const char *sig)
842 // FIXME: exception processing.
843 _Jv_InitClass (clazz);
845 _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
847 jclass field_class = NULL;
849 field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
852 _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
853 field_class = _Jv_FindClass (sig_u, NULL);
856 // FIXME: what if field_class == NULL?
858 while (clazz != NULL)
860 jint count = (is_static
861 ? JvNumStaticFields (clazz)
862 : JvNumInstanceFields (clazz));
863 jfieldID field = (is_static
864 ? JvGetFirstStaticField (clazz)
865 : JvGetFirstInstanceField (clazz));
866 for (jint i = 0; i < count; ++i)
868 // The field is resolved as a side effect of class
870 JvAssert (field->isResolved ());
872 _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
874 if (_Jv_equalUtf8Consts (f_name, a_name)
875 && field->getClass() == field_class)
878 field = field->getNextField ();
881 clazz = clazz->getSuperclass ();
884 env->ex = new java::lang::NoSuchFieldError ();
890 _Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
892 T *ptr = (T *) field->u.addr;
893 return wrap_value (env, *ptr);
898 _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
900 T *ptr = (T *) field->u.addr;
905 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
907 // FIXME: exception processing.
908 jstring r = _Jv_NewString (unichars, len);
909 return (jstring) _Jv_JNI_NewLocalRef (env, r);
913 _Jv_JNI_GetStringLength (JNIEnv *, jstring string)
915 return string->length();
919 _Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
921 jchar *result = _Jv_GetStringChars (string);
922 mark_for_gc (string);
925 return (const jchar *) result;
929 _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
931 unmark_for_gc (string);
935 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
937 // FIXME: exception processing.
938 jstring result = JvNewStringUTF (bytes);
939 return (jstring) _Jv_JNI_NewLocalRef (env, result);
943 _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
945 return JvGetStringUTFLength (string);
949 _Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
951 jsize len = JvGetStringUTFLength (string);
952 // FIXME: exception processing.
953 char *r = (char *) _Jv_Malloc (len + 1);
954 JvGetStringUTFRegion (string, 0, len, r);
960 return (const char *) r;
964 _Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
966 _Jv_Free ((void *) utf);
970 _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
973 jchar *result = _Jv_GetStringChars (string);
974 if (start < 0 || start > string->length ()
975 || len < 0 || start + len > string->length ())
976 env->ex = new java::lang::StringIndexOutOfBoundsException ();
978 memcpy (buf, &result[start], len * sizeof (jchar));
982 _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
983 jsize len, char *buf)
985 if (start < 0 || start > str->length ()
986 || len < 0 || start + len > str->length ())
987 env->ex = new java::lang::StringIndexOutOfBoundsException ();
989 _Jv_GetStringUTFRegion (str, start, len, buf);
993 _Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
995 jchar *result = _Jv_GetStringChars (str);
1002 _Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
1008 _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
1010 return array->length;
1014 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
1017 // FIXME: exception processing.
1018 jarray result = JvNewObjectArray (length, elementClass, init);
1019 return (jarray) _Jv_JNI_NewLocalRef (env, result);
1023 _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
1025 jobject *elts = elements (array);
1026 return _Jv_JNI_NewLocalRef (env, elts[index]);
1030 _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
1033 // FIXME: exception processing.
1034 _Jv_CheckArrayStore (array, value);
1035 jobject *elts = elements (array);
1036 elts[index] = value;
1039 template<typename T, jclass K>
1041 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
1043 // FIXME: exception processing.
1044 return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
1045 _Jv_NewPrimArray (K, length));
1048 template<typename T>
1050 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1053 T *elts = elements (array);
1056 // We elect never to copy.
1059 mark_for_gc (array);
1063 template<typename T>
1065 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
1066 T *, jint /* mode */)
1068 // Note that we ignore MODE. We can do this because we never copy
1069 // the array elements. My reading of the JNI documentation is that
1070 // this is an option for the implementor.
1071 unmark_for_gc (array);
1074 template<typename T>
1076 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1077 jsize start, jsize len,
1080 if (start < 0 || len >= array->length || start + len >= array->length)
1083 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1087 T *elts = elements (array) + start;
1088 memcpy (buf, elts, len * sizeof (T));
1092 template<typename T>
1094 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
1095 jsize start, jsize len, T *buf)
1097 if (start < 0 || len >= array->length || start + len >= array->length)
1100 env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
1104 T *elts = elements (array) + start;
1105 memcpy (elts, buf, len * sizeof (T));
1110 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
1113 // FIXME: does this work?
1114 jclass klass = array->getClass()->getComponentType();
1115 JvAssert (klass->isPrimitive ());
1116 char *r = _Jv_GetArrayElementFromElementType (array, klass);
1123 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
1129 _Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
1131 // FIXME: exception processing.
1132 jint r = _Jv_MonitorEnter (obj);
1137 _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
1139 // FIXME: exception processing.
1140 jint r = _Jv_MonitorExit (obj);
1146 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
1149 // FIXME: exception processing.
1150 java::lang::reflect::Field *field = new java::lang::reflect::Field();
1151 field->declaringClass = cls;
1152 field->offset = (char*) fieldID - (char *) cls->fields;
1153 field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
1154 return _Jv_JNI_NewLocalRef (env, field);
1159 _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
1161 using namespace java::lang::reflect;
1163 Field *field = reinterpret_cast<Field *> (f);
1164 return _Jv_FromReflectedField (field);
1168 _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
1171 using namespace java::lang::reflect;
1174 static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
1177 if (_Jv_equalUtf8Consts (id->name, init_name))
1180 Constructor *cons = new Constructor ();
1181 cons->offset = (char *) id - (char *) &klass->methods;
1182 cons->declaringClass = klass;
1187 Method *meth = new Method ();
1188 meth->offset = (char *) id - (char *) &klass->methods;
1189 meth->declaringClass = klass;
1193 return _Jv_JNI_NewLocalRef (env, result);
1197 _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
1199 using namespace java::lang::reflect;
1200 if ((&MethodClass)->isInstance (method))
1201 return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
1203 _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
1208 // Add a character to the buffer, encoding properly.
1210 add_char (char *buf, jchar c, int *here)
1214 buf[(*here)++] = '_';
1215 buf[(*here)++] = '1';
1219 buf[(*here)++] = '_';
1220 buf[(*here)++] = '2';
1224 buf[(*here)++] = '_';
1225 buf[(*here)++] = '3';
1228 buf[(*here)++] = '_';
1229 if ((c >= '0' && c <= '9')
1230 || (c >= 'a' && c <= 'z')
1231 || (c >= 'A' && c <= 'Z'))
1232 buf[(*here)++] = (char) c;
1235 // "Unicode" character.
1236 buf[(*here)++] = '_';
1237 buf[(*here)++] = '0';
1238 for (int i = 0; i < 4; ++i)
1241 buf[(*here) + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
1248 // Compute a mangled name for a native function. This computes the
1249 // long name, and also returns an index which indicates where a NUL
1250 // can be placed to create the short name. This function assumes that
1251 // the buffer is large enough for its results.
1253 mangled_name (jclass klass, _Jv_Utf8Const *func_name,
1254 _Jv_Utf8Const *signature, char *buf, int *long_start)
1256 strcpy (buf, "Java_");
1259 // Add fully qualified class name.
1260 jchar *chars = _Jv_GetStringChars (klass->getName ());
1261 jint len = klass->getName ()->length ();
1262 for (int i = 0; i < len; ++i)
1263 add_char (buf, chars[i], &here);
1265 // Don't use add_char because we need a literal `_'.
1268 const unsigned char *fn = (const unsigned char *) func_name->data;
1269 const unsigned char *limit = fn + func_name->length;
1270 for (int i = 0; ; ++i)
1272 int ch = UTF8_GET (fn, limit);
1275 add_char (buf, ch, &here);
1278 // This is where the long signature begins.
1283 const unsigned char *sig = (const unsigned char *) signature->data;
1284 limit = sig + signature->length;
1285 JvAssert (signature[0] == '(');
1286 for (int i = 1; ; ++i)
1288 int ch = UTF8_GET (sig, limit);
1289 if (ch == ')' || ch < 0)
1291 add_char (buf, ch, &here);
1297 // This function is the stub which is used to turn an ordinary (CNI)
1298 // method call into a JNI call.
1300 _Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this)
1302 _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
1305 _Jv_JNI_LocalFrame *frame
1306 = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
1307 + FRAME_SIZE * sizeof (jobject));
1309 env.p = &_Jv_JNIFunctions;
1311 env.klass = _this->defining_class;
1314 frame->marker = true;
1316 frame->size = FRAME_SIZE;
1317 for (int i = 0; i < frame->size; ++i)
1318 frame->vec[i] = NULL;
1320 // FIXME: we should mark every reference parameter as a local. For
1321 // now we assume a conservative GC, and we assume that the
1322 // references are on the stack somewhere.
1324 // We cache the value that we find, of course, but if we don't find
1325 // a value we don't cache that fact -- we might subsequently load a
1326 // library which finds the function in question.
1327 if (_this->function == NULL)
1329 char buf[10 + 6 * (_this->self->name->length
1330 + _this->self->signature->length)];
1332 mangled_name (_this->defining_class, _this->self->name,
1333 _this->self->signature, buf, &long_start);
1334 char c = buf[long_start];
1335 buf[long_start] = '\0';
1336 _this->function = _Jv_FindSymbolInExecutable (buf);
1337 if (_this->function == NULL)
1339 buf[long_start] = c;
1340 _this->function = _Jv_FindSymbolInExecutable (buf);
1341 if (_this->function == NULL)
1343 jstring str = JvNewStringUTF (_this->self->name->data);
1344 JvThrow (new java::lang::AbstractMethodError (str));
1349 // The actual call to the JNI function.
1350 ffi_raw_call (cif, (void (*) (...)) _this->function, ret, args);
1354 _Jv_JNI_PopLocalFrame (&env, NULL);
1356 while (env.locals != frame);
1364 #define NOT_IMPL NULL
1365 #define RESERVED NULL
1367 struct JNINativeInterface _Jv_JNIFunctions =
1374 _Jv_JNI_DefineClass,
1376 _Jv_JNI_FromReflectedMethod,
1377 _Jv_JNI_FromReflectedField,
1378 _Jv_JNI_ToReflectedMethod,
1379 _Jv_JNI_GetSuperclass,
1380 _Jv_JNI_IsAssignableFrom,
1381 _Jv_JNI_ToReflectedField,
1384 _Jv_JNI_ExceptionOccurred,
1385 _Jv_JNI_ExceptionDescribe,
1386 _Jv_JNI_ExceptionClear,
1389 _Jv_JNI_PushLocalFrame,
1390 _Jv_JNI_PopLocalFrame,
1391 _Jv_JNI_NewGlobalRef,
1392 _Jv_JNI_DeleteGlobalRef,
1393 _Jv_JNI_DeleteLocalRef,
1395 _Jv_JNI_IsSameObject,
1397 _Jv_JNI_NewLocalRef,
1398 _Jv_JNI_EnsureLocalCapacity,
1400 _Jv_JNI_AllocObject,
1404 _Jv_JNI_GetObjectClass,
1405 _Jv_JNI_IsInstanceOf,
1406 _Jv_JNI_GetAnyMethodID<false>,
1408 _Jv_JNI_CallMethod<jobject>,
1409 _Jv_JNI_CallMethodV<jobject>,
1410 _Jv_JNI_CallMethodA<jobject>,
1411 _Jv_JNI_CallMethod<jboolean>,
1412 _Jv_JNI_CallMethodV<jboolean>,
1413 _Jv_JNI_CallMethodA<jboolean>,
1414 _Jv_JNI_CallMethod<jbyte>,
1415 _Jv_JNI_CallMethodV<jbyte>,
1416 _Jv_JNI_CallMethodA<jbyte>,
1417 _Jv_JNI_CallMethod<jchar>,
1418 _Jv_JNI_CallMethodV<jchar>,
1419 _Jv_JNI_CallMethodA<jchar>,
1420 _Jv_JNI_CallMethod<jshort>,
1421 _Jv_JNI_CallMethodV<jshort>,
1422 _Jv_JNI_CallMethodA<jshort>,
1423 _Jv_JNI_CallMethod<jint>,
1424 _Jv_JNI_CallMethodV<jint>,
1425 _Jv_JNI_CallMethodA<jint>,
1426 _Jv_JNI_CallMethod<jlong>,
1427 _Jv_JNI_CallMethodV<jlong>,
1428 _Jv_JNI_CallMethodA<jlong>,
1429 _Jv_JNI_CallMethod<jfloat>,
1430 _Jv_JNI_CallMethodV<jfloat>,
1431 _Jv_JNI_CallMethodA<jfloat>,
1432 _Jv_JNI_CallMethod<jdouble>,
1433 _Jv_JNI_CallMethodV<jdouble>,
1434 _Jv_JNI_CallMethodA<jdouble>,
1435 _Jv_JNI_CallVoidMethod,
1436 _Jv_JNI_CallVoidMethodV,
1437 _Jv_JNI_CallVoidMethodA,
1439 // Nonvirtual method invocation functions follow.
1440 _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
1441 _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
1442 _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
1443 _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
1444 _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
1445 _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
1446 _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
1447 _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
1448 _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
1449 _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
1450 _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
1451 _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
1452 _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
1453 _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
1454 _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
1455 _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
1456 _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
1457 _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
1458 _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
1459 _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
1460 _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
1461 _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
1462 _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
1463 _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
1464 _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
1465 _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
1466 _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
1467 _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
1468 _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
1469 _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
1471 _Jv_JNI_GetAnyFieldID<false>,
1472 _Jv_JNI_GetField<jobject>,
1473 _Jv_JNI_GetField<jboolean>,
1474 _Jv_JNI_GetField<jbyte>,
1475 _Jv_JNI_GetField<jchar>,
1476 _Jv_JNI_GetField<jshort>,
1477 _Jv_JNI_GetField<jint>,
1478 _Jv_JNI_GetField<jlong>,
1479 _Jv_JNI_GetField<jfloat>,
1480 _Jv_JNI_GetField<jdouble>,
1490 _Jv_JNI_GetAnyMethodID<true>,
1492 _Jv_JNI_CallStaticMethod<jobject>,
1493 _Jv_JNI_CallStaticMethodV<jobject>,
1494 _Jv_JNI_CallStaticMethodA<jobject>,
1495 _Jv_JNI_CallStaticMethod<jboolean>,
1496 _Jv_JNI_CallStaticMethodV<jboolean>,
1497 _Jv_JNI_CallStaticMethodA<jboolean>,
1498 _Jv_JNI_CallStaticMethod<jbyte>,
1499 _Jv_JNI_CallStaticMethodV<jbyte>,
1500 _Jv_JNI_CallStaticMethodA<jbyte>,
1501 _Jv_JNI_CallStaticMethod<jchar>,
1502 _Jv_JNI_CallStaticMethodV<jchar>,
1503 _Jv_JNI_CallStaticMethodA<jchar>,
1504 _Jv_JNI_CallStaticMethod<jshort>,
1505 _Jv_JNI_CallStaticMethodV<jshort>,
1506 _Jv_JNI_CallStaticMethodA<jshort>,
1507 _Jv_JNI_CallStaticMethod<jint>,
1508 _Jv_JNI_CallStaticMethodV<jint>,
1509 _Jv_JNI_CallStaticMethodA<jint>,
1510 _Jv_JNI_CallStaticMethod<jlong>,
1511 _Jv_JNI_CallStaticMethodV<jlong>,
1512 _Jv_JNI_CallStaticMethodA<jlong>,
1513 _Jv_JNI_CallStaticMethod<jfloat>,
1514 _Jv_JNI_CallStaticMethodV<jfloat>,
1515 _Jv_JNI_CallStaticMethodA<jfloat>,
1516 _Jv_JNI_CallStaticMethod<jdouble>,
1517 _Jv_JNI_CallStaticMethodV<jdouble>,
1518 _Jv_JNI_CallStaticMethodA<jdouble>,
1519 _Jv_JNI_CallStaticVoidMethod,
1520 _Jv_JNI_CallStaticVoidMethodV,
1521 _Jv_JNI_CallStaticVoidMethodA,
1523 _Jv_JNI_GetAnyFieldID<true>,
1524 _Jv_JNI_GetStaticField<jobject>,
1525 _Jv_JNI_GetStaticField<jboolean>,
1526 _Jv_JNI_GetStaticField<jbyte>,
1527 _Jv_JNI_GetStaticField<jchar>,
1528 _Jv_JNI_GetStaticField<jshort>,
1529 _Jv_JNI_GetStaticField<jint>,
1530 _Jv_JNI_GetStaticField<jlong>,
1531 _Jv_JNI_GetStaticField<jfloat>,
1532 _Jv_JNI_GetStaticField<jdouble>,
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,
1541 _Jv_JNI_SetStaticField,
1543 _Jv_JNI_GetStringLength,
1544 _Jv_JNI_GetStringChars,
1545 _Jv_JNI_ReleaseStringChars,
1546 _Jv_JNI_NewStringUTF,
1547 _Jv_JNI_GetStringUTFLength,
1548 _Jv_JNI_GetStringUTFChars,
1549 _Jv_JNI_ReleaseStringUTFChars,
1550 _Jv_JNI_GetArrayLength,
1551 _Jv_JNI_NewObjectArray,
1552 _Jv_JNI_GetObjectArrayElement,
1553 _Jv_JNI_SetObjectArrayElement,
1554 _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
1555 _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
1556 _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
1557 _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
1558 _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
1559 _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
1560 _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
1561 _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
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_GetPrimitiveArrayElements,
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_ReleasePrimitiveArrayElements,
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_GetPrimitiveArrayRegion,
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 _Jv_JNI_SetPrimitiveArrayRegion,
1594 NOT_IMPL /* RegisterNatives */,
1595 NOT_IMPL /* UnregisterNatives */,
1596 _Jv_JNI_MonitorEnter,
1597 _Jv_JNI_MonitorExit,
1598 NOT_IMPL /* GetJavaVM */,
1600 _Jv_JNI_GetStringRegion,
1601 _Jv_JNI_GetStringUTFRegion,
1602 _Jv_JNI_GetPrimitiveArrayCritical,
1603 _Jv_JNI_ReleasePrimitiveArrayCritical,
1604 _Jv_JNI_GetStringCritical,
1605 _Jv_JNI_ReleaseStringCritical,
1607 NOT_IMPL /* newweakglobalref */,
1608 NOT_IMPL /* deleteweakglobalref */,
1610 _Jv_JNI_ExceptionCheck