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_VMClass.c 6131 2006-12-06 22:15:57Z twisti $
37 #include "mm/memory.h"
39 #include "native/jni.h"
40 #include "native/native.h"
41 #include "native/include/java_lang_Class.h"
42 #include "native/include/java_lang_Object.h"
44 #if defined(ENABLE_JAVASE)
45 # include "native/include/java_lang_ClassLoader.h"
46 # include "native/include/java_lang_reflect_Constructor.h"
47 # include "native/include/java_lang_reflect_Field.h"
48 # include "native/include/java_lang_reflect_Method.h"
51 #include "native/vm/java_lang_Class.h"
53 #include "toolbox/logging.h"
55 #include "vm/builtin.h"
56 #include "vm/exceptions.h"
57 #include "vm/global.h"
58 #include "vm/initialize.h"
59 #include "vm/stringlocal.h"
61 #include "vmcore/class.h"
62 #include "vmcore/loader.h"
63 #include "vmcore/resolve.h"
67 * Class: java/lang/Class
69 * Signature: ()Ljava/lang/String;
71 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
77 c = (classinfo *) klass;
79 /* create a java string */
81 s = (java_lang_String *) javastring_new(c->name);
86 /* return string where '/' is replaced by '.' */
88 for (i = 0; i < s->value->header.size; i++) {
89 if (s->value->data[i] == '/')
90 s->value->data[i] = '.';
98 * Class: java/lang/Class
100 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
102 #if defined(ENABLE_JAVASE)
103 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
104 #elif defined(ENABLE_JAVAME_CLDC1_1)
105 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
108 java_objectheader *cl;
112 java_objectheader *xptr;
117 cl = (java_objectheader *) loader;
119 /* illegal argument */
122 exceptions_throw_nullpointerexception();
126 /* create utf string in which '.' is replaced by '/' */
128 ufile = javastring_toutf(name, true);
129 uname = javastring_toutf(name, false);
131 /* name must not contain '/' (mauve test) */
133 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
135 exceptions_throw_classnotfoundexception(uname);
140 /* try to load, ... */
142 #if defined(ENABLE_JAVASE)
143 c = load_class_from_classloader(ufile, cl);
144 #elif defined(ENABLE_JAVAME_CLDC1_1)
145 c = load_class_bootstrap(ufile);
149 xptr = exceptions_get_exception();
151 xclass = xptr->vftbl->class;
153 /* if the exception is a NoClassDefFoundError, we replace it with a
154 ClassNotFoundException, otherwise return the exception */
156 if (xclass == class_java_lang_NoClassDefFoundError) {
157 /* clear exceptionptr, because builtin_new checks for
158 ExceptionInInitializerError */
159 exceptions_clear_exception();
161 exceptions_throw_classnotfoundexception(uname);
172 /* ...and initialize it, if required */
174 #if defined(ENABLE_JAVASE)
177 if (!initialize_class(c))
180 return (java_lang_Class *) c;
184 #if defined(ENABLE_JAVASE)
187 * Class: java/lang/Class
189 * Signature: (Ljava/lang/Object;)Z
191 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
194 java_objectheader *ob;
196 c = (classinfo *) klass;
197 ob = (java_objectheader *) o;
199 if (!(c->state & CLASS_LINKED))
203 return builtin_instanceof(ob, c);
208 * Class: java/lang/Class
209 * Method: isAssignableFrom
210 * Signature: (Ljava/lang/Class;)Z
212 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
217 kc = (classinfo *) klass;
218 cc = (classinfo *) c;
221 exceptions_throw_nullpointerexception();
225 if (!(kc->state & CLASS_LINKED))
229 if (!(cc->state & CLASS_LINKED))
233 /* XXX this may be wrong for array classes */
235 return builtin_isanysubclass(cc, kc);
240 * Class: java/lang/Class
241 * Method: isInterface
244 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
248 c = (classinfo *) klass;
250 if (c->flags & ACC_INTERFACE)
258 * Class: java/lang/Class
259 * Method: isPrimitive
262 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
267 c = (classinfo *) klass;
269 /* search table of primitive classes */
271 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
272 if (primitivetype_table[i].class_primitive == c)
280 * Class: java/lang/Class
281 * Method: getSuperclass
282 * Signature: ()Ljava/lang/Class;
284 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
289 c = (classinfo *) klass;
291 /* for java.lang.Object, primitive and Void classes we return NULL */
296 /* for interfaces we also return NULL */
298 if (c->flags & ACC_INTERFACE)
301 /* we may have to resolve the super class reference */
303 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager,
304 true, /* check access */
305 false, /* don't link */
311 /* store the resolution */
315 return (java_lang_Class *) sc;
320 * Class: java/lang/Class
321 * Method: getInterfaces
322 * Signature: ()[Ljava/lang/Class;
324 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
328 java_objectarray *oa;
331 c = (classinfo *) klass;
333 if (!(c->state & CLASS_LINKED))
337 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
342 for (i = 0; i < c->interfacescount; i++) {
343 ic = c->interfaces[i].cls;
345 oa->data[i] = (java_objectheader *) ic;
353 * Class: java/lang/Class
354 * Method: getComponentType
355 * Signature: ()Ljava/lang/Class;
357 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
361 arraydescriptor *desc;
363 c = (classinfo *) klass;
365 /* XXX maybe we could find a way to do this without linking. */
366 /* This way should be safe and easy, however. */
368 if (!(c->state & CLASS_LINKED))
372 desc = c->vftbl->arraydesc;
377 if (desc->arraytype == ARRAYTYPE_OBJECT)
378 comp = desc->componentvftbl->class;
380 comp = primitivetype_table[desc->arraytype].class_primitive;
382 return (java_lang_Class *) comp;
387 * Class: java/lang/Class
388 * Method: getModifiers
391 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
394 classref_or_classinfo inner;
395 classref_or_classinfo outer;
399 c = (classinfo *) klass;
401 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
402 /* search for passed class as inner class */
404 for (i = 0; i < c->innerclasscount; i++) {
405 inner = c->innerclass[i].inner_class;
406 outer = c->innerclass[i].outer_class;
408 /* Check if inner is a classref or a real class and get
409 the name of the structure */
411 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
413 /* innerclass is this class */
415 if (innername == c->name) {
416 /* has the class actually an outer class? */
419 /* return flags got from the outer class file */
420 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
422 return c->flags & ACC_CLASS_REFLECT_MASK;
427 /* passed class is no inner class or it was not requested */
429 return c->flags & ACC_CLASS_REFLECT_MASK;
434 * Class: java/lang/Class
435 * Method: getDeclaringClass
436 * Signature: ()Ljava/lang/Class;
438 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
441 classref_or_classinfo inner;
446 c = (classinfo *) klass;
448 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
449 if (c->innerclasscount == 0) /* no innerclasses exist */
452 for (i = 0; i < c->innerclasscount; i++) {
453 inner = c->innerclass[i].inner_class;
455 /* check if inner_class is a classref or a real class and
456 get the class name from the structure */
458 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
460 /* innerclass is this class */
462 if (innername == c->name) {
463 /* maybe the outer class is not loaded yet */
465 if (!resolve_classref_or_classinfo(NULL,
466 c->innerclass[i].outer_class,
467 resolveEager, false, false,
471 if (!(outer->state & CLASS_LINKED))
472 if (!link_class(outer))
475 return (java_lang_Class *) outer;
480 /* return NULL for arrayclasses and primitive classes */
487 * Class: java/lang/Class
488 * Method: getDeclaredClasses
489 * Signature: (Z)[Ljava/lang/Class;
491 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
494 classref_or_classinfo outer;
496 s4 declaredclasscount; /* number of declared classes */
497 s4 pos; /* current declared class */
498 java_objectarray *oa; /* array of declared classes */
501 c = (classinfo *) klass;
502 declaredclasscount = 0;
504 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
505 /* determine number of declared classes */
507 for (i = 0; i < c->innerclasscount; i++) {
508 outer = c->innerclass[i].outer_class;
510 /* check if outer_class is a classref or a real class and
511 get the class name from the structure */
513 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
515 /* outer class is this class */
517 if ((outername == c->name) &&
518 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
519 declaredclasscount++;
523 /* allocate Class[] and check for OOM */
525 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
530 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
531 outer = c->innerclass[i].outer_class;
533 /* check if outer_class is a classref or a real class and
534 get the class name from the structure */
536 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
538 /* outer class is this class */
540 if ((outername == c->name) &&
541 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
544 if (!resolve_classref_or_classinfo(NULL,
545 c->innerclass[i].inner_class,
546 resolveEager, false, false,
550 if (!(inner->state & CLASS_LINKED))
551 if (!link_class(inner))
554 oa->data[pos++] = (java_objectheader *) inner;
563 * Class: java/lang/Class
564 * Method: getDeclaredFields
565 * Signature: (Z)[Ljava/lang/reflect/Field;
567 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
570 java_objectarray *oa; /* result: array of field-objects */
572 java_objectheader *o;
573 java_lang_reflect_Field *rf;
574 s4 public_fields; /* number of elements in field-array */
578 c = (classinfo *) klass;
580 /* determine number of fields */
582 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
583 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
586 /* create array of fields */
588 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
593 /* get the fields and store in the array */
595 for (i = 0, pos = 0; i < c->fieldscount; i++) {
598 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
599 /* create Field object */
601 o = native_new_and_init(class_java_lang_reflect_Field);
606 /* initialize instance fields */
608 rf = (java_lang_reflect_Field *) o;
610 rf->declaringClass = (java_lang_Class *) c;
611 rf->name = javastring_new(f->name);
614 /* store object into array */
625 * Class: java/lang/Class
626 * Method: getDeclaredMethods
627 * Signature: (Z)[Ljava/lang/reflect/Method;
629 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
632 java_objectheader *o;
633 java_lang_reflect_Method *rm;
634 java_objectarray *oa; /* result: array of Method-objects */
635 methodinfo *m; /* the current method to be represented */
636 s4 public_methods; /* number of public methods of the class */
640 c = (classinfo *) klass;
643 /* JOWENN: array classes do not declare methods according to mauve
644 test. It should be considered, if we should return to my old
645 clone method overriding instead of declaring it as a member
648 if (_Jv_java_lang_Class_isArray(klass))
649 return builtin_anewarray(0, class_java_lang_reflect_Method);
651 /* determine number of methods */
653 for (i = 0; i < c->methodscount; i++) {
656 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
657 ((m->name != utf_init) && (m->name != utf_clinit)) &&
658 !(m->flags & ACC_MIRANDA))
662 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
667 for (i = 0, pos = 0; i < c->methodscount; i++) {
670 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
671 ((m->name != utf_init) && (m->name != utf_clinit)) &&
672 !(m->flags & ACC_MIRANDA)) {
674 o = native_new_and_init(class_java_lang_reflect_Method);
679 /* initialize instance fields */
681 rm = (java_lang_reflect_Method *) o;
683 rm->declaringClass = (java_lang_Class *) m->class;
684 rm->name = javastring_new(m->name);
687 /* store object into array */
698 * Class: java/lang/Class
699 * Method: getDeclaredConstructors
700 * Signature: (Z)[Ljava/lang/reflect/Constructor;
702 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
705 methodinfo *m; /* the current method to be represented */
706 java_objectarray *oa; /* result: array of Method-objects */
707 java_objectheader *o;
708 java_lang_reflect_Constructor *rc;
709 s4 public_methods; /* number of public methods of the class */
713 c = (classinfo *) klass;
715 /* determine number of constructors */
717 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
720 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
721 (m->name == utf_init))
725 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
730 for (i = 0, pos = 0; i < c->methodscount; i++) {
733 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
734 (m->name == utf_init)) {
736 o = native_new_and_init(class_java_lang_reflect_Constructor);
741 /* initialize instance fields */
743 rc = (java_lang_reflect_Constructor *) o;
745 rc->clazz = (java_lang_Class *) c;
748 /* store object into array */
759 * Class: java/lang/Class
760 * Method: getClassLoader
761 * Signature: ()Ljava/lang/ClassLoader;
763 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
767 c = (classinfo *) klass;
769 return (java_lang_ClassLoader *) c->classloader;
774 * Class: java/lang/Class
778 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
782 c = (classinfo *) klass;
784 if (!(c->state & CLASS_LINKED))
788 return (c->vftbl->arraydesc != NULL);
793 * Class: java/lang/Class
794 * Method: throwException
795 * Signature: (Ljava/lang/Throwable;)V
797 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
799 java_objectheader *o;
801 o = (java_objectheader *) t;
803 exceptions_set_exception(o);
809 * Class: java/lang/Class
810 * Method: getDeclaredAnnotations
811 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
813 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
820 * Class: java/lang/Class
821 * Method: getEnclosingClass
822 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
824 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
827 classref_or_classinfo cr;
830 c = (classinfo *) klass;
832 /* get enclosing class */
834 cr = c->enclosingclass;
839 /* resolve the class if necessary */
841 if (IS_CLASSREF(cr)) {
842 ec = resolve_classref_eager(cr.ref);
850 return (java_lang_Class *) ec;
854 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
856 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
857 _Jv_java_lang_Class_getEnclosingMethod.
859 *******************************************************************************/
861 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
863 classref_or_classinfo cr;
864 constant_nameandtype *cn;
868 /* get enclosing class and method */
870 cr = c->enclosingclass;
871 cn = c->enclosingmethod;
873 /* check for enclosing class and method */
881 /* resolve the class if necessary */
883 if (IS_CLASSREF(cr)) {
884 ec = resolve_classref_eager(cr.ref);
892 /* find method in enclosing class */
894 m = class_findmethod(ec, cn->name, cn->descriptor);
897 exceptions_throw_internalerror("Enclosing method doesn't exist");
906 * Class: java/lang/Class
907 * Method: getEnclosingConstructor
908 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
910 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
914 java_objectheader *o;
915 java_lang_reflect_Constructor *rc;
917 c = (classinfo *) klass;
919 /* get enclosing method */
921 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
926 /* check for <init> */
928 if (m->name != utf_init)
931 /* create java.lang.reflect.Constructor object */
933 o = native_new_and_init(class_java_lang_reflect_Constructor);
938 /* initialize instance fields */
940 rc = (java_lang_reflect_Constructor *) o;
942 rc->clazz = (java_lang_Class *) m->class;
943 rc->slot = m - m->class->methods; /* calculate method slot */
950 * Class: java/lang/Class
951 * Method: getEnclosingMethod
952 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
954 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
958 java_objectheader *o;
959 java_lang_reflect_Method *rm;
961 c = (classinfo *) klass;
963 /* get enclosing method */
965 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
970 /* check for <init> */
972 if (m->name == utf_init)
975 /* create java.lang.reflect.Method object */
977 o = native_new_and_init(class_java_lang_reflect_Method);
982 /* initialize instance fields */
984 rm = (java_lang_reflect_Method *) o;
986 rm->declaringClass = (java_lang_Class *) m->class;
987 rm->name = javastring_new(m->name);
988 rm->slot = m - m->class->methods; /* calculate method slot */
995 * Class: java/lang/Class
996 * Method: getClassSignature
997 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
999 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
1002 java_lang_String *s;
1004 c = (classinfo *) klass;
1006 if (c->signature == NULL)
1009 s = javastring_new(c->signature);
1011 /* in error case, s == NULL */
1019 * Class: java/lang/Class
1020 * Method: isAnonymousClass
1021 * Signature: (Ljava/lang/Class;)Z
1023 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1027 * Class: java/lang/VMClass
1028 * Method: isLocalClass
1029 * Signature: (Ljava/lang/Class;)Z
1031 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1035 * Class: java/lang/VMClass
1036 * Method: isMemberClass
1037 * Signature: (Ljava/lang/Class;)Z
1039 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1042 #endif /* ENABLE_JAVASE */
1046 * These are local overrides for various environment variables in Emacs.
1047 * Please do not remove this and leave it at the end of the file, where
1048 * Emacs will automagically detect them.
1049 * ---------------------------------------------------------------------
1052 * indent-tabs-mode: t
1056 * vim:noexpandtab:sw=4:ts=4: