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 "vm/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)
119 java_objectheader *xptr;
124 #if defined(ENABLE_JAVASE)
125 cl = loader_hashtable_classloader_add((java_objectheader *) loader);
128 /* illegal argument */
131 exceptions_throw_nullpointerexception();
135 /* create utf string in which '.' is replaced by '/' */
137 ufile = javastring_toutf((java_objectheader *) name, true);
138 uname = javastring_toutf((java_objectheader *) 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 return class_isanysubclass(cc, kc);
245 * Class: java/lang/Class
246 * Method: isInterface
249 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
253 c = (classinfo *) klass;
255 if (c->flags & ACC_INTERFACE)
262 #if defined(ENABLE_JAVASE)
265 * Class: java/lang/Class
266 * Method: isPrimitive
269 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
274 c = (classinfo *) klass;
276 /* search table of primitive classes */
278 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
279 if (primitivetype_table[i].class_primitive == c)
287 * Class: java/lang/Class
288 * Method: getSuperclass
289 * Signature: ()Ljava/lang/Class;
291 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
296 c = (classinfo *) klass;
298 /* for java.lang.Object, primitive and Void classes we return NULL */
303 /* for interfaces we also return NULL */
305 if (c->flags & ACC_INTERFACE)
308 /* we may have to resolve the super class reference */
310 if ((sc = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
313 /* store the resolution */
317 return (java_lang_Class *) sc;
322 * Class: java/lang/Class
323 * Method: getInterfaces
324 * Signature: ()[Ljava/lang/Class;
326 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
330 java_objectarray *oa;
333 c = (classinfo *) klass;
335 if (!(c->state & CLASS_LINKED))
339 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
344 for (i = 0; i < c->interfacescount; i++) {
345 ic = c->interfaces[i].cls;
347 oa->data[i] = (java_objectheader *) ic;
355 * Class: java/lang/Class
356 * Method: getComponentType
357 * Signature: ()Ljava/lang/Class;
359 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
363 arraydescriptor *desc;
365 c = (classinfo *) klass;
367 /* XXX maybe we could find a way to do this without linking. */
368 /* This way should be safe and easy, however. */
370 if (!(c->state & CLASS_LINKED))
374 desc = c->vftbl->arraydesc;
379 if (desc->arraytype == ARRAYTYPE_OBJECT)
380 comp = desc->componentvftbl->class;
382 comp = primitivetype_table[desc->arraytype].class_primitive;
384 return (java_lang_Class *) comp;
389 * Class: java/lang/Class
390 * Method: getModifiers
393 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
396 classref_or_classinfo inner;
397 classref_or_classinfo outer;
401 c = (classinfo *) klass;
403 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
404 /* search for passed class as inner class */
406 for (i = 0; i < c->innerclasscount; i++) {
407 inner = c->innerclass[i].inner_class;
408 outer = c->innerclass[i].outer_class;
410 /* Check if inner is a classref or a real class and get
411 the name of the structure */
413 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
415 /* innerclass is this class */
417 if (innername == c->name) {
418 /* has the class actually an outer class? */
421 /* return flags got from the outer class file */
422 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
424 return c->flags & ACC_CLASS_REFLECT_MASK;
429 /* passed class is no inner class or it was not requested */
431 return c->flags & ACC_CLASS_REFLECT_MASK;
436 * Class: java/lang/Class
437 * Method: getDeclaringClass
438 * Signature: ()Ljava/lang/Class;
440 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
443 classref_or_classinfo inner;
448 c = (classinfo *) klass;
450 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
451 if (c->innerclasscount == 0) /* no innerclasses exist */
454 for (i = 0; i < c->innerclasscount; i++) {
455 inner = c->innerclass[i].inner_class;
457 /* check if inner_class is a classref or a real class and
458 get the class name from the structure */
460 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
462 /* innerclass is this class */
464 if (innername == c->name) {
465 /* maybe the outer class is not loaded yet */
467 if ((outer = resolve_classref_or_classinfo_eager(
468 c->innerclass[i].outer_class,
472 if (!(outer->state & CLASS_LINKED))
473 if (!link_class(outer))
476 return (java_lang_Class *) outer;
481 /* return NULL for arrayclasses and primitive classes */
488 * Class: java/lang/Class
489 * Method: getDeclaredClasses
490 * Signature: (Z)[Ljava/lang/Class;
492 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
495 classref_or_classinfo outer;
497 s4 declaredclasscount; /* number of declared classes */
498 s4 pos; /* current declared class */
499 java_objectarray *oa; /* array of declared classes */
502 c = (classinfo *) klass;
503 declaredclasscount = 0;
505 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
506 /* determine number of declared classes */
508 for (i = 0; i < c->innerclasscount; i++) {
509 outer = c->innerclass[i].outer_class;
511 /* check if outer_class is a classref or a real class and
512 get the class name from the structure */
514 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
516 /* outer class is this class */
518 if ((outername == c->name) &&
519 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
520 declaredclasscount++;
524 /* allocate Class[] and check for OOM */
526 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
531 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
532 outer = c->innerclass[i].outer_class;
534 /* check if outer_class is a classref or a real class and
535 get the class name from the structure */
537 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
539 /* outer class is this class */
541 if ((outername == c->name) &&
542 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
545 if ((inner = resolve_classref_or_classinfo_eager(
546 c->innerclass[i].inner_class,
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 = (java_lang_String *) 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 = (java_lang_String *) 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->object;
772 #endif /* defined(ENABLE_JAVASE) */
776 * Class: java/lang/Class
780 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
784 c = (classinfo *) klass;
786 if (!(c->state & CLASS_LINKED))
790 return (c->vftbl->arraydesc != NULL);
794 #if defined(ENABLE_JAVASE)
797 * Class: java/lang/Class
798 * Method: throwException
799 * Signature: (Ljava/lang/Throwable;)V
801 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
803 java_objectheader *o;
805 o = (java_objectheader *) t;
807 exceptions_set_exception(o);
813 * Class: java/lang/Class
814 * Method: getDeclaredAnnotations
815 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
817 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
824 * Class: java/lang/Class
825 * Method: getEnclosingClass
826 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
828 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
831 classref_or_classinfo cr;
834 c = (classinfo *) klass;
836 /* get enclosing class */
838 cr = c->enclosingclass;
843 /* resolve the class if necessary */
845 if (IS_CLASSREF(cr)) {
846 ec = resolve_classref_eager(cr.ref);
854 return (java_lang_Class *) ec;
858 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
860 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
861 _Jv_java_lang_Class_getEnclosingMethod.
863 *******************************************************************************/
865 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
867 classref_or_classinfo cr;
868 constant_nameandtype *cn;
872 /* get enclosing class and method */
874 cr = c->enclosingclass;
875 cn = c->enclosingmethod;
877 /* check for enclosing class and method */
885 /* resolve the class if necessary */
887 if (IS_CLASSREF(cr)) {
888 ec = resolve_classref_eager(cr.ref);
896 /* find method in enclosing class */
898 m = class_findmethod(ec, cn->name, cn->descriptor);
901 exceptions_throw_internalerror("Enclosing method doesn't exist");
910 * Class: java/lang/Class
911 * Method: getEnclosingConstructor
912 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
914 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
918 java_objectheader *o;
919 java_lang_reflect_Constructor *rc;
921 c = (classinfo *) klass;
923 /* get enclosing method */
925 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
930 /* check for <init> */
932 if (m->name != utf_init)
935 /* create java.lang.reflect.Constructor object */
937 o = native_new_and_init(class_java_lang_reflect_Constructor);
942 /* initialize instance fields */
944 rc = (java_lang_reflect_Constructor *) o;
946 rc->clazz = (java_lang_Class *) m->class;
947 rc->slot = m - m->class->methods; /* calculate method slot */
954 * Class: java/lang/Class
955 * Method: getEnclosingMethod
956 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
958 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
962 java_objectheader *o;
963 java_lang_reflect_Method *rm;
965 c = (classinfo *) klass;
967 /* get enclosing method */
969 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
974 /* check for <init> */
976 if (m->name == utf_init)
979 /* create java.lang.reflect.Method object */
981 o = native_new_and_init(class_java_lang_reflect_Method);
986 /* initialize instance fields */
988 rm = (java_lang_reflect_Method *) o;
990 rm->declaringClass = (java_lang_Class *) m->class;
991 rm->name = (java_lang_String *) javastring_new(m->name);
992 rm->slot = m - m->class->methods; /* calculate method slot */
999 * Class: java/lang/Class
1000 * Method: getClassSignature
1001 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
1003 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
1006 java_objectheader *o;
1008 c = (classinfo *) klass;
1010 if (c->signature == NULL)
1013 o = javastring_new(c->signature);
1015 /* in error case o is NULL */
1017 return (java_lang_String *) o;
1023 * Class: java/lang/Class
1024 * Method: isAnonymousClass
1025 * Signature: (Ljava/lang/Class;)Z
1027 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1031 * Class: java/lang/VMClass
1032 * Method: isLocalClass
1033 * Signature: (Ljava/lang/Class;)Z
1035 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1039 * Class: java/lang/VMClass
1040 * Method: isMemberClass
1041 * Signature: (Ljava/lang/Class;)Z
1043 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1046 #endif /* ENABLE_JAVASE */
1050 * These are local overrides for various environment variables in Emacs.
1051 * Please do not remove this and leave it at the end of the file, where
1052 * Emacs will automagically detect them.
1053 * ---------------------------------------------------------------------
1056 * indent-tabs-mode: t
1060 * vim:noexpandtab:sw=4:ts=4: