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"
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/stringlocal.h"
66 #include "vmcore/class.h"
67 #include "vmcore/loader.h"
68 #include "vmcore/resolve.h"
72 * Class: java/lang/Class
74 * Signature: ()Ljava/lang/String;
76 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
82 c = (classinfo *) klass;
84 /* create a java string */
86 s = (java_lang_String *) javastring_new(c->name);
91 /* return string where '/' is replaced by '.' */
93 for (i = 0; i < s->value->header.size; i++) {
94 if (s->value->data[i] == '/')
95 s->value->data[i] = '.';
103 * Class: java/lang/Class
105 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
107 #if defined(ENABLE_JAVASE)
108 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
109 #elif defined(ENABLE_JAVAME_CLDC1_1)
110 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
113 #if defined(ENABLE_JAVASE)
114 java_objectheader *cl;
119 java_objectheader *xptr;
124 #if defined(ENABLE_JAVASE)
125 cl = (java_objectheader *) loader;
128 /* illegal argument */
131 exceptions_throw_nullpointerexception();
135 /* create utf string in which '.' is replaced by '/' */
137 ufile = javastring_toutf(name, true);
138 uname = javastring_toutf(name, false);
140 /* name must not contain '/' (mauve test) */
142 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
144 exceptions_throw_classnotfoundexception(uname);
149 /* try to load, ... */
151 #if defined(ENABLE_JAVASE)
152 c = load_class_from_classloader(ufile, cl);
153 #elif defined(ENABLE_JAVAME_CLDC1_1)
154 c = load_class_bootstrap(ufile);
158 xptr = exceptions_get_exception();
160 xclass = xptr->vftbl->class;
162 /* if the exception is a NoClassDefFoundError, we replace it with a
163 ClassNotFoundException, otherwise return the exception */
165 if (xclass == class_java_lang_NoClassDefFoundError) {
166 /* clear exceptionptr, because builtin_new checks for
167 ExceptionInInitializerError */
168 exceptions_clear_exception();
170 exceptions_throw_classnotfoundexception(uname);
181 /* ...and initialize it, if required */
183 #if defined(ENABLE_JAVASE)
186 if (!initialize_class(c))
189 return (java_lang_Class *) c;
194 * Class: java/lang/Class
196 * Signature: (Ljava/lang/Object;)Z
198 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
201 java_objectheader *ob;
203 c = (classinfo *) klass;
204 ob = (java_objectheader *) o;
206 if (!(c->state & CLASS_LINKED))
210 return builtin_instanceof(ob, c);
215 * Class: java/lang/Class
216 * Method: isAssignableFrom
217 * Signature: (Ljava/lang/Class;)Z
219 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
224 kc = (classinfo *) klass;
225 cc = (classinfo *) c;
228 exceptions_throw_nullpointerexception();
232 if (!(kc->state & CLASS_LINKED))
236 if (!(cc->state & CLASS_LINKED))
240 /* XXX this may be wrong for array classes */
242 return builtin_isanysubclass(cc, kc);
247 * Class: java/lang/Class
248 * Method: isInterface
251 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
255 c = (classinfo *) klass;
257 if (c->flags & ACC_INTERFACE)
264 #if defined(ENABLE_JAVASE)
267 * Class: java/lang/Class
268 * Method: isPrimitive
271 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
276 c = (classinfo *) klass;
278 /* search table of primitive classes */
280 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
281 if (primitivetype_table[i].class_primitive == c)
289 * Class: java/lang/Class
290 * Method: getSuperclass
291 * Signature: ()Ljava/lang/Class;
293 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
298 c = (classinfo *) klass;
300 /* for java.lang.Object, primitive and Void classes we return NULL */
305 /* for interfaces we also return NULL */
307 if (c->flags & ACC_INTERFACE)
310 /* we may have to resolve the super class reference */
312 if ((sc = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
315 /* store the resolution */
319 return (java_lang_Class *) sc;
324 * Class: java/lang/Class
325 * Method: getInterfaces
326 * Signature: ()[Ljava/lang/Class;
328 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
332 java_objectarray *oa;
335 c = (classinfo *) klass;
337 if (!(c->state & CLASS_LINKED))
341 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
346 for (i = 0; i < c->interfacescount; i++) {
347 ic = c->interfaces[i].cls;
349 oa->data[i] = (java_objectheader *) ic;
357 * Class: java/lang/Class
358 * Method: getComponentType
359 * Signature: ()Ljava/lang/Class;
361 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
365 arraydescriptor *desc;
367 c = (classinfo *) klass;
369 /* XXX maybe we could find a way to do this without linking. */
370 /* This way should be safe and easy, however. */
372 if (!(c->state & CLASS_LINKED))
376 desc = c->vftbl->arraydesc;
381 if (desc->arraytype == ARRAYTYPE_OBJECT)
382 comp = desc->componentvftbl->class;
384 comp = primitivetype_table[desc->arraytype].class_primitive;
386 return (java_lang_Class *) comp;
391 * Class: java/lang/Class
392 * Method: getModifiers
395 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
398 classref_or_classinfo inner;
399 classref_or_classinfo outer;
403 c = (classinfo *) klass;
405 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
406 /* search for passed class as inner class */
408 for (i = 0; i < c->innerclasscount; i++) {
409 inner = c->innerclass[i].inner_class;
410 outer = c->innerclass[i].outer_class;
412 /* Check if inner is a classref or a real class and get
413 the name of the structure */
415 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
417 /* innerclass is this class */
419 if (innername == c->name) {
420 /* has the class actually an outer class? */
423 /* return flags got from the outer class file */
424 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
426 return c->flags & ACC_CLASS_REFLECT_MASK;
431 /* passed class is no inner class or it was not requested */
433 return c->flags & ACC_CLASS_REFLECT_MASK;
438 * Class: java/lang/Class
439 * Method: getDeclaringClass
440 * Signature: ()Ljava/lang/Class;
442 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
445 classref_or_classinfo inner;
450 c = (classinfo *) klass;
452 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
453 if (c->innerclasscount == 0) /* no innerclasses exist */
456 for (i = 0; i < c->innerclasscount; i++) {
457 inner = c->innerclass[i].inner_class;
459 /* check if inner_class is a classref or a real class and
460 get the class name from the structure */
462 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
464 /* innerclass is this class */
466 if (innername == c->name) {
467 /* maybe the outer class is not loaded yet */
469 if ((outer = resolve_classref_or_classinfo_eager(
470 c->innerclass[i].outer_class,
474 if (!(outer->state & CLASS_LINKED))
475 if (!link_class(outer))
478 return (java_lang_Class *) outer;
483 /* return NULL for arrayclasses and primitive classes */
490 * Class: java/lang/Class
491 * Method: getDeclaredClasses
492 * Signature: (Z)[Ljava/lang/Class;
494 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
497 classref_or_classinfo outer;
499 s4 declaredclasscount; /* number of declared classes */
500 s4 pos; /* current declared class */
501 java_objectarray *oa; /* array of declared classes */
504 c = (classinfo *) klass;
505 declaredclasscount = 0;
507 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
508 /* determine number of declared classes */
510 for (i = 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)))
522 declaredclasscount++;
526 /* allocate Class[] and check for OOM */
528 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
533 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
534 outer = c->innerclass[i].outer_class;
536 /* check if outer_class is a classref or a real class and
537 get the class name from the structure */
539 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
541 /* outer class is this class */
543 if ((outername == c->name) &&
544 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
547 if ((inner = resolve_classref_or_classinfo_eager(
548 c->innerclass[i].inner_class,
552 if (!(inner->state & CLASS_LINKED))
553 if (!link_class(inner))
556 oa->data[pos++] = (java_objectheader *) inner;
565 * Class: java/lang/Class
566 * Method: getDeclaredFields
567 * Signature: (Z)[Ljava/lang/reflect/Field;
569 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
572 java_objectarray *oa; /* result: array of field-objects */
574 java_objectheader *o;
575 java_lang_reflect_Field *rf;
576 s4 public_fields; /* number of elements in field-array */
580 c = (classinfo *) klass;
582 /* determine number of fields */
584 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
585 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
588 /* create array of fields */
590 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
595 /* get the fields and store in the array */
597 for (i = 0, pos = 0; i < c->fieldscount; i++) {
600 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
601 /* create Field object */
603 o = native_new_and_init(class_java_lang_reflect_Field);
608 /* initialize instance fields */
610 rf = (java_lang_reflect_Field *) o;
612 rf->declaringClass = (java_lang_Class *) c;
613 rf->name = javastring_new(f->name);
616 /* store object into array */
627 * Class: java/lang/Class
628 * Method: getDeclaredMethods
629 * Signature: (Z)[Ljava/lang/reflect/Method;
631 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
634 java_objectheader *o;
635 java_lang_reflect_Method *rm;
636 java_objectarray *oa; /* result: array of Method-objects */
637 methodinfo *m; /* the current method to be represented */
638 s4 public_methods; /* number of public methods of the class */
642 c = (classinfo *) klass;
645 /* JOWENN: array classes do not declare methods according to mauve
646 test. It should be considered, if we should return to my old
647 clone method overriding instead of declaring it as a member
650 if (_Jv_java_lang_Class_isArray(klass))
651 return builtin_anewarray(0, class_java_lang_reflect_Method);
653 /* determine number of methods */
655 for (i = 0; i < c->methodscount; i++) {
658 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
659 ((m->name != utf_init) && (m->name != utf_clinit)) &&
660 !(m->flags & ACC_MIRANDA))
664 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
669 for (i = 0, pos = 0; i < c->methodscount; i++) {
672 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
673 ((m->name != utf_init) && (m->name != utf_clinit)) &&
674 !(m->flags & ACC_MIRANDA)) {
676 o = native_new_and_init(class_java_lang_reflect_Method);
681 /* initialize instance fields */
683 rm = (java_lang_reflect_Method *) o;
685 rm->declaringClass = (java_lang_Class *) m->class;
686 rm->name = javastring_new(m->name);
689 /* store object into array */
700 * Class: java/lang/Class
701 * Method: getDeclaredConstructors
702 * Signature: (Z)[Ljava/lang/reflect/Constructor;
704 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
707 methodinfo *m; /* the current method to be represented */
708 java_objectarray *oa; /* result: array of Method-objects */
709 java_objectheader *o;
710 java_lang_reflect_Constructor *rc;
711 s4 public_methods; /* number of public methods of the class */
715 c = (classinfo *) klass;
717 /* determine number of constructors */
719 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
722 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
723 (m->name == utf_init))
727 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
732 for (i = 0, pos = 0; i < c->methodscount; i++) {
735 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
736 (m->name == utf_init)) {
738 o = native_new_and_init(class_java_lang_reflect_Constructor);
743 /* initialize instance fields */
745 rc = (java_lang_reflect_Constructor *) o;
747 rc->clazz = (java_lang_Class *) c;
750 /* store object into array */
761 * Class: java/lang/Class
762 * Method: getClassLoader
763 * Signature: ()Ljava/lang/ClassLoader;
765 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
769 c = (classinfo *) klass;
771 return (java_lang_ClassLoader *) c->classloader;
774 #endif /* defined(ENABLE_JAVASE) */
778 * Class: java/lang/Class
782 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
786 c = (classinfo *) klass;
788 if (!(c->state & CLASS_LINKED))
792 return (c->vftbl->arraydesc != NULL);
796 #if defined(ENABLE_JAVASE)
799 * Class: java/lang/Class
800 * Method: throwException
801 * Signature: (Ljava/lang/Throwable;)V
803 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
805 java_objectheader *o;
807 o = (java_objectheader *) t;
809 exceptions_set_exception(o);
815 * Class: java/lang/Class
816 * Method: getDeclaredAnnotations
817 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
819 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
826 * Class: java/lang/Class
827 * Method: getEnclosingClass
828 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
830 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
833 classref_or_classinfo cr;
836 c = (classinfo *) klass;
838 /* get enclosing class */
840 cr = c->enclosingclass;
845 /* resolve the class if necessary */
847 if (IS_CLASSREF(cr)) {
848 ec = resolve_classref_eager(cr.ref);
856 return (java_lang_Class *) ec;
860 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
862 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
863 _Jv_java_lang_Class_getEnclosingMethod.
865 *******************************************************************************/
867 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
869 classref_or_classinfo cr;
870 constant_nameandtype *cn;
874 /* get enclosing class and method */
876 cr = c->enclosingclass;
877 cn = c->enclosingmethod;
879 /* check for enclosing class and method */
887 /* resolve the class if necessary */
889 if (IS_CLASSREF(cr)) {
890 ec = resolve_classref_eager(cr.ref);
898 /* find method in enclosing class */
900 m = class_findmethod(ec, cn->name, cn->descriptor);
903 exceptions_throw_internalerror("Enclosing method doesn't exist");
912 * Class: java/lang/Class
913 * Method: getEnclosingConstructor
914 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
916 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
920 java_objectheader *o;
921 java_lang_reflect_Constructor *rc;
923 c = (classinfo *) klass;
925 /* get enclosing method */
927 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
932 /* check for <init> */
934 if (m->name != utf_init)
937 /* create java.lang.reflect.Constructor object */
939 o = native_new_and_init(class_java_lang_reflect_Constructor);
944 /* initialize instance fields */
946 rc = (java_lang_reflect_Constructor *) o;
948 rc->clazz = (java_lang_Class *) m->class;
949 rc->slot = m - m->class->methods; /* calculate method slot */
956 * Class: java/lang/Class
957 * Method: getEnclosingMethod
958 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
960 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
964 java_objectheader *o;
965 java_lang_reflect_Method *rm;
967 c = (classinfo *) klass;
969 /* get enclosing method */
971 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
976 /* check for <init> */
978 if (m->name == utf_init)
981 /* create java.lang.reflect.Method object */
983 o = native_new_and_init(class_java_lang_reflect_Method);
988 /* initialize instance fields */
990 rm = (java_lang_reflect_Method *) o;
992 rm->declaringClass = (java_lang_Class *) m->class;
993 rm->name = javastring_new(m->name);
994 rm->slot = m - m->class->methods; /* calculate method slot */
1001 * Class: java/lang/Class
1002 * Method: getClassSignature
1003 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
1005 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
1008 java_lang_String *s;
1010 c = (classinfo *) klass;
1012 if (c->signature == NULL)
1015 s = javastring_new(c->signature);
1017 /* in error case, s == NULL */
1025 * Class: java/lang/Class
1026 * Method: isAnonymousClass
1027 * Signature: (Ljava/lang/Class;)Z
1029 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1033 * Class: java/lang/VMClass
1034 * Method: isLocalClass
1035 * Signature: (Ljava/lang/Class;)Z
1037 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1041 * Class: java/lang/VMClass
1042 * Method: isMemberClass
1043 * Signature: (Ljava/lang/Class;)Z
1045 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1048 #endif /* ENABLE_JAVASE */
1052 * These are local overrides for various environment variables in Emacs.
1053 * Please do not remove this and leave it at the end of the file, where
1054 * Emacs will automagically detect them.
1055 * ---------------------------------------------------------------------
1058 * indent-tabs-mode: t
1062 * vim:noexpandtab:sw=4:ts=4: