1 // jni.cc - JNI implementation, including the jump table.
3 /* Copyright (C) 1998, 1999, 2000 Free Software Foundation
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>
27 #include <java/lang/Class.h>
28 #include <java/lang/ClassLoader.h>
29 #include <java/lang/Throwable.h>
30 #include <java/lang/ArrayIndexOutOfBoundsException.h>
31 #include <java/lang/StringIndexOutOfBoundsException.h>
32 #include <java/lang/AbstractMethodError.h>
33 #include <java/lang/InstantiationException.h>
34 #include <java/lang/NoSuchFieldError.h>
35 #include <java/lang/NoSuchMethodError.h>
36 #include <java/lang/reflect/Constructor.h>
37 #include <java/lang/reflect/Method.h>
38 #include <java/lang/reflect/Modifier.h>
39 #include <java/lang/OutOfMemoryError.h>
40 #include <java/util/Hashtable.h>
41 #include <java/lang/Integer.h>
42 #include <java/lang/ThreadGroup.h>
43 #include <gnu/gcj/jni/NativeThread.h>
45 #include <gcj/method.h>
46 #include <gcj/field.h>
48 #include <java-interp.h>
50 // FIXME: remove these defines.
51 #define ClassClass java::lang::Class::class$
52 #define ObjectClass java::lang::Object::class$
53 #define ThrowableClass java::lang::Throwable::class$
54 #define MethodClass java::lang::reflect::Method::class$
55 #define ThreadGroupClass java::lang::ThreadGroup::class$
56 #define NativeThreadClass gnu::gcj::jni::NativeThread::class$
58 // This enum is used to select different template instantiations in
59 // the invocation code.
68 // Forward declarations.
69 extern struct JNINativeInterface _Jv_JNIFunctions
;
70 extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions
;
72 // Number of slots in the default frame. The VM must allow at least
76 // Mark value indicating this is an overflow frame.
78 // Mark value indicating this is a user frame.
80 // Mark value indicating this is a system frame.
83 // This structure is used to keep track of local references.
84 struct _Jv_JNI_LocalFrame
86 // This is true if this frame object represents a pushed frame (eg
87 // from PushLocalFrame).
90 // Number of elements in frame.
93 // Next frame in chain.
94 _Jv_JNI_LocalFrame
*next
;
96 // The elements. These are allocated using the C "struct hack".
100 // This holds a reference count for all local and global references.
101 static java::util::Hashtable
*ref_table
;
104 static JavaVM
*the_vm
;
107 // The only JVMPI interface description.
108 static JVMPI_Interface _Jv_JVMPI_Interface
;
111 jvmpiEnableEvent (jint event_type
, void *)
115 case JVMPI_EVENT_OBJECT_ALLOC
:
116 _Jv_JVMPI_Notify_OBJECT_ALLOC
= _Jv_JVMPI_Interface
.NotifyEvent
;
119 case JVMPI_EVENT_THREAD_START
:
120 _Jv_JVMPI_Notify_THREAD_START
= _Jv_JVMPI_Interface
.NotifyEvent
;
123 case JVMPI_EVENT_THREAD_END
:
124 _Jv_JVMPI_Notify_THREAD_END
= _Jv_JVMPI_Interface
.NotifyEvent
;
128 return JVMPI_NOT_AVAILABLE
;
131 return JVMPI_SUCCESS
;
135 jvmpiDisableEvent (jint event_type
, void *)
139 case JVMPI_EVENT_OBJECT_ALLOC
:
140 _Jv_JVMPI_Notify_OBJECT_ALLOC
= NULL
;
144 return JVMPI_NOT_AVAILABLE
;
147 return JVMPI_SUCCESS
;
156 ref_table
= new java::util::Hashtable
;
159 _Jv_JVMPI_Interface
.version
= 1;
160 _Jv_JVMPI_Interface
.EnableEvent
= &jvmpiEnableEvent
;
161 _Jv_JVMPI_Interface
.DisableEvent
= &jvmpiDisableEvent
;
162 _Jv_JVMPI_Interface
.EnableGC
= &_Jv_EnableGC
;
163 _Jv_JVMPI_Interface
.DisableGC
= &_Jv_DisableGC
;
164 _Jv_JVMPI_Interface
.RunGC
= &_Jv_RunGC
;
168 // Tell the GC that a certain pointer is live.
170 mark_for_gc (jobject obj
)
172 JvSynchronize
sync (ref_table
);
174 using namespace java::lang
;
175 Integer
*refcount
= (Integer
*) ref_table
->get (obj
);
176 jint val
= (refcount
== NULL
) ? 0 : refcount
->intValue ();
177 // FIXME: what about out of memory error?
178 ref_table
->put (obj
, new Integer (val
+ 1));
183 unmark_for_gc (jobject obj
)
185 JvSynchronize
sync (ref_table
);
187 using namespace java::lang
;
188 Integer
*refcount
= (Integer
*) ref_table
->get (obj
);
190 jint val
= refcount
->intValue () - 1;
192 ref_table
->remove (obj
);
194 // FIXME: what about out of memory error?
195 ref_table
->put (obj
, new Integer (val
));
201 _Jv_JNI_NewGlobalRef (JNIEnv
*, jobject obj
)
208 _Jv_JNI_DeleteGlobalRef (JNIEnv
*, jobject obj
)
214 _Jv_JNI_DeleteLocalRef (JNIEnv
*env
, jobject obj
)
216 _Jv_JNI_LocalFrame
*frame
;
218 for (frame
= env
->locals
; frame
!= NULL
; frame
= frame
->next
)
220 for (int i
= 0; i
< FRAME_SIZE
; ++i
)
222 if (frame
->vec
[i
] == obj
)
224 frame
->vec
[i
] = NULL
;
230 // Don't go past a marked frame.
231 JvAssert (frame
->marker
== MARK_NONE
);
238 _Jv_JNI_EnsureLocalCapacity (JNIEnv
*env
, jint size
)
240 // It is easier to just always allocate a new frame of the requested
241 // size. This isn't the most efficient thing, but for now we don't
242 // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
244 _Jv_JNI_LocalFrame
*frame
;
247 frame
= (_Jv_JNI_LocalFrame
*) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame
)
248 + size
* sizeof (jobject
));
256 frame
->marker
= MARK_NONE
;
258 memset (&frame
->vec
[0], 0, size
* sizeof (jobject
));
259 frame
->next
= env
->locals
;
266 _Jv_JNI_PushLocalFrame (JNIEnv
*env
, jint size
)
268 jint r
= _Jv_JNI_EnsureLocalCapacity (env
, size
);
272 // The new frame is on top.
273 env
->locals
->marker
= MARK_USER
;
279 _Jv_JNI_NewLocalRef (JNIEnv
*env
, jobject obj
)
281 // Try to find an open slot somewhere in the topmost frame.
282 _Jv_JNI_LocalFrame
*frame
= env
->locals
;
283 bool done
= false, set
= false;
284 while (frame
!= NULL
&& ! done
)
286 for (int i
= 0; i
< frame
->size
; ++i
)
287 if (frame
->vec
[i
] == NULL
)
298 // No slots, so we allocate a new frame. According to the spec
299 // we could just die here. FIXME: return value.
300 _Jv_JNI_EnsureLocalCapacity (env
, 16);
301 // We know the first element of the new frame will be ok.
302 env
->locals
->vec
[0] = obj
;
310 _Jv_JNI_PopLocalFrame (JNIEnv
*env
, jobject result
, int stop
)
312 _Jv_JNI_LocalFrame
*rf
= env
->locals
;
315 while (rf
!= NULL
&& ! done
)
317 for (int i
= 0; i
< rf
->size
; ++i
)
318 if (rf
->vec
[i
] != NULL
)
319 unmark_for_gc (rf
->vec
[i
]);
321 // If the frame we just freed is the marker frame, we are done.
322 done
= (rf
->marker
== stop
);
324 _Jv_JNI_LocalFrame
*n
= rf
->next
;
325 // When N==NULL, we've reached the stack-allocated frame, and we
326 // must not free it. However, we must be sure to clear all its
327 // elements, since we might conceivably reuse it.
330 memset (&rf
->vec
[0], 0, rf
->size
* sizeof (jobject
));
338 return result
== NULL
? NULL
: _Jv_JNI_NewLocalRef (env
, result
);
342 _Jv_JNI_PopLocalFrame (JNIEnv
*env
, jobject result
)
344 return _Jv_JNI_PopLocalFrame (env
, result
, MARK_USER
);
347 // Pop a `system' frame from the stack. This is `extern "C"' as it is
348 // used by the compiler.
350 _Jv_JNI_PopSystemFrame (JNIEnv
*env
)
352 _Jv_JNI_PopLocalFrame (env
, NULL
, MARK_SYSTEM
);
356 jthrowable t
= env
->ex
;
362 // This function is used from other template functions. It wraps the
363 // return value appropriately; we specialize it so that object returns
364 // are turned into local references.
367 wrap_value (JNIEnv
*, T value
)
374 wrap_value (JNIEnv
*env
, jobject value
)
376 return value
== NULL
? value
: _Jv_JNI_NewLocalRef (env
, value
);
382 _Jv_JNI_GetVersion (JNIEnv
*)
384 return JNI_VERSION_1_2
;
388 _Jv_JNI_DefineClass (JNIEnv
*env
, jobject loader
,
389 const jbyte
*buf
, jsize bufLen
)
393 jbyteArray bytes
= JvNewByteArray (bufLen
);
395 jbyte
*elts
= elements (bytes
);
396 memcpy (elts
, buf
, bufLen
* sizeof (jbyte
));
398 java::lang::ClassLoader
*l
399 = reinterpret_cast<java::lang::ClassLoader
*> (loader
);
401 jclass result
= l
->defineClass (bytes
, 0, bufLen
);
402 return (jclass
) wrap_value (env
, result
);
412 _Jv_JNI_FindClass (JNIEnv
*env
, const char *name
)
414 // FIXME: assume that NAME isn't too long.
415 int len
= strlen (name
);
417 for (int i
= 0; i
<= len
; ++i
)
418 s
[i
] = (name
[i
] == '/') ? '.' : name
[i
];
423 // This might throw an out of memory exception.
424 jstring n
= JvNewStringUTF (s
);
426 java::lang::ClassLoader
*loader
= NULL
;
427 if (env
->klass
!= NULL
)
428 loader
= env
->klass
->getClassLoader ();
432 // FIXME: should use getBaseClassLoader, but we don't have that
434 loader
= java::lang::ClassLoader::getSystemClassLoader ();
437 r
= loader
->loadClass (n
);
444 return (jclass
) wrap_value (env
, r
);
448 _Jv_JNI_GetSuperclass (JNIEnv
*env
, jclass clazz
)
450 return (jclass
) wrap_value (env
, clazz
->getSuperclass ());
454 _Jv_JNI_IsAssignableFrom(JNIEnv
*, jclass clazz1
, jclass clazz2
)
456 return clazz1
->isAssignableFrom (clazz2
);
460 _Jv_JNI_Throw (JNIEnv
*env
, jthrowable obj
)
462 // We check in case the user did some funky cast.
463 JvAssert (obj
!= NULL
&& (&ThrowableClass
)->isInstance (obj
));
469 _Jv_JNI_ThrowNew (JNIEnv
*env
, jclass clazz
, const char *message
)
471 using namespace java::lang::reflect
;
473 JvAssert ((&ThrowableClass
)->isAssignableFrom (clazz
));
478 JArray
<jclass
> *argtypes
479 = (JArray
<jclass
> *) JvNewObjectArray (1, &ClassClass
, NULL
);
481 jclass
*elts
= elements (argtypes
);
482 elts
[0] = &StringClass
;
484 Constructor
*cons
= clazz
->getConstructor (argtypes
);
486 jobjectArray values
= JvNewObjectArray (1, &StringClass
, NULL
);
487 jobject
*velts
= elements (values
);
488 velts
[0] = JvNewStringUTF (message
);
490 jobject obj
= cons
->newInstance (values
);
492 env
->ex
= reinterpret_cast<jthrowable
> (obj
);
504 _Jv_JNI_ExceptionOccurred (JNIEnv
*env
)
506 return (jthrowable
) wrap_value (env
, env
->ex
);
510 _Jv_JNI_ExceptionDescribe (JNIEnv
*env
)
513 env
->ex
->printStackTrace();
517 _Jv_JNI_ExceptionClear (JNIEnv
*env
)
523 _Jv_JNI_ExceptionCheck (JNIEnv
*env
)
525 return env
->ex
!= NULL
;
529 _Jv_JNI_FatalError (JNIEnv
*, const char *message
)
537 _Jv_JNI_IsSameObject (JNIEnv
*, jobject obj1
, jobject obj2
)
543 _Jv_JNI_AllocObject (JNIEnv
*env
, jclass clazz
)
546 using namespace java::lang::reflect
;
550 JvAssert (clazz
&& ! clazz
->isArray ());
551 if (clazz
->isInterface() || Modifier::isAbstract(clazz
->getModifiers()))
552 env
->ex
= new java::lang::InstantiationException ();
555 // FIXME: will this work for String?
556 obj
= JvAllocObject (clazz
);
564 return wrap_value (env
, obj
);
568 _Jv_JNI_GetObjectClass (JNIEnv
*env
, jobject obj
)
571 return (jclass
) wrap_value (env
, obj
->getClass());
575 _Jv_JNI_IsInstanceOf (JNIEnv
*, jobject obj
, jclass clazz
)
577 return clazz
->isInstance(obj
);
583 // This section concerns method invocation.
586 template<jboolean is_static
>
588 _Jv_JNI_GetAnyMethodID (JNIEnv
*env
, jclass clazz
,
589 const char *name
, const char *sig
)
593 _Jv_InitClass (clazz
);
595 _Jv_Utf8Const
*name_u
= _Jv_makeUtf8Const ((char *) name
, -1);
596 _Jv_Utf8Const
*sig_u
= _Jv_makeUtf8Const ((char *) sig
, -1);
598 JvAssert (! clazz
->isPrimitive());
600 using namespace java::lang::reflect
;
602 while (clazz
!= NULL
)
604 jint count
= JvNumMethods (clazz
);
605 jmethodID meth
= JvGetFirstMethod (clazz
);
607 for (jint i
= 0; i
< count
; ++i
)
609 if (((is_static
&& Modifier::isStatic (meth
->accflags
))
610 || (! is_static
&& ! Modifier::isStatic (meth
->accflags
)))
611 && _Jv_equalUtf8Consts (meth
->name
, name_u
)
612 && _Jv_equalUtf8Consts (meth
->signature
, sig_u
))
615 meth
= meth
->getNextMethod();
618 clazz
= clazz
->getSuperclass ();
621 env
->ex
= new java::lang::NoSuchMethodError ();
631 // This is a helper function which turns a va_list into an array of
632 // `jvalue's. It needs signature information in order to do its work.
633 // The array of values must already be allocated.
635 array_from_valist (jvalue
*values
, JArray
<jclass
> *arg_types
, va_list vargs
)
637 jclass
*arg_elts
= elements (arg_types
);
638 for (int i
= 0; i
< arg_types
->length
; ++i
)
640 if (arg_elts
[i
] == JvPrimClass (byte
))
641 values
[i
].b
= va_arg (vargs
, jbyte
);
642 else if (arg_elts
[i
] == JvPrimClass (short))
643 values
[i
].s
= va_arg (vargs
, jshort
);
644 else if (arg_elts
[i
] == JvPrimClass (int))
645 values
[i
].i
= va_arg (vargs
, jint
);
646 else if (arg_elts
[i
] == JvPrimClass (long))
647 values
[i
].j
= va_arg (vargs
, jlong
);
648 else if (arg_elts
[i
] == JvPrimClass (float))
649 values
[i
].f
= va_arg (vargs
, jfloat
);
650 else if (arg_elts
[i
] == JvPrimClass (double))
651 values
[i
].d
= va_arg (vargs
, jdouble
);
652 else if (arg_elts
[i
] == JvPrimClass (boolean
))
653 values
[i
].z
= va_arg (vargs
, jboolean
);
654 else if (arg_elts
[i
] == JvPrimClass (char))
655 values
[i
].c
= va_arg (vargs
, jchar
);
659 values
[i
].l
= va_arg (vargs
, jobject
);
664 // This can call any sort of method: virtual, "nonvirtual", static, or
666 template<typename T
, invocation_type style
>
668 _Jv_JNI_CallAnyMethodV (JNIEnv
*env
, jobject obj
, jclass klass
,
669 jmethodID id
, va_list vargs
)
672 id
= _Jv_LookupDeclaredMethod (obj
->getClass (), id
->name
, id
->signature
);
674 jclass decl_class
= klass
? klass
: obj
->getClass ();
675 JvAssert (decl_class
!= NULL
);
678 JArray
<jclass
> *arg_types
;
682 _Jv_GetTypesFromSignature (id
, decl_class
,
683 &arg_types
, &return_type
);
685 jvalue args
[arg_types
->length
];
686 array_from_valist (args
, arg_types
, vargs
);
688 // For constructors we need to pass the Class we are instantiating.
689 if (style
== constructor
)
693 jthrowable ex
= _Jv_CallAnyMethodA (obj
, return_type
, id
,
694 style
== constructor
,
695 arg_types
, args
, &result
);
700 // We cheat a little here. FIXME.
701 return wrap_value (env
, * (T
*) &result
);
708 return wrap_value (env
, (T
) 0);
711 template<typename T
, invocation_type style
>
713 _Jv_JNI_CallAnyMethod (JNIEnv
*env
, jobject obj
, jclass klass
,
714 jmethodID method
, ...)
719 va_start (args
, method
);
720 result
= _Jv_JNI_CallAnyMethodV
<T
, style
> (env
, obj
, klass
, method
, args
);
726 template<typename T
, invocation_type style
>
728 _Jv_JNI_CallAnyMethodA (JNIEnv
*env
, jobject obj
, jclass klass
,
729 jmethodID id
, jvalue
*args
)
732 id
= _Jv_LookupDeclaredMethod (obj
->getClass (), id
->name
, id
->signature
);
734 jclass decl_class
= klass
? klass
: obj
->getClass ();
735 JvAssert (decl_class
!= NULL
);
738 JArray
<jclass
> *arg_types
;
741 _Jv_GetTypesFromSignature (id
, decl_class
,
742 &arg_types
, &return_type
);
744 // For constructors we need to pass the Class we are instantiating.
745 if (style
== constructor
)
749 jthrowable ex
= _Jv_CallAnyMethodA (obj
, return_type
, id
,
750 style
== constructor
,
751 arg_types
, args
, &result
);
756 // We cheat a little here. FIXME.
757 return wrap_value (env
, * (T
*) &result
);
764 return wrap_value (env
, (T
) 0);
767 template<invocation_type style
>
769 _Jv_JNI_CallAnyVoidMethodV (JNIEnv
*env
, jobject obj
, jclass klass
,
770 jmethodID id
, va_list vargs
)
773 id
= _Jv_LookupDeclaredMethod (obj
->getClass (), id
->name
, id
->signature
);
775 jclass decl_class
= klass
? klass
: obj
->getClass ();
776 JvAssert (decl_class
!= NULL
);
779 JArray
<jclass
> *arg_types
;
782 _Jv_GetTypesFromSignature (id
, decl_class
,
783 &arg_types
, &return_type
);
785 jvalue args
[arg_types
->length
];
786 array_from_valist (args
, arg_types
, vargs
);
788 // For constructors we need to pass the Class we are instantiating.
789 if (style
== constructor
)
792 jthrowable ex
= _Jv_CallAnyMethodA (obj
, return_type
, id
,
793 style
== constructor
,
794 arg_types
, args
, NULL
);
805 template<invocation_type style
>
807 _Jv_JNI_CallAnyVoidMethod (JNIEnv
*env
, jobject obj
, jclass klass
,
808 jmethodID method
, ...)
812 va_start (args
, method
);
813 _Jv_JNI_CallAnyVoidMethodV
<style
> (env
, obj
, klass
, method
, args
);
817 template<invocation_type style
>
819 _Jv_JNI_CallAnyVoidMethodA (JNIEnv
*env
, jobject obj
, jclass klass
,
820 jmethodID id
, jvalue
*args
)
823 id
= _Jv_LookupDeclaredMethod (obj
->getClass (), id
->name
, id
->signature
);
825 jclass decl_class
= klass
? klass
: obj
->getClass ();
826 JvAssert (decl_class
!= NULL
);
829 JArray
<jclass
> *arg_types
;
832 _Jv_GetTypesFromSignature (id
, decl_class
,
833 &arg_types
, &return_type
);
835 jthrowable ex
= _Jv_CallAnyMethodA (obj
, return_type
, id
,
836 style
== constructor
,
837 arg_types
, args
, NULL
);
848 // Functions with this signature are used to implement functions in
849 // the CallMethod family.
852 _Jv_JNI_CallMethodV (JNIEnv
*env
, jobject obj
, jmethodID id
, va_list args
)
854 return _Jv_JNI_CallAnyMethodV
<T
, normal
> (env
, obj
, NULL
, id
, args
);
857 // Functions with this signature are used to implement functions in
858 // the CallMethod family.
861 _Jv_JNI_CallMethod (JNIEnv
*env
, jobject obj
, jmethodID id
, ...)
867 result
= _Jv_JNI_CallAnyMethodV
<T
, normal
> (env
, obj
, NULL
, id
, args
);
873 // Functions with this signature are used to implement functions in
874 // the CallMethod family.
877 _Jv_JNI_CallMethodA (JNIEnv
*env
, jobject obj
, jmethodID id
, jvalue
*args
)
879 return _Jv_JNI_CallAnyMethodA
<T
, normal
> (env
, obj
, NULL
, id
, args
);
883 _Jv_JNI_CallVoidMethodV (JNIEnv
*env
, jobject obj
, jmethodID id
, va_list args
)
885 _Jv_JNI_CallAnyVoidMethodV
<normal
> (env
, obj
, NULL
, id
, args
);
889 _Jv_JNI_CallVoidMethod (JNIEnv
*env
, jobject obj
, jmethodID id
, ...)
894 _Jv_JNI_CallAnyVoidMethodV
<normal
> (env
, obj
, NULL
, id
, args
);
899 _Jv_JNI_CallVoidMethodA (JNIEnv
*env
, jobject obj
, jmethodID id
, jvalue
*args
)
901 _Jv_JNI_CallAnyVoidMethodA
<normal
> (env
, obj
, NULL
, id
, args
);
904 // Functions with this signature are used to implement functions in
905 // the CallStaticMethod family.
908 _Jv_JNI_CallStaticMethodV (JNIEnv
*env
, jclass klass
,
909 jmethodID id
, va_list args
)
911 JvAssert (((id
->accflags
) & java::lang::reflect::Modifier::STATIC
));
912 JvAssert ((&ClassClass
)->isInstance (klass
));
914 return _Jv_JNI_CallAnyMethodV
<T
, static_type
> (env
, NULL
, klass
, id
, args
);
917 // Functions with this signature are used to implement functions in
918 // the CallStaticMethod family.
921 _Jv_JNI_CallStaticMethod (JNIEnv
*env
, jclass klass
, jmethodID id
, ...)
926 JvAssert (((id
->accflags
) & java::lang::reflect::Modifier::STATIC
));
927 JvAssert ((&ClassClass
)->isInstance (klass
));
930 result
= _Jv_JNI_CallAnyMethodV
<T
, static_type
> (env
, NULL
, klass
,
937 // Functions with this signature are used to implement functions in
938 // the CallStaticMethod family.
941 _Jv_JNI_CallStaticMethodA (JNIEnv
*env
, jclass klass
, jmethodID id
,
944 JvAssert (((id
->accflags
) & java::lang::reflect::Modifier::STATIC
));
945 JvAssert ((&ClassClass
)->isInstance (klass
));
947 return _Jv_JNI_CallAnyMethodA
<T
, static_type
> (env
, NULL
, klass
, id
, args
);
951 _Jv_JNI_CallStaticVoidMethodV (JNIEnv
*env
, jclass klass
, jmethodID id
,
954 _Jv_JNI_CallAnyVoidMethodV
<static_type
> (env
, NULL
, klass
, id
, args
);
958 _Jv_JNI_CallStaticVoidMethod (JNIEnv
*env
, jclass klass
, jmethodID id
, ...)
963 _Jv_JNI_CallAnyVoidMethodV
<static_type
> (env
, NULL
, klass
, id
, args
);
968 _Jv_JNI_CallStaticVoidMethodA (JNIEnv
*env
, jclass klass
, jmethodID id
,
971 _Jv_JNI_CallAnyVoidMethodA
<static_type
> (env
, NULL
, klass
, id
, args
);
975 _Jv_JNI_NewObjectV (JNIEnv
*env
, jclass klass
,
976 jmethodID id
, va_list args
)
978 JvAssert (klass
&& ! klass
->isArray ());
979 JvAssert (! strcmp (id
->name
->data
, "<init>")
980 && id
->signature
->length
> 2
981 && id
->signature
->data
[0] == '('
982 && ! strcmp (&id
->signature
->data
[id
->signature
->length
- 2],
985 return _Jv_JNI_CallAnyMethodV
<jobject
, constructor
> (env
, NULL
, klass
,
990 _Jv_JNI_NewObject (JNIEnv
*env
, jclass klass
, jmethodID id
, ...)
992 JvAssert (klass
&& ! klass
->isArray ());
993 JvAssert (! strcmp (id
->name
->data
, "<init>")
994 && id
->signature
->length
> 2
995 && id
->signature
->data
[0] == '('
996 && ! strcmp (&id
->signature
->data
[id
->signature
->length
- 2],
1002 va_start (args
, id
);
1003 result
= _Jv_JNI_CallAnyMethodV
<jobject
, constructor
> (env
, NULL
, klass
,
1011 _Jv_JNI_NewObjectA (JNIEnv
*env
, jclass klass
, jmethodID id
,
1014 JvAssert (klass
&& ! klass
->isArray ());
1015 JvAssert (! strcmp (id
->name
->data
, "<init>")
1016 && id
->signature
->length
> 2
1017 && id
->signature
->data
[0] == '('
1018 && ! strcmp (&id
->signature
->data
[id
->signature
->length
- 2],
1021 return _Jv_JNI_CallAnyMethodA
<jobject
, constructor
> (env
, NULL
, klass
,
1027 template<typename T
>
1029 _Jv_JNI_GetField (JNIEnv
*env
, jobject obj
, jfieldID field
)
1032 T
*ptr
= (T
*) ((char *) obj
+ field
->getOffset ());
1033 return wrap_value (env
, *ptr
);
1036 template<typename T
>
1038 _Jv_JNI_SetField (JNIEnv
*, jobject obj
, jfieldID field
, T value
)
1041 T
*ptr
= (T
*) ((char *) obj
+ field
->getOffset ());
1045 template<jboolean is_static
>
1047 _Jv_JNI_GetAnyFieldID (JNIEnv
*env
, jclass clazz
,
1048 const char *name
, const char *sig
)
1052 _Jv_InitClass (clazz
);
1054 _Jv_Utf8Const
*a_name
= _Jv_makeUtf8Const ((char *) name
, -1);
1056 jclass field_class
= NULL
;
1058 field_class
= _Jv_FindClassFromSignature ((char *) sig
, NULL
);
1061 _Jv_Utf8Const
*sig_u
= _Jv_makeUtf8Const ((char *) sig
, -1);
1062 field_class
= _Jv_FindClass (sig_u
, NULL
);
1065 // FIXME: what if field_class == NULL?
1067 while (clazz
!= NULL
)
1069 jint count
= (is_static
1070 ? JvNumStaticFields (clazz
)
1071 : JvNumInstanceFields (clazz
));
1072 jfieldID field
= (is_static
1073 ? JvGetFirstStaticField (clazz
)
1074 : JvGetFirstInstanceField (clazz
));
1075 for (jint i
= 0; i
< count
; ++i
)
1077 // The field is resolved as a side effect of class
1079 JvAssert (field
->isResolved ());
1081 _Jv_Utf8Const
*f_name
= field
->getNameUtf8Const(clazz
);
1083 if (_Jv_equalUtf8Consts (f_name
, a_name
)
1084 && field
->getClass() == field_class
)
1087 field
= field
->getNextField ();
1090 clazz
= clazz
->getSuperclass ();
1093 env
->ex
= new java::lang::NoSuchFieldError ();
1095 catch (jthrowable t
)
1102 template<typename T
>
1104 _Jv_JNI_GetStaticField (JNIEnv
*env
, jclass
, jfieldID field
)
1106 T
*ptr
= (T
*) field
->u
.addr
;
1107 return wrap_value (env
, *ptr
);
1110 template<typename T
>
1112 _Jv_JNI_SetStaticField (JNIEnv
*, jclass
, jfieldID field
, T value
)
1114 T
*ptr
= (T
*) field
->u
.addr
;
1119 _Jv_JNI_NewString (JNIEnv
*env
, const jchar
*unichars
, jsize len
)
1123 jstring r
= _Jv_NewString (unichars
, len
);
1124 return (jstring
) wrap_value (env
, r
);
1126 catch (jthrowable t
)
1134 _Jv_JNI_GetStringLength (JNIEnv
*, jstring string
)
1136 return string
->length();
1139 static const jchar
*
1140 _Jv_JNI_GetStringChars (JNIEnv
*, jstring string
, jboolean
*isCopy
)
1142 jchar
*result
= _Jv_GetStringChars (string
);
1143 mark_for_gc (string
);
1146 return (const jchar
*) result
;
1150 _Jv_JNI_ReleaseStringChars (JNIEnv
*, jstring string
, const jchar
*)
1152 unmark_for_gc (string
);
1156 _Jv_JNI_NewStringUTF (JNIEnv
*env
, const char *bytes
)
1160 jstring result
= JvNewStringUTF (bytes
);
1161 return (jstring
) wrap_value (env
, result
);
1163 catch (jthrowable t
)
1171 _Jv_JNI_GetStringUTFLength (JNIEnv
*, jstring string
)
1173 return JvGetStringUTFLength (string
);
1177 _Jv_JNI_GetStringUTFChars (JNIEnv
*env
, jstring string
, jboolean
*isCopy
)
1179 jsize len
= JvGetStringUTFLength (string
);
1182 char *r
= (char *) _Jv_Malloc (len
+ 1);
1183 JvGetStringUTFRegion (string
, 0, len
, r
);
1189 return (const char *) r
;
1191 catch (jthrowable t
)
1199 _Jv_JNI_ReleaseStringUTFChars (JNIEnv
*, jstring
, const char *utf
)
1201 _Jv_Free ((void *) utf
);
1205 _Jv_JNI_GetStringRegion (JNIEnv
*env
, jstring string
, jsize start
, jsize len
,
1208 jchar
*result
= _Jv_GetStringChars (string
);
1209 if (start
< 0 || start
> string
->length ()
1210 || len
< 0 || start
+ len
> string
->length ())
1214 env
->ex
= new java::lang::StringIndexOutOfBoundsException ();
1216 catch (jthrowable t
)
1222 memcpy (buf
, &result
[start
], len
* sizeof (jchar
));
1226 _Jv_JNI_GetStringUTFRegion (JNIEnv
*env
, jstring str
, jsize start
,
1227 jsize len
, char *buf
)
1229 if (start
< 0 || start
> str
->length ()
1230 || len
< 0 || start
+ len
> str
->length ())
1234 env
->ex
= new java::lang::StringIndexOutOfBoundsException ();
1236 catch (jthrowable t
)
1242 _Jv_GetStringUTFRegion (str
, start
, len
, buf
);
1245 static const jchar
*
1246 _Jv_JNI_GetStringCritical (JNIEnv
*, jstring str
, jboolean
*isCopy
)
1248 jchar
*result
= _Jv_GetStringChars (str
);
1255 _Jv_JNI_ReleaseStringCritical (JNIEnv
*, jstring
, const jchar
*)
1261 _Jv_JNI_GetArrayLength (JNIEnv
*, jarray array
)
1263 return array
->length
;
1267 _Jv_JNI_NewObjectArray (JNIEnv
*env
, jsize length
, jclass elementClass
,
1272 jarray result
= JvNewObjectArray (length
, elementClass
, init
);
1273 return (jarray
) wrap_value (env
, result
);
1275 catch (jthrowable t
)
1283 _Jv_JNI_GetObjectArrayElement (JNIEnv
*env
, jobjectArray array
, jsize index
)
1285 jobject
*elts
= elements (array
);
1286 return wrap_value (env
, elts
[index
]);
1290 _Jv_JNI_SetObjectArrayElement (JNIEnv
*env
, jobjectArray array
, jsize index
,
1295 _Jv_CheckArrayStore (array
, value
);
1296 jobject
*elts
= elements (array
);
1297 elts
[index
] = value
;
1299 catch (jthrowable t
)
1305 template<typename T
, jclass K
>
1307 _Jv_JNI_NewPrimitiveArray (JNIEnv
*env
, jsize length
)
1311 return (JArray
<T
> *) wrap_value (env
, _Jv_NewPrimArray (K
, length
));
1313 catch (jthrowable t
)
1320 template<typename T
>
1322 _Jv_JNI_GetPrimitiveArrayElements (JNIEnv
*, JArray
<T
> *array
,
1325 T
*elts
= elements (array
);
1328 // We elect never to copy.
1331 mark_for_gc (array
);
1335 template<typename T
>
1337 _Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv
*, JArray
<T
> *array
,
1338 T
*, jint
/* mode */)
1340 // Note that we ignore MODE. We can do this because we never copy
1341 // the array elements. My reading of the JNI documentation is that
1342 // this is an option for the implementor.
1343 unmark_for_gc (array
);
1346 template<typename T
>
1348 _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv
*env
, JArray
<T
> *array
,
1349 jsize start
, jsize len
,
1352 if (start
< 0 || len
>= array
->length
|| start
+ len
>= array
->length
)
1357 env
->ex
= new java::lang::ArrayIndexOutOfBoundsException ();
1359 catch (jthrowable t
)
1361 // Could have thown out of memory error.
1367 T
*elts
= elements (array
) + start
;
1368 memcpy (buf
, elts
, len
* sizeof (T
));
1372 template<typename T
>
1374 _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv
*env
, JArray
<T
> *array
,
1375 jsize start
, jsize len
, T
*buf
)
1377 if (start
< 0 || len
>= array
->length
|| start
+ len
>= array
->length
)
1382 env
->ex
= new java::lang::ArrayIndexOutOfBoundsException ();
1384 catch (jthrowable t
)
1391 T
*elts
= elements (array
) + start
;
1392 memcpy (elts
, buf
, len
* sizeof (T
));
1397 _Jv_JNI_GetPrimitiveArrayCritical (JNIEnv
*, jarray array
,
1400 // FIXME: does this work?
1401 jclass klass
= array
->getClass()->getComponentType();
1402 JvAssert (klass
->isPrimitive ());
1403 char *r
= _Jv_GetArrayElementFromElementType (array
, klass
);
1410 _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv
*, jarray
, void *, jint
)
1416 _Jv_JNI_MonitorEnter (JNIEnv
*env
, jobject obj
)
1420 return _Jv_MonitorEnter (obj
);
1422 catch (jthrowable t
)
1430 _Jv_JNI_MonitorExit (JNIEnv
*env
, jobject obj
)
1434 return _Jv_MonitorExit (obj
);
1436 catch (jthrowable t
)
1445 _Jv_JNI_ToReflectedField (JNIEnv
*env
, jclass cls
, jfieldID fieldID
,
1450 java::lang::reflect::Field
*field
= new java::lang::reflect::Field();
1451 field
->declaringClass
= cls
;
1452 field
->offset
= (char*) fieldID
- (char *) cls
->fields
;
1453 field
->name
= _Jv_NewStringUtf8Const (fieldID
->getNameUtf8Const (cls
));
1454 return wrap_value (env
, field
);
1456 catch (jthrowable t
)
1465 _Jv_JNI_FromReflectedField (JNIEnv
*, jobject f
)
1467 using namespace java::lang::reflect
;
1469 Field
*field
= reinterpret_cast<Field
*> (f
);
1470 return _Jv_FromReflectedField (field
);
1474 _Jv_JNI_ToReflectedMethod (JNIEnv
*env
, jclass klass
, jmethodID id
,
1477 using namespace java::lang::reflect
;
1480 static _Jv_Utf8Const
*init_name
= _Jv_makeUtf8Const ("<init>", 6);
1482 jobject result
= NULL
;
1486 if (_Jv_equalUtf8Consts (id
->name
, init_name
))
1489 Constructor
*cons
= new Constructor ();
1490 cons
->offset
= (char *) id
- (char *) &klass
->methods
;
1491 cons
->declaringClass
= klass
;
1496 Method
*meth
= new Method ();
1497 meth
->offset
= (char *) id
- (char *) &klass
->methods
;
1498 meth
->declaringClass
= klass
;
1502 catch (jthrowable t
)
1507 return wrap_value (env
, result
);
1511 _Jv_JNI_FromReflectedMethod (JNIEnv
*, jobject method
)
1513 using namespace java::lang::reflect
;
1514 if ((&MethodClass
)->isInstance (method
))
1515 return _Jv_FromReflectedMethod (reinterpret_cast<Method
*> (method
));
1517 _Jv_FromReflectedConstructor (reinterpret_cast<Constructor
*> (method
));
1521 _Jv_JNI_RegisterNatives (JNIEnv
*env
, jclass k
,
1522 const JNINativeMethod
*methods
,
1526 // For now, this only matters for interpreted methods. FIXME.
1527 if (! _Jv_IsInterpretedClass (k
))
1529 // FIXME: throw exception.
1532 _Jv_InterpClass
*klass
= reinterpret_cast<_Jv_InterpClass
*> (k
);
1534 // Look at each descriptor given us, and find the corresponding
1535 // method in the class.
1536 for (int j
= 0; j
< nMethods
; ++j
)
1540 _Jv_MethodBase
**imeths
= _Jv_GetFirstMethod (klass
);
1541 for (int i
= 0; i
< JvNumMethods (klass
); ++i
)
1543 _Jv_MethodBase
*meth
= imeths
[i
];
1544 _Jv_Method
*self
= meth
->get_method ();
1546 if (! strcmp (self
->name
->data
, methods
[j
].name
)
1547 && ! strcmp (self
->signature
->data
, methods
[j
].signature
))
1549 if (! (self
->accflags
1550 & java::lang::reflect::Modifier::NATIVE
))
1553 // Found a match that is native.
1554 _Jv_JNIMethod
*jmeth
= reinterpret_cast<_Jv_JNIMethod
*> (meth
);
1555 jmeth
->set_function (methods
[i
].fnPtr
);
1563 jstring m
= JvNewStringUTF (methods
[j
].name
);
1566 env
->ex
=new java::lang::NoSuchMethodError (m
);
1568 catch (jthrowable t
)
1577 #else /* INTERPRETER */
1579 #endif /* INTERPRETER */
1583 _Jv_JNI_UnregisterNatives (JNIEnv
*, jclass
)
1592 // Add a character to the buffer, encoding properly.
1594 add_char (char *buf
, jchar c
, int *here
)
1598 buf
[(*here
)++] = '_';
1599 buf
[(*here
)++] = '1';
1603 buf
[(*here
)++] = '_';
1604 buf
[(*here
)++] = '2';
1608 buf
[(*here
)++] = '_';
1609 buf
[(*here
)++] = '3';
1612 buf
[(*here
)++] = '_';
1613 else if ((c
>= '0' && c
<= '9')
1614 || (c
>= 'a' && c
<= 'z')
1615 || (c
>= 'A' && c
<= 'Z'))
1616 buf
[(*here
)++] = (char) c
;
1619 // "Unicode" character.
1620 buf
[(*here
)++] = '_';
1621 buf
[(*here
)++] = '0';
1622 for (int i
= 0; i
< 4; ++i
)
1625 buf
[(*here
) + 4 - i
] = (val
> 10) ? ('a' + val
- 10) : ('0' + val
);
1632 // Compute a mangled name for a native function. This computes the
1633 // long name, and also returns an index which indicates where a NUL
1634 // can be placed to create the short name. This function assumes that
1635 // the buffer is large enough for its results.
1637 mangled_name (jclass klass
, _Jv_Utf8Const
*func_name
,
1638 _Jv_Utf8Const
*signature
, char *buf
, int *long_start
)
1640 strcpy (buf
, "Java_");
1643 // Add fully qualified class name.
1644 jchar
*chars
= _Jv_GetStringChars (klass
->getName ());
1645 jint len
= klass
->getName ()->length ();
1646 for (int i
= 0; i
< len
; ++i
)
1647 add_char (buf
, chars
[i
], &here
);
1649 // Don't use add_char because we need a literal `_'.
1652 const unsigned char *fn
= (const unsigned char *) func_name
->data
;
1653 const unsigned char *limit
= fn
+ func_name
->length
;
1654 for (int i
= 0; ; ++i
)
1656 int ch
= UTF8_GET (fn
, limit
);
1659 add_char (buf
, ch
, &here
);
1662 // This is where the long signature begins.
1667 const unsigned char *sig
= (const unsigned char *) signature
->data
;
1668 limit
= sig
+ signature
->length
;
1669 JvAssert (sig
[0] == '(');
1673 int ch
= UTF8_GET (sig
, limit
);
1674 if (ch
== ')' || ch
< 0)
1676 add_char (buf
, ch
, &here
);
1682 // Return the current thread's JNIEnv; if one does not exist, create
1683 // it. Also create a new system frame for use. This is `extern "C"'
1684 // because the compiler calls it.
1686 _Jv_GetJNIEnvNewFrame (jclass klass
)
1688 JNIEnv
*env
= _Jv_GetCurrentJNIEnv ();
1691 env
= (JNIEnv
*) _Jv_MallocUnchecked (sizeof (JNIEnv
));
1692 env
->p
= &_Jv_JNIFunctions
;
1697 _Jv_SetCurrentJNIEnv (env
);
1700 _Jv_JNI_LocalFrame
*frame
1701 = (_Jv_JNI_LocalFrame
*) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame
)
1703 * sizeof (jobject
)));
1705 frame
->marker
= MARK_SYSTEM
;
1706 frame
->size
= FRAME_SIZE
;
1707 frame
->next
= env
->locals
;
1708 env
->locals
= frame
;
1710 for (int i
= 0; i
< frame
->size
; ++i
)
1711 frame
->vec
[i
] = NULL
;
1716 // Return the function which implements a particular JNI method. If
1717 // we can't find the function, we throw the appropriate exception.
1718 // This is `extern "C"' because the compiler uses it.
1720 _Jv_LookupJNIMethod (jclass klass
, _Jv_Utf8Const
*name
,
1721 _Jv_Utf8Const
*signature
)
1723 char buf
[10 + 6 * (name
->length
+ signature
->length
)];
1727 mangled_name (klass
, name
, signature
, buf
, &long_start
);
1728 char c
= buf
[long_start
];
1729 buf
[long_start
] = '\0';
1730 function
= _Jv_FindSymbolInExecutable (buf
);
1731 if (function
== NULL
)
1733 buf
[long_start
] = c
;
1734 function
= _Jv_FindSymbolInExecutable (buf
);
1735 if (function
== NULL
)
1737 jstring str
= JvNewStringUTF (name
->data
);
1738 JvThrow (new java::lang::AbstractMethodError (str
));
1745 // This function is the stub which is used to turn an ordinary (CNI)
1746 // method call into a JNI call.
1748 _Jv_JNIMethod::call (ffi_cif
*, void *ret
, ffi_raw
*args
, void *__this
)
1750 _Jv_JNIMethod
* _this
= (_Jv_JNIMethod
*) __this
;
1752 JNIEnv
*env
= _Jv_GetJNIEnvNewFrame (_this
->defining_class
);
1754 // FIXME: we should mark every reference parameter as a local. For
1755 // now we assume a conservative GC, and we assume that the
1756 // references are on the stack somewhere.
1758 // We cache the value that we find, of course, but if we don't find
1759 // a value we don't cache that fact -- we might subsequently load a
1760 // library which finds the function in question.
1761 if (_this
->function
== NULL
)
1762 _this
->function
= _Jv_LookupJNIMethod (_this
->defining_class
,
1764 _this
->self
->signature
);
1766 JvAssert (_this
->args_raw_size
% sizeof (ffi_raw
) == 0);
1767 ffi_raw real_args
[2 + _this
->args_raw_size
/ sizeof (ffi_raw
)];
1770 // First argument is always the environment pointer.
1771 real_args
[offset
++].ptr
= env
;
1773 // For a static method, we pass in the Class. For non-static
1774 // methods, the `this' argument is already handled.
1775 if ((_this
->self
->accflags
& java::lang::reflect::Modifier::STATIC
))
1776 real_args
[offset
++].ptr
= _this
->defining_class
;
1778 // Copy over passed-in arguments.
1779 memcpy (&real_args
[offset
], args
, _this
->args_raw_size
);
1781 // The actual call to the JNI function.
1782 ffi_raw_call (&_this
->jni_cif
, (void (*)()) _this
->function
,
1785 _Jv_JNI_PopSystemFrame (env
);
1788 #endif /* INTERPRETER */
1796 // An internal helper function.
1798 _Jv_JNI_AttachCurrentThread (JavaVM
*, jstring name
, void **penv
, void *args
)
1800 JavaVMAttachArgs
*attach
= reinterpret_cast<JavaVMAttachArgs
*> (args
);
1801 java::lang::ThreadGroup
*group
= NULL
;
1805 // FIXME: do we really want to support 1.1?
1806 if (attach
->version
!= JNI_VERSION_1_2
1807 && attach
->version
!= JNI_VERSION_1_1
)
1808 return JNI_EVERSION
;
1810 JvAssert ((&ThreadGroupClass
)->isInstance (attach
->group
));
1811 group
= reinterpret_cast<java::lang::ThreadGroup
*> (attach
->group
);
1814 // Attaching an already-attached thread is a no-op.
1815 if (_Jv_GetCurrentJNIEnv () != NULL
)
1818 JNIEnv
*env
= (JNIEnv
*) _Jv_MallocUnchecked (sizeof (JNIEnv
));
1821 env
->p
= &_Jv_JNIFunctions
;
1825 = (_Jv_JNI_LocalFrame
*) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame
)
1827 * sizeof (jobject
)));
1828 if (env
->locals
== NULL
)
1833 *penv
= reinterpret_cast<void *> (env
);
1835 // This thread might already be a Java thread -- this function might
1836 // have been called simply to set the new JNIEnv.
1837 if (_Jv_ThreadCurrent () == NULL
)
1841 (void) new gnu::gcj::jni::NativeThread (group
, name
);
1843 catch (jthrowable t
)
1848 _Jv_SetCurrentJNIEnv (env
);
1853 // This is the one actually used by JNI.
1855 _Jv_JNI_AttachCurrentThread (JavaVM
*vm
, void **penv
, void *args
)
1857 return _Jv_JNI_AttachCurrentThread (vm
, NULL
, penv
, args
);
1861 _Jv_JNI_DestroyJavaVM (JavaVM
*vm
)
1863 JvAssert (the_vm
&& vm
== the_vm
);
1866 if (_Jv_ThreadCurrent () != NULL
)
1872 main_name
= JvNewStringLatin1 ("main");
1874 catch (jthrowable t
)
1879 jint r
= _Jv_JNI_AttachCurrentThread (vm
,
1881 reinterpret_cast<void **> (&env
),
1887 env
= _Jv_GetCurrentJNIEnv ();
1891 // Docs say that this always returns an error code.
1896 _Jv_JNI_DetachCurrentThread (JavaVM
*)
1898 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
1900 return JNI_EDETACHED
;
1902 // FIXME: we only allow threads attached via AttachCurrentThread to
1903 // be detached. I have no idea how we could implement detaching
1904 // other threads, given the requirement that we must release all the
1905 // monitors. That just seems evil.
1906 JvAssert ((&NativeThreadClass
)->isInstance (t
));
1908 // FIXME: release the monitors. We'll take this to mean all
1909 // monitors acquired via the JNI interface. This means we have to
1910 // keep track of them.
1912 gnu::gcj::jni::NativeThread
*nt
1913 = reinterpret_cast<gnu::gcj::jni::NativeThread
*> (t
);
1920 _Jv_JNI_GetEnv (JavaVM
*, void **penv
, jint version
)
1922 if (_Jv_ThreadCurrent () == NULL
)
1925 return JNI_EDETACHED
;
1929 // Handle JVMPI requests.
1930 if (version
== JVMPI_VERSION_1
)
1932 *penv
= (void *) &_Jv_JVMPI_Interface
;
1937 // FIXME: do we really want to support 1.1?
1938 if (version
!= JNI_VERSION_1_2
&& version
!= JNI_VERSION_1_1
)
1941 return JNI_EVERSION
;
1944 *penv
= (void *) _Jv_GetCurrentJNIEnv ();
1949 JNI_GetDefaultJavaVMInitArgs (void *args
)
1951 jint version
= * (jint
*) args
;
1952 // Here we only support 1.2.
1953 if (version
!= JNI_VERSION_1_2
)
1954 return JNI_EVERSION
;
1956 JavaVMInitArgs
*ia
= reinterpret_cast<JavaVMInitArgs
*> (args
);
1957 ia
->version
= JNI_VERSION_1_2
;
1960 ia
->ignoreUnrecognized
= true;
1966 JNI_CreateJavaVM (JavaVM
**vm
, void **penv
, void *args
)
1968 JvAssert (! the_vm
);
1969 // FIXME: synchronize
1970 JavaVM
*nvm
= (JavaVM
*) _Jv_MallocUnchecked (sizeof (JavaVM
));
1973 nvm
->functions
= &_Jv_JNI_InvokeFunctions
;
1975 // Parse the arguments.
1978 jint version
= * (jint
*) args
;
1979 // We only support 1.2.
1980 if (version
!= JNI_VERSION_1_2
)
1981 return JNI_EVERSION
;
1982 JavaVMInitArgs
*ia
= reinterpret_cast<JavaVMInitArgs
*> (args
);
1983 for (int i
= 0; i
< ia
->nOptions
; ++i
)
1985 if (! strcmp (ia
->options
[i
].optionString
, "vfprintf")
1986 || ! strcmp (ia
->options
[i
].optionString
, "exit")
1987 || ! strcmp (ia
->options
[i
].optionString
, "abort"))
1989 // We are required to recognize these, but for now we
1990 // don't handle them in any way. FIXME.
1993 else if (! strncmp (ia
->options
[i
].optionString
,
1994 "-verbose", sizeof ("-verbose") - 1))
1996 // We don't do anything with this option either. We
1997 // might want to make sure the argument is valid, but we
1998 // don't really care all that much for now.
2001 else if (! strncmp (ia
->options
[i
].optionString
, "-D", 2))
2006 else if (ia
->ignoreUnrecognized
)
2008 if (ia
->options
[i
].optionString
[0] == '_'
2009 || ! strncmp (ia
->options
[i
].optionString
, "-X", 2))
2017 jint r
=_Jv_JNI_AttachCurrentThread (nvm
, penv
, NULL
);
2027 JNI_GetCreatedJavaVMs (JavaVM
**vm_buffer
, jsize buf_len
, jsize
*n_vms
)
2032 // We only support a single VM.
2035 vm_buffer
[0] = the_vm
;
2046 // FIXME: synchronize
2049 JavaVM
*nvm
= (JavaVM
*) _Jv_MallocUnchecked (sizeof (JavaVM
));
2051 nvm
->functions
= &_Jv_JNI_InvokeFunctions
;
2055 // If this is a Java thread, we want to make sure it has an
2056 // associated JNIEnv.
2057 if (_Jv_ThreadCurrent () != NULL
)
2060 _Jv_JNI_AttachCurrentThread (the_vm
, &ignore
, NULL
);
2067 _Jv_JNI_GetJavaVM (JNIEnv
*, JavaVM
**vm
)
2069 *vm
= _Jv_GetJavaVM ();
2070 return *vm
== NULL
? JNI_ERR
: JNI_OK
;
2075 #define NOT_IMPL NULL
2076 #define RESERVED NULL
2078 struct JNINativeInterface _Jv_JNIFunctions
=
2085 _Jv_JNI_DefineClass
,
2087 _Jv_JNI_FromReflectedMethod
,
2088 _Jv_JNI_FromReflectedField
,
2089 _Jv_JNI_ToReflectedMethod
,
2090 _Jv_JNI_GetSuperclass
,
2091 _Jv_JNI_IsAssignableFrom
,
2092 _Jv_JNI_ToReflectedField
,
2095 _Jv_JNI_ExceptionOccurred
,
2096 _Jv_JNI_ExceptionDescribe
,
2097 _Jv_JNI_ExceptionClear
,
2100 _Jv_JNI_PushLocalFrame
,
2101 _Jv_JNI_PopLocalFrame
,
2102 _Jv_JNI_NewGlobalRef
,
2103 _Jv_JNI_DeleteGlobalRef
,
2104 _Jv_JNI_DeleteLocalRef
,
2106 _Jv_JNI_IsSameObject
,
2108 _Jv_JNI_NewLocalRef
,
2109 _Jv_JNI_EnsureLocalCapacity
,
2111 _Jv_JNI_AllocObject
,
2115 _Jv_JNI_GetObjectClass
,
2116 _Jv_JNI_IsInstanceOf
,
2117 _Jv_JNI_GetAnyMethodID
<false>,
2119 _Jv_JNI_CallMethod
<jobject
>,
2120 _Jv_JNI_CallMethodV
<jobject
>,
2121 _Jv_JNI_CallMethodA
<jobject
>,
2122 _Jv_JNI_CallMethod
<jboolean
>,
2123 _Jv_JNI_CallMethodV
<jboolean
>,
2124 _Jv_JNI_CallMethodA
<jboolean
>,
2125 _Jv_JNI_CallMethod
<jbyte
>,
2126 _Jv_JNI_CallMethodV
<jbyte
>,
2127 _Jv_JNI_CallMethodA
<jbyte
>,
2128 _Jv_JNI_CallMethod
<jchar
>,
2129 _Jv_JNI_CallMethodV
<jchar
>,
2130 _Jv_JNI_CallMethodA
<jchar
>,
2131 _Jv_JNI_CallMethod
<jshort
>,
2132 _Jv_JNI_CallMethodV
<jshort
>,
2133 _Jv_JNI_CallMethodA
<jshort
>,
2134 _Jv_JNI_CallMethod
<jint
>,
2135 _Jv_JNI_CallMethodV
<jint
>,
2136 _Jv_JNI_CallMethodA
<jint
>,
2137 _Jv_JNI_CallMethod
<jlong
>,
2138 _Jv_JNI_CallMethodV
<jlong
>,
2139 _Jv_JNI_CallMethodA
<jlong
>,
2140 _Jv_JNI_CallMethod
<jfloat
>,
2141 _Jv_JNI_CallMethodV
<jfloat
>,
2142 _Jv_JNI_CallMethodA
<jfloat
>,
2143 _Jv_JNI_CallMethod
<jdouble
>,
2144 _Jv_JNI_CallMethodV
<jdouble
>,
2145 _Jv_JNI_CallMethodA
<jdouble
>,
2146 _Jv_JNI_CallVoidMethod
,
2147 _Jv_JNI_CallVoidMethodV
,
2148 _Jv_JNI_CallVoidMethodA
,
2150 // Nonvirtual method invocation functions follow.
2151 _Jv_JNI_CallAnyMethod
<jobject
, nonvirtual
>,
2152 _Jv_JNI_CallAnyMethodV
<jobject
, nonvirtual
>,
2153 _Jv_JNI_CallAnyMethodA
<jobject
, nonvirtual
>,
2154 _Jv_JNI_CallAnyMethod
<jboolean
, nonvirtual
>,
2155 _Jv_JNI_CallAnyMethodV
<jboolean
, nonvirtual
>,
2156 _Jv_JNI_CallAnyMethodA
<jboolean
, nonvirtual
>,
2157 _Jv_JNI_CallAnyMethod
<jbyte
, nonvirtual
>,
2158 _Jv_JNI_CallAnyMethodV
<jbyte
, nonvirtual
>,
2159 _Jv_JNI_CallAnyMethodA
<jbyte
, nonvirtual
>,
2160 _Jv_JNI_CallAnyMethod
<jchar
, nonvirtual
>,
2161 _Jv_JNI_CallAnyMethodV
<jchar
, nonvirtual
>,
2162 _Jv_JNI_CallAnyMethodA
<jchar
, nonvirtual
>,
2163 _Jv_JNI_CallAnyMethod
<jshort
, nonvirtual
>,
2164 _Jv_JNI_CallAnyMethodV
<jshort
, nonvirtual
>,
2165 _Jv_JNI_CallAnyMethodA
<jshort
, nonvirtual
>,
2166 _Jv_JNI_CallAnyMethod
<jint
, nonvirtual
>,
2167 _Jv_JNI_CallAnyMethodV
<jint
, nonvirtual
>,
2168 _Jv_JNI_CallAnyMethodA
<jint
, nonvirtual
>,
2169 _Jv_JNI_CallAnyMethod
<jlong
, nonvirtual
>,
2170 _Jv_JNI_CallAnyMethodV
<jlong
, nonvirtual
>,
2171 _Jv_JNI_CallAnyMethodA
<jlong
, nonvirtual
>,
2172 _Jv_JNI_CallAnyMethod
<jfloat
, nonvirtual
>,
2173 _Jv_JNI_CallAnyMethodV
<jfloat
, nonvirtual
>,
2174 _Jv_JNI_CallAnyMethodA
<jfloat
, nonvirtual
>,
2175 _Jv_JNI_CallAnyMethod
<jdouble
, nonvirtual
>,
2176 _Jv_JNI_CallAnyMethodV
<jdouble
, nonvirtual
>,
2177 _Jv_JNI_CallAnyMethodA
<jdouble
, nonvirtual
>,
2178 _Jv_JNI_CallAnyVoidMethod
<nonvirtual
>,
2179 _Jv_JNI_CallAnyVoidMethodV
<nonvirtual
>,
2180 _Jv_JNI_CallAnyVoidMethodA
<nonvirtual
>,
2182 _Jv_JNI_GetAnyFieldID
<false>,
2183 _Jv_JNI_GetField
<jobject
>,
2184 _Jv_JNI_GetField
<jboolean
>,
2185 _Jv_JNI_GetField
<jbyte
>,
2186 _Jv_JNI_GetField
<jchar
>,
2187 _Jv_JNI_GetField
<jshort
>,
2188 _Jv_JNI_GetField
<jint
>,
2189 _Jv_JNI_GetField
<jlong
>,
2190 _Jv_JNI_GetField
<jfloat
>,
2191 _Jv_JNI_GetField
<jdouble
>,
2201 _Jv_JNI_GetAnyMethodID
<true>,
2203 _Jv_JNI_CallStaticMethod
<jobject
>,
2204 _Jv_JNI_CallStaticMethodV
<jobject
>,
2205 _Jv_JNI_CallStaticMethodA
<jobject
>,
2206 _Jv_JNI_CallStaticMethod
<jboolean
>,
2207 _Jv_JNI_CallStaticMethodV
<jboolean
>,
2208 _Jv_JNI_CallStaticMethodA
<jboolean
>,
2209 _Jv_JNI_CallStaticMethod
<jbyte
>,
2210 _Jv_JNI_CallStaticMethodV
<jbyte
>,
2211 _Jv_JNI_CallStaticMethodA
<jbyte
>,
2212 _Jv_JNI_CallStaticMethod
<jchar
>,
2213 _Jv_JNI_CallStaticMethodV
<jchar
>,
2214 _Jv_JNI_CallStaticMethodA
<jchar
>,
2215 _Jv_JNI_CallStaticMethod
<jshort
>,
2216 _Jv_JNI_CallStaticMethodV
<jshort
>,
2217 _Jv_JNI_CallStaticMethodA
<jshort
>,
2218 _Jv_JNI_CallStaticMethod
<jint
>,
2219 _Jv_JNI_CallStaticMethodV
<jint
>,
2220 _Jv_JNI_CallStaticMethodA
<jint
>,
2221 _Jv_JNI_CallStaticMethod
<jlong
>,
2222 _Jv_JNI_CallStaticMethodV
<jlong
>,
2223 _Jv_JNI_CallStaticMethodA
<jlong
>,
2224 _Jv_JNI_CallStaticMethod
<jfloat
>,
2225 _Jv_JNI_CallStaticMethodV
<jfloat
>,
2226 _Jv_JNI_CallStaticMethodA
<jfloat
>,
2227 _Jv_JNI_CallStaticMethod
<jdouble
>,
2228 _Jv_JNI_CallStaticMethodV
<jdouble
>,
2229 _Jv_JNI_CallStaticMethodA
<jdouble
>,
2230 _Jv_JNI_CallStaticVoidMethod
,
2231 _Jv_JNI_CallStaticVoidMethodV
,
2232 _Jv_JNI_CallStaticVoidMethodA
,
2234 _Jv_JNI_GetAnyFieldID
<true>,
2235 _Jv_JNI_GetStaticField
<jobject
>,
2236 _Jv_JNI_GetStaticField
<jboolean
>,
2237 _Jv_JNI_GetStaticField
<jbyte
>,
2238 _Jv_JNI_GetStaticField
<jchar
>,
2239 _Jv_JNI_GetStaticField
<jshort
>,
2240 _Jv_JNI_GetStaticField
<jint
>,
2241 _Jv_JNI_GetStaticField
<jlong
>,
2242 _Jv_JNI_GetStaticField
<jfloat
>,
2243 _Jv_JNI_GetStaticField
<jdouble
>,
2244 _Jv_JNI_SetStaticField
,
2245 _Jv_JNI_SetStaticField
,
2246 _Jv_JNI_SetStaticField
,
2247 _Jv_JNI_SetStaticField
,
2248 _Jv_JNI_SetStaticField
,
2249 _Jv_JNI_SetStaticField
,
2250 _Jv_JNI_SetStaticField
,
2251 _Jv_JNI_SetStaticField
,
2252 _Jv_JNI_SetStaticField
,
2254 _Jv_JNI_GetStringLength
,
2255 _Jv_JNI_GetStringChars
,
2256 _Jv_JNI_ReleaseStringChars
,
2257 _Jv_JNI_NewStringUTF
,
2258 _Jv_JNI_GetStringUTFLength
,
2259 _Jv_JNI_GetStringUTFChars
,
2260 _Jv_JNI_ReleaseStringUTFChars
,
2261 _Jv_JNI_GetArrayLength
,
2262 _Jv_JNI_NewObjectArray
,
2263 _Jv_JNI_GetObjectArrayElement
,
2264 _Jv_JNI_SetObjectArrayElement
,
2265 _Jv_JNI_NewPrimitiveArray
<jboolean
, JvPrimClass (boolean
)>,
2266 _Jv_JNI_NewPrimitiveArray
<jbyte
, JvPrimClass (byte
)>,
2267 _Jv_JNI_NewPrimitiveArray
<jchar
, JvPrimClass (char)>,
2268 _Jv_JNI_NewPrimitiveArray
<jshort
, JvPrimClass (short)>,
2269 _Jv_JNI_NewPrimitiveArray
<jint
, JvPrimClass (int)>,
2270 _Jv_JNI_NewPrimitiveArray
<jlong
, JvPrimClass (long)>,
2271 _Jv_JNI_NewPrimitiveArray
<jfloat
, JvPrimClass (float)>,
2272 _Jv_JNI_NewPrimitiveArray
<jdouble
, JvPrimClass (double)>,
2273 _Jv_JNI_GetPrimitiveArrayElements
,
2274 _Jv_JNI_GetPrimitiveArrayElements
,
2275 _Jv_JNI_GetPrimitiveArrayElements
,
2276 _Jv_JNI_GetPrimitiveArrayElements
,
2277 _Jv_JNI_GetPrimitiveArrayElements
,
2278 _Jv_JNI_GetPrimitiveArrayElements
,
2279 _Jv_JNI_GetPrimitiveArrayElements
,
2280 _Jv_JNI_GetPrimitiveArrayElements
,
2281 _Jv_JNI_ReleasePrimitiveArrayElements
,
2282 _Jv_JNI_ReleasePrimitiveArrayElements
,
2283 _Jv_JNI_ReleasePrimitiveArrayElements
,
2284 _Jv_JNI_ReleasePrimitiveArrayElements
,
2285 _Jv_JNI_ReleasePrimitiveArrayElements
,
2286 _Jv_JNI_ReleasePrimitiveArrayElements
,
2287 _Jv_JNI_ReleasePrimitiveArrayElements
,
2288 _Jv_JNI_ReleasePrimitiveArrayElements
,
2289 _Jv_JNI_GetPrimitiveArrayRegion
,
2290 _Jv_JNI_GetPrimitiveArrayRegion
,
2291 _Jv_JNI_GetPrimitiveArrayRegion
,
2292 _Jv_JNI_GetPrimitiveArrayRegion
,
2293 _Jv_JNI_GetPrimitiveArrayRegion
,
2294 _Jv_JNI_GetPrimitiveArrayRegion
,
2295 _Jv_JNI_GetPrimitiveArrayRegion
,
2296 _Jv_JNI_GetPrimitiveArrayRegion
,
2297 _Jv_JNI_SetPrimitiveArrayRegion
,
2298 _Jv_JNI_SetPrimitiveArrayRegion
,
2299 _Jv_JNI_SetPrimitiveArrayRegion
,
2300 _Jv_JNI_SetPrimitiveArrayRegion
,
2301 _Jv_JNI_SetPrimitiveArrayRegion
,
2302 _Jv_JNI_SetPrimitiveArrayRegion
,
2303 _Jv_JNI_SetPrimitiveArrayRegion
,
2304 _Jv_JNI_SetPrimitiveArrayRegion
,
2305 _Jv_JNI_RegisterNatives
,
2306 _Jv_JNI_UnregisterNatives
,
2307 _Jv_JNI_MonitorEnter
,
2308 _Jv_JNI_MonitorExit
,
2311 _Jv_JNI_GetStringRegion
,
2312 _Jv_JNI_GetStringUTFRegion
,
2313 _Jv_JNI_GetPrimitiveArrayCritical
,
2314 _Jv_JNI_ReleasePrimitiveArrayCritical
,
2315 _Jv_JNI_GetStringCritical
,
2316 _Jv_JNI_ReleaseStringCritical
,
2318 NOT_IMPL
/* newweakglobalref */,
2319 NOT_IMPL
/* deleteweakglobalref */,
2321 _Jv_JNI_ExceptionCheck
2324 struct JNIInvokeInterface _Jv_JNI_InvokeFunctions
=
2330 _Jv_JNI_DestroyJavaVM
,
2331 _Jv_JNI_AttachCurrentThread
,
2332 _Jv_JNI_DetachCurrentThread
,