1 /* src/native/vm/java_lang_Class.c - java/lang/Class
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: java_lang_Class.c 8318 2007-08-16 10:05:34Z michi $
38 #include "mm/memory.h"
40 #include "native/jni.h"
41 #include "native/llni.h"
42 #include "native/native.h"
44 /* keep this order of the native includes */
46 #include "native/include/java_lang_String.h"
48 #if defined(ENABLE_JAVASE)
49 # if defined(WITH_CLASSPATH_SUN)
50 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
52 # include "native/include/java_lang_ClassLoader.h"
55 #include "native/include/java_lang_Object.h"
56 #include "native/include/java_lang_Class.h"
58 #if defined(ENABLE_JAVASE)
59 # include "native/include/java_lang_reflect_Constructor.h"
60 # include "native/include/java_lang_reflect_Field.h"
61 # include "native/include/java_lang_reflect_Method.h"
64 #include "native/vm/java_lang_Class.h"
65 #include "native/vm/java_lang_String.h"
67 #if defined(ENABLE_JAVASE)
68 # include "native/vm/reflect.h"
71 #include "toolbox/logging.h"
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/primitive.h"
78 #include "vm/resolve.h"
79 #include "vm/stringlocal.h"
81 #include "vmcore/class.h"
82 #include "vmcore/loader.h"
84 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
86 #include "vmcore/annotation.h"
87 #include "native/include/sun_reflect_ConstantPool.h"
91 * Class: java/lang/Class
93 * Signature: ()Ljava/lang/String;
95 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
102 c = (classinfo *) klass;
104 /* create a java string */
106 s = (java_lang_String *) javastring_new(c->name);
111 /* return string where '/' is replaced by '.' */
113 LLNI_field_get_ref(s, value, ca);
115 for (i = 0; i < LLNI_array_size(ca); i++) {
116 if (LLNI_array_direct(ca, i) == '/')
117 LLNI_array_direct(ca, i) = '.';
125 * Class: java/lang/Class
127 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
129 #if defined(ENABLE_JAVASE)
130 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
131 #elif defined(ENABLE_JAVAME_CLDC1_1)
132 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
135 #if defined(ENABLE_JAVASE)
144 #if defined(ENABLE_JAVASE)
145 cl = (classloader *) loader;
148 /* illegal argument */
151 exceptions_throw_nullpointerexception();
155 /* create utf string in which '.' is replaced by '/' */
157 ufile = javastring_toutf((java_handle_t *) name, true);
158 uname = javastring_toutf((java_handle_t *) name, false);
160 /* name must not contain '/' (mauve test) */
162 for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
164 exceptions_throw_classnotfoundexception(uname);
169 /* try to load, ... */
171 #if defined(ENABLE_JAVASE)
172 c = load_class_from_classloader(ufile, cl);
173 #elif defined(ENABLE_JAVAME_CLDC1_1)
174 c = load_class_bootstrap(ufile);
185 /* ...and initialize it, if required */
187 #if defined(ENABLE_JAVASE)
190 if (!initialize_class(c))
193 return (java_lang_Class *) c;
198 * Class: java/lang/Class
200 * Signature: (Ljava/lang/Object;)Z
202 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
207 c = (classinfo *) klass;
208 ob = (java_handle_t *) o;
210 if (!(c->state & CLASS_LINKED))
214 return builtin_instanceof(ob, c);
219 * Class: java/lang/Class
220 * Method: isAssignableFrom
221 * Signature: (Ljava/lang/Class;)Z
223 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
228 kc = (classinfo *) klass;
229 cc = (classinfo *) c;
232 exceptions_throw_nullpointerexception();
236 if (!(kc->state & CLASS_LINKED))
240 if (!(cc->state & CLASS_LINKED))
244 return class_isanysubclass(cc, kc);
249 * Class: java/lang/Class
250 * Method: isInterface
253 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
257 c = (classinfo *) this;
259 return class_is_interface(c);
263 #if defined(ENABLE_JAVASE)
266 * Class: java/lang/Class
267 * Method: isPrimitive
270 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
274 c = (classinfo *) klass;
276 return class_is_primitive(c);
281 * Class: java/lang/Class
282 * Method: getSuperclass
283 * Signature: ()Ljava/lang/Class;
285 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
290 c = (classinfo *) klass;
292 super = class_get_superclass(c);
294 return (java_lang_Class *) super;
299 * Class: java/lang/Class
300 * Method: getInterfaces
301 * Signature: ()[Ljava/lang/Class;
303 java_handle_objectarray_t *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
306 java_handle_objectarray_t *oa;
308 c = (classinfo *) klass;
310 oa = class_get_interfaces(c);
317 * Class: java/lang/Class
318 * Method: getComponentType
319 * Signature: ()Ljava/lang/Class;
321 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
325 arraydescriptor *desc;
327 c = (classinfo *) klass;
329 /* XXX maybe we could find a way to do this without linking. */
330 /* This way should be safe and easy, however. */
332 if (!(c->state & CLASS_LINKED))
336 desc = c->vftbl->arraydesc;
341 if (desc->arraytype == ARRAYTYPE_OBJECT)
342 comp = desc->componentvftbl->class;
344 comp = primitive_class_get_by_type(desc->arraytype);
346 return (java_lang_Class *) comp;
351 * Class: java/lang/Class
352 * Method: getModifiers
355 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
358 classref_or_classinfo inner;
359 classref_or_classinfo outer;
363 c = (classinfo *) klass;
365 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
366 /* search for passed class as inner class */
368 for (i = 0; i < c->innerclasscount; i++) {
369 inner = c->innerclass[i].inner_class;
370 outer = c->innerclass[i].outer_class;
372 /* Check if inner is a classref or a real class and get
373 the name of the structure */
375 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
377 /* innerclass is this class */
379 if (innername == c->name) {
380 /* has the class actually an outer class? */
383 /* return flags got from the outer class file */
384 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
386 return c->flags & ACC_CLASS_REFLECT_MASK;
391 /* passed class is no inner class or it was not requested */
393 return c->flags & ACC_CLASS_REFLECT_MASK;
398 * Class: java/lang/Class
399 * Method: getDeclaringClass
400 * Signature: ()Ljava/lang/Class;
402 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
406 c = (classinfo *) klass;
408 return (java_lang_Class *) class_get_declaringclass(c);
413 * Class: java/lang/Class
414 * Method: getDeclaredClasses
415 * Signature: (Z)[Ljava/lang/Class;
417 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
420 java_handle_objectarray_t *oa;
422 c = (classinfo *) klass;
424 oa = class_get_declaredclasses(c, publicOnly);
431 * Class: java/lang/Class
432 * Method: getDeclaredFields
433 * Signature: (Z)[Ljava/lang/reflect/Field;
435 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
438 java_handle_objectarray_t *oa; /* result: array of field-objects */
440 java_lang_reflect_Field *rf;
441 s4 public_fields; /* number of elements in field-array */
445 c = (classinfo *) klass;
447 /* determine number of fields */
449 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
450 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
453 /* create array of fields */
455 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
460 /* get the fields and store in the array */
462 for (i = 0, pos = 0; i < c->fieldscount; i++) {
465 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
466 /* create Field object */
468 rf = reflect_field_new(f);
470 /* store object into array */
473 LLNI_objectarray_element_set(oa, pos, rf);
482 * Class: java/lang/Class
483 * Method: getDeclaredMethods
484 * Signature: (Z)[Ljava/lang/reflect/Method;
486 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
489 java_lang_reflect_Method *rm;
490 java_handle_objectarray_t *oa; /* result: array of Method-objects */
491 methodinfo *m; /* the current method to be represented */
492 s4 public_methods; /* number of public methods of the class */
496 c = (classinfo *) klass;
500 /* JOWENN: array classes do not declare methods according to mauve
501 test. It should be considered, if we should return to my old
502 clone method overriding instead of declaring it as a member
505 if (class_is_array(c))
506 return builtin_anewarray(0, class_java_lang_reflect_Method);
508 /* determine number of methods */
510 for (i = 0; i < c->methodscount; i++) {
513 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
514 ((m->name != utf_init) && (m->name != utf_clinit)) &&
515 !(m->flags & ACC_MIRANDA))
519 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
524 for (i = 0, pos = 0; i < c->methodscount; i++) {
527 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
528 ((m->name != utf_init) && (m->name != utf_clinit)) &&
529 !(m->flags & ACC_MIRANDA)) {
530 /* create Method object */
532 rm = reflect_method_new(m);
534 /* store object into array */
537 LLNI_objectarray_element_set(oa, pos, rm);
546 * Class: java/lang/Class
547 * Method: getDeclaredConstructors
548 * Signature: (Z)[Ljava/lang/reflect/Constructor;
550 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
553 methodinfo *m; /* the current method to be represented */
554 java_handle_objectarray_t *oa; /* result: array of Method-objects */
555 java_lang_reflect_Constructor *rc;
556 s4 public_methods; /* number of public methods of the class */
560 c = (classinfo *) klass;
562 /* determine number of constructors */
564 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
567 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
568 (m->name == utf_init))
572 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
577 for (i = 0, pos = 0; i < c->methodscount; i++) {
580 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
581 (m->name == utf_init)) {
582 /* create Constructor object */
584 rc = reflect_constructor_new(m);
586 /* store object into array */
589 LLNI_objectarray_element_set(oa, pos, rc);
598 * Class: java/lang/Class
599 * Method: getClassLoader
600 * Signature: ()Ljava/lang/ClassLoader;
602 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
606 c = (classinfo *) klass;
608 return (java_lang_ClassLoader *) c->classloader;
611 #endif /* defined(ENABLE_JAVASE) */
615 * Class: java/lang/Class
619 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
623 c = (classinfo *) this;
625 return class_is_array(c);
629 #if defined(ENABLE_JAVASE)
632 * Class: java/lang/Class
633 * Method: throwException
634 * Signature: (Ljava/lang/Throwable;)V
636 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
640 o = (java_handle_t *) t;
642 exceptions_set_exception(o);
646 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
648 * Class: java/lang/Class
649 * Method: getDeclaredAnnotations
650 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
652 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
654 classinfo *c = (classinfo*)klass;
655 static methodinfo *m_parseAnnotationsIntoArray = NULL;
656 utf *utf_parseAnnotationsIntoArray = NULL;
657 utf *utf_desc = NULL;
658 java_handle_bytearray_t *annotations = NULL;
659 sun_reflect_ConstantPool *constantPool = NULL;
661 java_lang_Object *constantPoolOop = (java_lang_Object*)klass;
664 exceptions_throw_nullpointerexception();
668 /* Return null for arrays and primitives: */
669 if (class_is_primitive(c) || class_is_array(c)) {
673 if (c->annotations != NULL) {
674 size = c->annotations->size;
675 annotations = builtin_newarray_byte(size);
677 if(annotations != NULL) {
678 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
683 (sun_reflect_ConstantPool*)native_new_and_init(
684 class_sun_reflect_ConstantPool);
686 if(constantPool == NULL) {
691 LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
693 /* only resolve the method the first time */
694 if (m_parseAnnotationsIntoArray == NULL) {
695 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
696 utf_desc = utf_new_char(
697 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
698 "[Ljava/lang/annotation/Annotation;");
700 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
705 m_parseAnnotationsIntoArray = class_resolveclassmethod(
706 class_sun_reflect_annotation_AnnotationParser,
707 utf_parseAnnotationsIntoArray,
709 class_java_lang_Class,
712 if (m_parseAnnotationsIntoArray == NULL) {
713 /* method not found */
718 return (java_handle_objectarray_t*)vm_call_method(
719 m_parseAnnotationsIntoArray, NULL,
720 annotations, constantPool, klass);
726 * Class: java/lang/Class
727 * Method: getEnclosingClass
728 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
730 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
733 classref_or_classinfo cr;
736 c = (classinfo *) klass;
738 /* get enclosing class */
740 cr = c->enclosingclass;
745 /* resolve the class if necessary */
747 if (IS_CLASSREF(cr)) {
748 ec = resolve_classref_eager(cr.ref);
756 return (java_lang_Class *) ec;
760 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
762 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
763 _Jv_java_lang_Class_getEnclosingMethod.
765 *******************************************************************************/
767 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
769 classref_or_classinfo cr;
770 constant_nameandtype *cn;
774 /* get enclosing class and method */
776 cr = c->enclosingclass;
777 cn = c->enclosingmethod;
779 /* check for enclosing class and method */
787 /* resolve the class if necessary */
789 if (IS_CLASSREF(cr)) {
790 ec = resolve_classref_eager(cr.ref);
798 /* find method in enclosing class */
800 m = class_findmethod(ec, cn->name, cn->descriptor);
803 exceptions_throw_internalerror("Enclosing method doesn't exist");
812 * Class: java/lang/Class
813 * Method: getEnclosingConstructor
814 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
816 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
820 java_lang_reflect_Constructor *rc;
822 c = (classinfo *) klass;
824 /* get enclosing method */
826 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
831 /* check for <init> */
833 if (m->name != utf_init)
836 /* create Constructor object */
838 rc = reflect_constructor_new(m);
845 * Class: java/lang/Class
846 * Method: getEnclosingMethod
847 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
849 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
853 java_lang_reflect_Method *rm;
855 c = (classinfo *) klass;
857 /* get enclosing method */
859 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
864 /* check for <init> */
866 if (m->name == utf_init)
869 /* create java.lang.reflect.Method object */
871 rm = reflect_method_new(m);
878 * Class: java/lang/Class
879 * Method: getClassSignature
880 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
882 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
887 c = (classinfo *) klass;
889 if (c->signature == NULL)
892 o = javastring_new(c->signature);
894 /* in error case o is NULL */
896 return (java_lang_String *) o;
902 * Class: java/lang/Class
903 * Method: isAnonymousClass
904 * Signature: (Ljava/lang/Class;)Z
906 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
910 * Class: java/lang/VMClass
911 * Method: isLocalClass
912 * Signature: (Ljava/lang/Class;)Z
914 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
918 * Class: java/lang/VMClass
919 * Method: isMemberClass
920 * Signature: (Ljava/lang/Class;)Z
922 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
925 #endif /* ENABLE_JAVASE */
929 * These are local overrides for various environment variables in Emacs.
930 * Please do not remove this and leave it at the end of the file, where
931 * Emacs will automagically detect them.
932 * ---------------------------------------------------------------------
935 * indent-tabs-mode: t
939 * vim:noexpandtab:sw=4:ts=4: