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 8123 2007-06-20 23:50:55Z michi $
37 #include "mm/memory.h"
39 #include "native/jni.h"
40 #include "native/native.h"
42 #if defined(ENABLE_JAVAME_CLDC1_1)
43 # include "native/include/java_lang_String.h"/* required by java_lang_Class.h */
46 #include "native/include/java_lang_Class.h"
47 #include "native/include/java_lang_Object.h"
49 #if defined(ENABLE_JAVASE)
50 # include "native/include/java_lang_ClassLoader.h"
51 # include "native/include/java_lang_reflect_Constructor.h"
52 # include "native/include/java_lang_reflect_Field.h"
53 # include "native/include/java_lang_reflect_Method.h"
56 #include "native/vm/java_lang_Class.h"
58 #include "toolbox/logging.h"
60 #include "vm/builtin.h"
61 #include "vm/exceptions.h"
62 #include "vm/global.h"
63 #include "vm/initialize.h"
64 #include "vm/resolve.h"
65 #include "vm/stringlocal.h"
67 #include "vmcore/class.h"
68 #include "vmcore/loader.h"
69 #include "vmcore/primitive.h"
73 * Class: java/lang/Class
75 * Signature: ()Ljava/lang/String;
77 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
83 c = (classinfo *) klass;
85 /* create a java string */
87 s = (java_lang_String *) javastring_new(c->name);
92 /* return string where '/' is replaced by '.' */
94 for (i = 0; i < s->value->header.size; i++) {
95 if (s->value->data[i] == '/')
96 s->value->data[i] = '.';
104 * Class: java/lang/Class
106 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
108 #if defined(ENABLE_JAVASE)
109 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
110 #elif defined(ENABLE_JAVAME_CLDC1_1)
111 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
114 #if defined(ENABLE_JAVASE)
123 #if defined(ENABLE_JAVASE)
124 cl = loader_hashtable_classloader_add((java_objectheader *) loader);
127 /* illegal argument */
130 exceptions_throw_nullpointerexception();
134 /* create utf string in which '.' is replaced by '/' */
136 ufile = javastring_toutf((java_objectheader *) name, true);
137 uname = javastring_toutf((java_objectheader *) name, false);
139 /* name must not contain '/' (mauve test) */
141 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
143 exceptions_throw_classnotfoundexception(uname);
148 /* try to load, ... */
150 #if defined(ENABLE_JAVASE)
151 c = load_class_from_classloader(ufile, cl);
152 #elif defined(ENABLE_JAVAME_CLDC1_1)
153 c = load_class_bootstrap(ufile);
164 /* ...and initialize it, if required */
166 #if defined(ENABLE_JAVASE)
169 if (!initialize_class(c))
172 return (java_lang_Class *) c;
177 * Class: java/lang/Class
179 * Signature: (Ljava/lang/Object;)Z
181 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
184 java_objectheader *ob;
186 c = (classinfo *) klass;
187 ob = (java_objectheader *) o;
189 if (!(c->state & CLASS_LINKED))
193 return builtin_instanceof(ob, c);
198 * Class: java/lang/Class
199 * Method: isAssignableFrom
200 * Signature: (Ljava/lang/Class;)Z
202 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
207 kc = (classinfo *) klass;
208 cc = (classinfo *) c;
211 exceptions_throw_nullpointerexception();
215 if (!(kc->state & CLASS_LINKED))
219 if (!(cc->state & CLASS_LINKED))
223 return class_isanysubclass(cc, kc);
228 * Class: java/lang/Class
229 * Method: isInterface
232 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
236 c = (classinfo *) klass;
238 if (c->flags & ACC_INTERFACE)
245 #if defined(ENABLE_JAVASE)
248 * Class: java/lang/Class
249 * Method: isPrimitive
252 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
257 c = (classinfo *) klass;
259 result = primitive_class_is_primitive(c);
266 * Class: java/lang/Class
267 * Method: getSuperclass
268 * Signature: ()Ljava/lang/Class;
270 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
275 c = (classinfo *) klass;
277 /* for java.lang.Object, primitive and Void classes we return NULL */
282 /* for interfaces we also return NULL */
284 if (c->flags & ACC_INTERFACE)
287 /* we may have to resolve the super class reference */
289 if ((sc = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
292 /* store the resolution */
296 return (java_lang_Class *) sc;
301 * Class: java/lang/Class
302 * Method: getInterfaces
303 * Signature: ()[Ljava/lang/Class;
305 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
309 java_objectarray *oa;
312 c = (classinfo *) klass;
314 if (!(c->state & CLASS_LINKED))
318 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
323 for (i = 0; i < c->interfacescount; i++) {
324 ic = c->interfaces[i].cls;
326 oa->data[i] = (java_objectheader *) ic;
334 * Class: java/lang/Class
335 * Method: getComponentType
336 * Signature: ()Ljava/lang/Class;
338 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
342 arraydescriptor *desc;
344 c = (classinfo *) klass;
346 /* XXX maybe we could find a way to do this without linking. */
347 /* This way should be safe and easy, however. */
349 if (!(c->state & CLASS_LINKED))
353 desc = c->vftbl->arraydesc;
358 if (desc->arraytype == ARRAYTYPE_OBJECT)
359 comp = desc->componentvftbl->class;
361 comp = primitive_class_get_by_type(desc->arraytype);
363 return (java_lang_Class *) comp;
368 * Class: java/lang/Class
369 * Method: getModifiers
372 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
375 classref_or_classinfo inner;
376 classref_or_classinfo outer;
380 c = (classinfo *) klass;
382 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
383 /* search for passed class as inner class */
385 for (i = 0; i < c->innerclasscount; i++) {
386 inner = c->innerclass[i].inner_class;
387 outer = c->innerclass[i].outer_class;
389 /* Check if inner is a classref or a real class and get
390 the name of the structure */
392 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
394 /* innerclass is this class */
396 if (innername == c->name) {
397 /* has the class actually an outer class? */
400 /* return flags got from the outer class file */
401 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
403 return c->flags & ACC_CLASS_REFLECT_MASK;
408 /* passed class is no inner class or it was not requested */
410 return c->flags & ACC_CLASS_REFLECT_MASK;
415 * Class: java/lang/Class
416 * Method: getDeclaringClass
417 * Signature: ()Ljava/lang/Class;
419 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
422 classref_or_classinfo inner;
427 c = (classinfo *) klass;
429 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
430 if (c->innerclasscount == 0) /* no innerclasses exist */
433 for (i = 0; i < c->innerclasscount; i++) {
434 inner = c->innerclass[i].inner_class;
436 /* check if inner_class is a classref or a real class and
437 get the class name from the structure */
439 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
441 /* innerclass is this class */
443 if (innername == c->name) {
444 /* maybe the outer class is not loaded yet */
446 if ((outer = resolve_classref_or_classinfo_eager(
447 c->innerclass[i].outer_class,
451 if (!(outer->state & CLASS_LINKED))
452 if (!link_class(outer))
455 return (java_lang_Class *) outer;
460 /* return NULL for arrayclasses and primitive classes */
467 * Class: java/lang/Class
468 * Method: getDeclaredClasses
469 * Signature: (Z)[Ljava/lang/Class;
471 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
474 classref_or_classinfo outer;
476 s4 declaredclasscount; /* number of declared classes */
477 s4 pos; /* current declared class */
478 java_objectarray *oa; /* array of declared classes */
481 c = (classinfo *) klass;
482 declaredclasscount = 0;
484 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
485 /* determine number of declared classes */
487 for (i = 0; i < c->innerclasscount; i++) {
488 outer = c->innerclass[i].outer_class;
490 /* check if outer_class is a classref or a real class and
491 get the class name from the structure */
493 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
495 /* outer class is this class */
497 if ((outername == c->name) &&
498 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
499 declaredclasscount++;
503 /* allocate Class[] and check for OOM */
505 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
510 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
511 outer = c->innerclass[i].outer_class;
513 /* check if outer_class is a classref or a real class and
514 get the class name from the structure */
516 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
518 /* outer class is this class */
520 if ((outername == c->name) &&
521 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
524 if ((inner = resolve_classref_or_classinfo_eager(
525 c->innerclass[i].inner_class,
529 if (!(inner->state & CLASS_LINKED))
530 if (!link_class(inner))
533 oa->data[pos++] = (java_objectheader *) inner;
542 * Class: java/lang/Class
543 * Method: getDeclaredFields
544 * Signature: (Z)[Ljava/lang/reflect/Field;
546 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
549 java_objectarray *oa; /* result: array of field-objects */
551 java_objectheader *o;
552 java_lang_reflect_Field *rf;
553 s4 public_fields; /* number of elements in field-array */
557 c = (classinfo *) klass;
559 /* determine number of fields */
561 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
562 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
565 /* create array of fields */
567 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
572 /* get the fields and store in the array */
574 for (i = 0, pos = 0; i < c->fieldscount; i++) {
577 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
578 /* create Field object */
580 o = native_new_and_init(class_java_lang_reflect_Field);
585 /* initialize instance fields */
587 rf = (java_lang_reflect_Field *) o;
589 rf->declaringClass = (java_lang_Class *) c;
590 rf->name = (java_lang_String *) javastring_new(f->name);
593 /* store object into array */
604 * Class: java/lang/Class
605 * Method: getDeclaredMethods
606 * Signature: (Z)[Ljava/lang/reflect/Method;
608 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
611 java_objectheader *o;
612 java_lang_reflect_Method *rm;
613 java_objectarray *oa; /* result: array of Method-objects */
614 methodinfo *m; /* the current method to be represented */
615 s4 public_methods; /* number of public methods of the class */
619 c = (classinfo *) klass;
622 /* JOWENN: array classes do not declare methods according to mauve
623 test. It should be considered, if we should return to my old
624 clone method overriding instead of declaring it as a member
627 if (_Jv_java_lang_Class_isArray(klass))
628 return builtin_anewarray(0, class_java_lang_reflect_Method);
630 /* determine number of methods */
632 for (i = 0; i < c->methodscount; i++) {
635 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
636 ((m->name != utf_init) && (m->name != utf_clinit)) &&
637 !(m->flags & ACC_MIRANDA))
641 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
646 for (i = 0, pos = 0; i < c->methodscount; i++) {
649 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
650 ((m->name != utf_init) && (m->name != utf_clinit)) &&
651 !(m->flags & ACC_MIRANDA)) {
653 o = native_new_and_init(class_java_lang_reflect_Method);
658 /* initialize instance fields */
660 rm = (java_lang_reflect_Method *) o;
662 rm->declaringClass = (java_lang_Class *) m->class;
663 rm->name = (java_lang_String *) javastring_new(m->name);
666 /* store object into array */
677 * Class: java/lang/Class
678 * Method: getDeclaredConstructors
679 * Signature: (Z)[Ljava/lang/reflect/Constructor;
681 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
684 methodinfo *m; /* the current method to be represented */
685 java_objectarray *oa; /* result: array of Method-objects */
686 java_objectheader *o;
687 java_lang_reflect_Constructor *rc;
688 s4 public_methods; /* number of public methods of the class */
692 c = (classinfo *) klass;
694 /* determine number of constructors */
696 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
699 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
700 (m->name == utf_init))
704 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
709 for (i = 0, pos = 0; i < c->methodscount; i++) {
712 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
713 (m->name == utf_init)) {
715 o = native_new_and_init(class_java_lang_reflect_Constructor);
720 /* initialize instance fields */
722 rc = (java_lang_reflect_Constructor *) o;
724 rc->clazz = (java_lang_Class *) c;
727 /* store object into array */
738 * Class: java/lang/Class
739 * Method: getClassLoader
740 * Signature: ()Ljava/lang/ClassLoader;
742 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
746 c = (classinfo *) klass;
748 if (c->classloader == NULL)
751 return (java_lang_ClassLoader *) c->classloader->object;
754 #endif /* defined(ENABLE_JAVASE) */
758 * Class: java/lang/Class
762 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
766 c = (classinfo *) klass;
768 if (!(c->state & CLASS_LINKED))
772 return (c->vftbl->arraydesc != NULL);
776 #if defined(ENABLE_JAVASE)
779 * Class: java/lang/Class
780 * Method: throwException
781 * Signature: (Ljava/lang/Throwable;)V
783 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
785 java_objectheader *o;
787 o = (java_objectheader *) t;
789 exceptions_set_exception(o);
795 * Class: java/lang/Class
796 * Method: getDeclaredAnnotations
797 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
799 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
806 * Class: java/lang/Class
807 * Method: getEnclosingClass
808 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
810 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
813 classref_or_classinfo cr;
816 c = (classinfo *) klass;
818 /* get enclosing class */
820 cr = c->enclosingclass;
825 /* resolve the class if necessary */
827 if (IS_CLASSREF(cr)) {
828 ec = resolve_classref_eager(cr.ref);
836 return (java_lang_Class *) ec;
840 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
842 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
843 _Jv_java_lang_Class_getEnclosingMethod.
845 *******************************************************************************/
847 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
849 classref_or_classinfo cr;
850 constant_nameandtype *cn;
854 /* get enclosing class and method */
856 cr = c->enclosingclass;
857 cn = c->enclosingmethod;
859 /* check for enclosing class and method */
867 /* resolve the class if necessary */
869 if (IS_CLASSREF(cr)) {
870 ec = resolve_classref_eager(cr.ref);
878 /* find method in enclosing class */
880 m = class_findmethod(ec, cn->name, cn->descriptor);
883 exceptions_throw_internalerror("Enclosing method doesn't exist");
892 * Class: java/lang/Class
893 * Method: getEnclosingConstructor
894 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
896 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
900 java_objectheader *o;
901 java_lang_reflect_Constructor *rc;
903 c = (classinfo *) klass;
905 /* get enclosing method */
907 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
912 /* check for <init> */
914 if (m->name != utf_init)
917 /* create java.lang.reflect.Constructor object */
919 o = native_new_and_init(class_java_lang_reflect_Constructor);
924 /* initialize instance fields */
926 rc = (java_lang_reflect_Constructor *) o;
928 rc->clazz = (java_lang_Class *) m->class;
929 rc->slot = m - m->class->methods; /* calculate method slot */
936 * Class: java/lang/Class
937 * Method: getEnclosingMethod
938 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
940 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
944 java_objectheader *o;
945 java_lang_reflect_Method *rm;
947 c = (classinfo *) klass;
949 /* get enclosing method */
951 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
956 /* check for <init> */
958 if (m->name == utf_init)
961 /* create java.lang.reflect.Method object */
963 o = native_new_and_init(class_java_lang_reflect_Method);
968 /* initialize instance fields */
970 rm = (java_lang_reflect_Method *) o;
972 rm->declaringClass = (java_lang_Class *) m->class;
973 rm->name = (java_lang_String *) javastring_new(m->name);
974 rm->slot = m - m->class->methods; /* calculate method slot */
981 * Class: java/lang/Class
982 * Method: getClassSignature
983 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
985 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
988 java_objectheader *o;
990 c = (classinfo *) klass;
992 if (c->signature == NULL)
995 o = javastring_new(c->signature);
997 /* in error case o is NULL */
999 return (java_lang_String *) o;
1005 * Class: java/lang/Class
1006 * Method: isAnonymousClass
1007 * Signature: (Ljava/lang/Class;)Z
1009 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1013 * Class: java/lang/VMClass
1014 * Method: isLocalClass
1015 * Signature: (Ljava/lang/Class;)Z
1017 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1021 * Class: java/lang/VMClass
1022 * Method: isMemberClass
1023 * Signature: (Ljava/lang/Class;)Z
1025 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1028 #endif /* ENABLE_JAVASE */
1032 * These are local overrides for various environment variables in Emacs.
1033 * Please do not remove this and leave it at the end of the file, where
1034 * Emacs will automagically detect them.
1035 * ---------------------------------------------------------------------
1038 * indent-tabs-mode: t
1042 * vim:noexpandtab:sw=4:ts=4: