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;
193 #if defined(ENABLE_JAVASE)
196 * Class: java/lang/Class
198 * Signature: (Ljava/lang/Object;)Z
200 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
203 java_objectheader *ob;
205 c = (classinfo *) klass;
206 ob = (java_objectheader *) o;
208 if (!(c->state & CLASS_LINKED))
212 return builtin_instanceof(ob, c);
217 * Class: java/lang/Class
218 * Method: isAssignableFrom
219 * Signature: (Ljava/lang/Class;)Z
221 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
226 kc = (classinfo *) klass;
227 cc = (classinfo *) c;
230 exceptions_throw_nullpointerexception();
234 if (!(kc->state & CLASS_LINKED))
238 if (!(cc->state & CLASS_LINKED))
242 /* XXX this may be wrong for array classes */
244 return builtin_isanysubclass(cc, kc);
249 * Class: java/lang/Class
250 * Method: isInterface
253 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
257 c = (classinfo *) klass;
259 if (c->flags & ACC_INTERFACE)
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 (!resolve_classref_or_classinfo(NULL, c->super, resolveEager,
313 true, /* check access */
314 false, /* don't link */
320 /* store the resolution */
324 return (java_lang_Class *) sc;
329 * Class: java/lang/Class
330 * Method: getInterfaces
331 * Signature: ()[Ljava/lang/Class;
333 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
337 java_objectarray *oa;
340 c = (classinfo *) klass;
342 if (!(c->state & CLASS_LINKED))
346 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
351 for (i = 0; i < c->interfacescount; i++) {
352 ic = c->interfaces[i].cls;
354 oa->data[i] = (java_objectheader *) ic;
362 * Class: java/lang/Class
363 * Method: getComponentType
364 * Signature: ()Ljava/lang/Class;
366 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
370 arraydescriptor *desc;
372 c = (classinfo *) klass;
374 /* XXX maybe we could find a way to do this without linking. */
375 /* This way should be safe and easy, however. */
377 if (!(c->state & CLASS_LINKED))
381 desc = c->vftbl->arraydesc;
386 if (desc->arraytype == ARRAYTYPE_OBJECT)
387 comp = desc->componentvftbl->class;
389 comp = primitivetype_table[desc->arraytype].class_primitive;
391 return (java_lang_Class *) comp;
396 * Class: java/lang/Class
397 * Method: getModifiers
400 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
403 classref_or_classinfo inner;
404 classref_or_classinfo outer;
408 c = (classinfo *) klass;
410 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
411 /* search for passed class as inner class */
413 for (i = 0; i < c->innerclasscount; i++) {
414 inner = c->innerclass[i].inner_class;
415 outer = c->innerclass[i].outer_class;
417 /* Check if inner is a classref or a real class and get
418 the name of the structure */
420 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
422 /* innerclass is this class */
424 if (innername == c->name) {
425 /* has the class actually an outer class? */
428 /* return flags got from the outer class file */
429 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
431 return c->flags & ACC_CLASS_REFLECT_MASK;
436 /* passed class is no inner class or it was not requested */
438 return c->flags & ACC_CLASS_REFLECT_MASK;
443 * Class: java/lang/Class
444 * Method: getDeclaringClass
445 * Signature: ()Ljava/lang/Class;
447 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
450 classref_or_classinfo inner;
455 c = (classinfo *) klass;
457 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
458 if (c->innerclasscount == 0) /* no innerclasses exist */
461 for (i = 0; i < c->innerclasscount; i++) {
462 inner = c->innerclass[i].inner_class;
464 /* check if inner_class is a classref or a real class and
465 get the class name from the structure */
467 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
469 /* innerclass is this class */
471 if (innername == c->name) {
472 /* maybe the outer class is not loaded yet */
474 if (!resolve_classref_or_classinfo(NULL,
475 c->innerclass[i].outer_class,
476 resolveEager, false, false,
480 if (!(outer->state & CLASS_LINKED))
481 if (!link_class(outer))
484 return (java_lang_Class *) outer;
489 /* return NULL for arrayclasses and primitive classes */
496 * Class: java/lang/Class
497 * Method: getDeclaredClasses
498 * Signature: (Z)[Ljava/lang/Class;
500 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
503 classref_or_classinfo outer;
505 s4 declaredclasscount; /* number of declared classes */
506 s4 pos; /* current declared class */
507 java_objectarray *oa; /* array of declared classes */
510 c = (classinfo *) klass;
511 declaredclasscount = 0;
513 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
514 /* determine number of declared classes */
516 for (i = 0; i < c->innerclasscount; i++) {
517 outer = c->innerclass[i].outer_class;
519 /* check if outer_class is a classref or a real class and
520 get the class name from the structure */
522 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
524 /* outer class is this class */
526 if ((outername == c->name) &&
527 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
528 declaredclasscount++;
532 /* allocate Class[] and check for OOM */
534 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
539 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
540 outer = c->innerclass[i].outer_class;
542 /* check if outer_class is a classref or a real class and
543 get the class name from the structure */
545 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
547 /* outer class is this class */
549 if ((outername == c->name) &&
550 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
553 if (!resolve_classref_or_classinfo(NULL,
554 c->innerclass[i].inner_class,
555 resolveEager, false, false,
559 if (!(inner->state & CLASS_LINKED))
560 if (!link_class(inner))
563 oa->data[pos++] = (java_objectheader *) inner;
572 * Class: java/lang/Class
573 * Method: getDeclaredFields
574 * Signature: (Z)[Ljava/lang/reflect/Field;
576 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
579 java_objectarray *oa; /* result: array of field-objects */
581 java_objectheader *o;
582 java_lang_reflect_Field *rf;
583 s4 public_fields; /* number of elements in field-array */
587 c = (classinfo *) klass;
589 /* determine number of fields */
591 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
592 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
595 /* create array of fields */
597 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
602 /* get the fields and store in the array */
604 for (i = 0, pos = 0; i < c->fieldscount; i++) {
607 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
608 /* create Field object */
610 o = native_new_and_init(class_java_lang_reflect_Field);
615 /* initialize instance fields */
617 rf = (java_lang_reflect_Field *) o;
619 rf->declaringClass = (java_lang_Class *) c;
620 rf->name = javastring_new(f->name);
623 /* store object into array */
634 * Class: java/lang/Class
635 * Method: getDeclaredMethods
636 * Signature: (Z)[Ljava/lang/reflect/Method;
638 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
641 java_objectheader *o;
642 java_lang_reflect_Method *rm;
643 java_objectarray *oa; /* result: array of Method-objects */
644 methodinfo *m; /* the current method to be represented */
645 s4 public_methods; /* number of public methods of the class */
649 c = (classinfo *) klass;
652 /* JOWENN: array classes do not declare methods according to mauve
653 test. It should be considered, if we should return to my old
654 clone method overriding instead of declaring it as a member
657 if (_Jv_java_lang_Class_isArray(klass))
658 return builtin_anewarray(0, class_java_lang_reflect_Method);
660 /* determine number of methods */
662 for (i = 0; i < c->methodscount; i++) {
665 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
666 ((m->name != utf_init) && (m->name != utf_clinit)) &&
667 !(m->flags & ACC_MIRANDA))
671 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
676 for (i = 0, pos = 0; i < c->methodscount; i++) {
679 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
680 ((m->name != utf_init) && (m->name != utf_clinit)) &&
681 !(m->flags & ACC_MIRANDA)) {
683 o = native_new_and_init(class_java_lang_reflect_Method);
688 /* initialize instance fields */
690 rm = (java_lang_reflect_Method *) o;
692 rm->declaringClass = (java_lang_Class *) m->class;
693 rm->name = javastring_new(m->name);
696 /* store object into array */
707 * Class: java/lang/Class
708 * Method: getDeclaredConstructors
709 * Signature: (Z)[Ljava/lang/reflect/Constructor;
711 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
714 methodinfo *m; /* the current method to be represented */
715 java_objectarray *oa; /* result: array of Method-objects */
716 java_objectheader *o;
717 java_lang_reflect_Constructor *rc;
718 s4 public_methods; /* number of public methods of the class */
722 c = (classinfo *) klass;
724 /* determine number of constructors */
726 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
729 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
730 (m->name == utf_init))
734 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
739 for (i = 0, pos = 0; i < c->methodscount; i++) {
742 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
743 (m->name == utf_init)) {
745 o = native_new_and_init(class_java_lang_reflect_Constructor);
750 /* initialize instance fields */
752 rc = (java_lang_reflect_Constructor *) o;
754 rc->clazz = (java_lang_Class *) c;
757 /* store object into array */
768 * Class: java/lang/Class
769 * Method: getClassLoader
770 * Signature: ()Ljava/lang/ClassLoader;
772 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
776 c = (classinfo *) klass;
778 return (java_lang_ClassLoader *) c->classloader;
783 * Class: java/lang/Class
787 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
791 c = (classinfo *) klass;
793 if (!(c->state & CLASS_LINKED))
797 return (c->vftbl->arraydesc != NULL);
802 * Class: java/lang/Class
803 * Method: throwException
804 * Signature: (Ljava/lang/Throwable;)V
806 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
808 java_objectheader *o;
810 o = (java_objectheader *) t;
812 exceptions_set_exception(o);
818 * Class: java/lang/Class
819 * Method: getDeclaredAnnotations
820 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
822 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
829 * Class: java/lang/Class
830 * Method: getEnclosingClass
831 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
833 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
836 classref_or_classinfo cr;
839 c = (classinfo *) klass;
841 /* get enclosing class */
843 cr = c->enclosingclass;
848 /* resolve the class if necessary */
850 if (IS_CLASSREF(cr)) {
851 ec = resolve_classref_eager(cr.ref);
859 return (java_lang_Class *) ec;
863 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
865 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
866 _Jv_java_lang_Class_getEnclosingMethod.
868 *******************************************************************************/
870 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
872 classref_or_classinfo cr;
873 constant_nameandtype *cn;
877 /* get enclosing class and method */
879 cr = c->enclosingclass;
880 cn = c->enclosingmethod;
882 /* check for enclosing class and method */
890 /* resolve the class if necessary */
892 if (IS_CLASSREF(cr)) {
893 ec = resolve_classref_eager(cr.ref);
901 /* find method in enclosing class */
903 m = class_findmethod(ec, cn->name, cn->descriptor);
906 exceptions_throw_internalerror("Enclosing method doesn't exist");
915 * Class: java/lang/Class
916 * Method: getEnclosingConstructor
917 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
919 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
923 java_objectheader *o;
924 java_lang_reflect_Constructor *rc;
926 c = (classinfo *) klass;
928 /* get enclosing method */
930 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
935 /* check for <init> */
937 if (m->name != utf_init)
940 /* create java.lang.reflect.Constructor object */
942 o = native_new_and_init(class_java_lang_reflect_Constructor);
947 /* initialize instance fields */
949 rc = (java_lang_reflect_Constructor *) o;
951 rc->clazz = (java_lang_Class *) m->class;
952 rc->slot = m - m->class->methods; /* calculate method slot */
959 * Class: java/lang/Class
960 * Method: getEnclosingMethod
961 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
963 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
967 java_objectheader *o;
968 java_lang_reflect_Method *rm;
970 c = (classinfo *) klass;
972 /* get enclosing method */
974 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
979 /* check for <init> */
981 if (m->name == utf_init)
984 /* create java.lang.reflect.Method object */
986 o = native_new_and_init(class_java_lang_reflect_Method);
991 /* initialize instance fields */
993 rm = (java_lang_reflect_Method *) o;
995 rm->declaringClass = (java_lang_Class *) m->class;
996 rm->name = javastring_new(m->name);
997 rm->slot = m - m->class->methods; /* calculate method slot */
1004 * Class: java/lang/Class
1005 * Method: getClassSignature
1006 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
1008 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
1011 java_lang_String *s;
1013 c = (classinfo *) klass;
1015 if (c->signature == NULL)
1018 s = javastring_new(c->signature);
1020 /* in error case, s == NULL */
1028 * Class: java/lang/Class
1029 * Method: isAnonymousClass
1030 * Signature: (Ljava/lang/Class;)Z
1032 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1036 * Class: java/lang/VMClass
1037 * Method: isLocalClass
1038 * Signature: (Ljava/lang/Class;)Z
1040 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1044 * Class: java/lang/VMClass
1045 * Method: isMemberClass
1046 * Signature: (Ljava/lang/Class;)Z
1048 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1051 #endif /* ENABLE_JAVASE */
1055 * These are local overrides for various environment variables in Emacs.
1056 * Please do not remove this and leave it at the end of the file, where
1057 * Emacs will automagically detect them.
1058 * ---------------------------------------------------------------------
1061 * indent-tabs-mode: t
1065 * vim:noexpandtab:sw=4:ts=4: