1 /* src/native/vm/java_lang_Class.c - java/lang/Class
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Roman Obermaiser
32 $Id: java_lang_VMClass.c 6131 2006-12-06 22:15:57Z twisti $
44 #include "mm/memory.h"
45 #include "native/jni.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_Class.h"
48 #include "native/include/java_lang_ClassLoader.h"
49 #include "native/include/java_lang_Object.h"
50 #include "native/include/java_lang_VMClass.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"
54 #include "native/include/java_security_ProtectionDomain.h"
55 #include "native/vm/java_lang_Class.h"
56 #include "toolbox/logging.h"
57 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/global.h"
61 #include "vm/initialize.h"
62 #include "vm/loader.h"
63 #include "vm/resolve.h"
64 #include "vm/stringlocal.h"
68 * Class: java/lang/Class
70 * Signature: (Ljava/lang/Object;)Z
72 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
75 java_objectheader *ob;
77 c = (classinfo *) klass;
78 ob = (java_objectheader *) o;
80 if (!(c->state & CLASS_LINKED))
84 return builtin_instanceof(ob, c);
89 * Class: java/lang/Class
90 * Method: isAssignableFrom
91 * Signature: (Ljava/lang/Class;)Z
93 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
98 kc = (classinfo *) klass;
102 exceptions_throw_nullpointerexception();
106 if (!(kc->state & CLASS_LINKED))
110 if (!(cc->state & CLASS_LINKED))
114 /* XXX this may be wrong for array classes */
116 return builtin_isanysubclass(cc, kc);
121 * Class: java/lang/Class
122 * Method: isInterface
125 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
129 c = (classinfo *) klass;
131 if (c->flags & ACC_INTERFACE)
139 * Class: java/lang/Class
140 * Method: isPrimitive
143 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
148 c = (classinfo *) klass;
150 /* search table of primitive classes */
152 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
153 if (primitivetype_table[i].class_primitive == c)
161 * Class: java/lang/Class
163 * Signature: ()Ljava/lang/String;
165 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
171 c = (classinfo *) klass;
173 /* create a java string */
175 s = (java_lang_String *) javastring_new(c->name);
180 /* return string where '/' is replaced by '.' */
182 for (i = 0; i < s->value->header.size; i++) {
183 if (s->value->data[i] == '/')
184 s->value->data[i] = '.';
192 * Class: java/lang/Class
193 * Method: getSuperclass
194 * Signature: ()Ljava/lang/Class;
196 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
201 c = (classinfo *) klass;
203 /* for java.lang.Object, primitive and Void classes we return NULL */
208 /* for interfaces we also return NULL */
210 if (c->flags & ACC_INTERFACE)
213 /* we may have to resolve the super class reference */
215 if (!resolve_classref_or_classinfo(NULL, c->super, resolveEager,
216 true, /* check access */
217 false, /* don't link */
223 /* store the resolution */
227 return (java_lang_Class *) sc;
232 * Class: java/lang/Class
233 * Method: getInterfaces
234 * Signature: ()[Ljava/lang/Class;
236 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
240 java_objectarray *oa;
243 c = (classinfo *) klass;
245 if (!(c->state & CLASS_LINKED))
249 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
254 for (i = 0; i < c->interfacescount; i++) {
255 ic = c->interfaces[i].cls;
257 oa->data[i] = (java_objectheader *) ic;
265 * Class: java/lang/Class
266 * Method: getComponentType
267 * Signature: ()Ljava/lang/Class;
269 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
273 arraydescriptor *desc;
275 c = (classinfo *) klass;
277 /* XXX maybe we could find a way to do this without linking. */
278 /* This way should be safe and easy, however. */
280 if (!(c->state & CLASS_LINKED))
284 desc = c->vftbl->arraydesc;
289 if (desc->arraytype == ARRAYTYPE_OBJECT)
290 comp = desc->componentvftbl->class;
292 comp = primitivetype_table[desc->arraytype].class_primitive;
294 return (java_lang_Class *) comp;
299 * Class: java/lang/Class
300 * Method: getModifiers
303 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
306 classref_or_classinfo inner;
307 classref_or_classinfo outer;
311 c = (classinfo *) klass;
313 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
314 /* search for passed class as inner class */
316 for (i = 0; i < c->innerclasscount; i++) {
317 inner = c->innerclass[i].inner_class;
318 outer = c->innerclass[i].outer_class;
320 /* Check if inner is a classref or a real class and get
321 the name of the structure */
323 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
325 /* innerclass is this class */
327 if (innername == c->name) {
328 /* has the class actually an outer class? */
331 /* return flags got from the outer class file */
332 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
334 return c->flags & ACC_CLASS_REFLECT_MASK;
339 /* passed class is no inner class or it was not requested */
341 return c->flags & ACC_CLASS_REFLECT_MASK;
346 * Class: java/lang/Class
347 * Method: getDeclaringClass
348 * Signature: ()Ljava/lang/Class;
350 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
353 classref_or_classinfo inner;
358 c = (classinfo *) klass;
360 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
361 if (c->innerclasscount == 0) /* no innerclasses exist */
364 for (i = 0; i < c->innerclasscount; i++) {
365 inner = c->innerclass[i].inner_class;
367 /* check if inner_class is a classref or a real class and
368 get the class name from the structure */
370 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
372 /* innerclass is this class */
374 if (innername == c->name) {
375 /* maybe the outer class is not loaded yet */
377 if (!resolve_classref_or_classinfo(NULL,
378 c->innerclass[i].outer_class,
379 resolveEager, false, false,
383 if (!(outer->state & CLASS_LINKED))
384 if (!link_class(outer))
387 return (java_lang_Class *) outer;
392 /* return NULL for arrayclasses and primitive classes */
399 * Class: java/lang/Class
400 * Method: getDeclaredClasses
401 * Signature: (Z)[Ljava/lang/Class;
403 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
406 classref_or_classinfo outer;
408 s4 declaredclasscount; /* number of declared classes */
409 s4 pos; /* current declared class */
410 java_objectarray *oa; /* array of declared classes */
413 c = (classinfo *) klass;
414 declaredclasscount = 0;
416 if (!_Jv_java_lang_Class_isPrimitive(klass) && (c->name->text[0] != '[')) {
417 /* determine number of declared classes */
419 for (i = 0; i < c->innerclasscount; i++) {
420 outer = c->innerclass[i].outer_class;
422 /* check if outer_class is a classref or a real class and
423 get the class name from the structure */
425 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
427 /* outer class is this class */
429 if ((outername == c->name) &&
430 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
431 declaredclasscount++;
435 /* allocate Class[] and check for OOM */
437 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
442 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
443 outer = c->innerclass[i].outer_class;
445 /* check if outer_class is a classref or a real class and
446 get the class name from the structure */
448 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
450 /* outer class is this class */
452 if ((outername == c->name) &&
453 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
456 if (!resolve_classref_or_classinfo(NULL,
457 c->innerclass[i].inner_class,
458 resolveEager, false, false,
462 if (!(inner->state & CLASS_LINKED))
463 if (!link_class(inner))
466 oa->data[pos++] = (java_objectheader *) inner;
475 * Class: java/lang/Class
476 * Method: getDeclaredFields
477 * Signature: (Z)[Ljava/lang/reflect/Field;
479 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
482 java_objectarray *oa; /* result: array of field-objects */
484 java_objectheader *o;
485 java_lang_reflect_Field *rf;
486 s4 public_fields; /* number of elements in field-array */
490 c = (classinfo *) klass;
492 /* determine number of fields */
494 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
495 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
498 /* create array of fields */
500 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
505 /* get the fields and store in the array */
507 for (i = 0, pos = 0; i < c->fieldscount; i++) {
510 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
511 /* create Field object */
513 o = native_new_and_init(class_java_lang_reflect_Field);
518 /* initialize instance fields */
520 rf = (java_lang_reflect_Field *) o;
522 rf->declaringClass = (java_lang_Class *) c;
523 rf->name = javastring_new(f->name);
526 /* store object into array */
537 * Class: java/lang/Class
538 * Method: getDeclaredMethods
539 * Signature: (Z)[Ljava/lang/reflect/Method;
541 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
544 java_objectheader *o;
545 java_lang_reflect_Method *rm;
546 java_objectarray *oa; /* result: array of Method-objects */
547 methodinfo *m; /* the current method to be represented */
548 s4 public_methods; /* number of public methods of the class */
552 c = (classinfo *) klass;
555 /* JOWENN: array classes do not declare methods according to mauve
556 test. It should be considered, if we should return to my old
557 clone method overriding instead of declaring it as a member
560 if (_Jv_java_lang_Class_isArray(klass))
561 return builtin_anewarray(0, class_java_lang_reflect_Method);
563 /* determine number of methods */
565 for (i = 0; i < c->methodscount; i++) {
568 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
569 ((m->name != utf_init) && (m->name != utf_clinit)) &&
570 !(m->flags & ACC_MIRANDA))
574 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
579 for (i = 0, pos = 0; i < c->methodscount; i++) {
582 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
583 ((m->name != utf_init) && (m->name != utf_clinit)) &&
584 !(m->flags & ACC_MIRANDA)) {
586 o = native_new_and_init(class_java_lang_reflect_Method);
591 /* initialize instance fields */
593 rm = (java_lang_reflect_Method *) o;
595 rm->declaringClass = (java_lang_Class *) m->class;
596 rm->name = javastring_new(m->name);
599 /* store object into array */
610 * Class: java/lang/Class
611 * Method: getDeclaredConstructors
612 * Signature: (Z)[Ljava/lang/reflect/Constructor;
614 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
617 methodinfo *m; /* the current method to be represented */
618 java_objectarray *oa; /* result: array of Method-objects */
619 java_objectheader *o;
620 java_lang_reflect_Constructor *rc;
621 s4 public_methods; /* number of public methods of the class */
625 c = (classinfo *) klass;
627 /* determine number of constructors */
629 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
632 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
633 (m->name == utf_init))
637 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
642 for (i = 0, pos = 0; i < c->methodscount; i++) {
645 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
646 (m->name == utf_init)) {
648 o = native_new_and_init(class_java_lang_reflect_Constructor);
653 /* initialize instance fields */
655 rc = (java_lang_reflect_Constructor *) o;
657 rc->clazz = (java_lang_Class *) c;
660 /* store object into array */
671 * Class: java/lang/Class
672 * Method: getClassLoader
673 * Signature: ()Ljava/lang/ClassLoader;
675 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
679 c = (classinfo *) klass;
681 return (java_lang_ClassLoader *) c->classloader;
686 * Class: java/lang/VMClass
688 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
690 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
697 /* illegal argument */
700 exceptions_throw_nullpointerexception();
704 /* name must not contain '/' (mauve test) */
706 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
709 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
714 /* create utf string in which '.' is replaced by '/' */
716 u = javastring_toutf(name, true);
718 /* try to load, ... */
720 if (!(c = load_class_from_classloader(u, (java_objectheader *) loader))) {
723 xclass = (*exceptionptr)->vftbl->class;
725 /* if the exception is a NoClassDefFoundError, we replace it with a
726 ClassNotFoundException, otherwise return the exception */
728 if (xclass == class_java_lang_NoClassDefFoundError) {
729 /* clear exceptionptr, because builtin_new checks for
730 ExceptionInInitializerError */
731 *exceptionptr = NULL;
734 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
745 /* ...and initialize it, if required */
748 if (!initialize_class(c))
751 return (java_lang_Class *) c;
756 * Class: java/lang/Class
760 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
764 c = (classinfo *) klass;
766 if (!(c->state & CLASS_LINKED))
770 return (c->vftbl->arraydesc != NULL);
775 * Class: java/lang/Class
776 * Method: throwException
777 * Signature: (Ljava/lang/Throwable;)V
779 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
781 *exceptionptr = (java_objectheader *) t;
787 * Class: java/lang/Class
788 * Method: getDeclaredAnnotations
789 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
791 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
798 * Class: java/lang/Class
799 * Method: getEnclosingClass
800 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
802 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
805 classref_or_classinfo cr;
808 c = (classinfo *) klass;
810 /* get enclosing class */
812 cr = c->enclosingclass;
817 /* resolve the class if necessary */
819 if (IS_CLASSREF(cr)) {
820 ec = resolve_classref_eager(cr.ref);
828 return (java_lang_Class *) ec;
832 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
834 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
835 _Jv_java_lang_Class_getEnclosingMethod.
837 *******************************************************************************/
839 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
841 classref_or_classinfo cr;
842 constant_nameandtype *cn;
846 /* get enclosing class and method */
848 cr = c->enclosingclass;
849 cn = c->enclosingmethod;
851 /* check for enclosing class and method */
859 /* resolve the class if necessary */
861 if (IS_CLASSREF(cr)) {
862 ec = resolve_classref_eager(cr.ref);
870 /* find method in enclosing class */
872 m = class_findmethod(ec, cn->name, cn->descriptor);
875 exceptions_throw_internalerror("Enclosing method doesn't exist");
884 * Class: java/lang/Class
885 * Method: getEnclosingConstructor
886 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
888 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
892 java_objectheader *o;
893 java_lang_reflect_Constructor *rc;
895 c = (classinfo *) klass;
897 /* get enclosing method */
899 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
904 /* check for <init> */
906 if (m->name != utf_init)
909 /* create java.lang.reflect.Constructor object */
911 o = native_new_and_init(class_java_lang_reflect_Constructor);
916 /* initialize instance fields */
918 rc = (java_lang_reflect_Constructor *) o;
920 rc->clazz = (java_lang_Class *) m->class;
921 rc->slot = m - m->class->methods; /* calculate method slot */
928 * Class: java/lang/Class
929 * Method: getEnclosingMethod
930 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
932 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
936 java_objectheader *o;
937 java_lang_reflect_Method *rm;
939 c = (classinfo *) klass;
941 /* get enclosing method */
943 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
948 /* check for <init> */
950 if (m->name == utf_init)
953 /* create java.lang.reflect.Method object */
955 o = native_new_and_init(class_java_lang_reflect_Method);
960 /* initialize instance fields */
962 rm = (java_lang_reflect_Method *) o;
964 rm->declaringClass = (java_lang_Class *) m->class;
965 rm->name = javastring_new(m->name);
966 rm->slot = m - m->class->methods; /* calculate method slot */
973 * Class: java/lang/Class
974 * Method: getClassSignature
975 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
977 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
982 c = (classinfo *) klass;
984 if (c->signature == NULL)
987 s = javastring_new(c->signature);
989 /* in error case, s == NULL */
997 * Class: java/lang/Class
998 * Method: isAnonymousClass
999 * Signature: (Ljava/lang/Class;)Z
1001 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1005 * Class: java/lang/VMClass
1006 * Method: isLocalClass
1007 * Signature: (Ljava/lang/Class;)Z
1009 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1013 * Class: java/lang/VMClass
1014 * Method: isMemberClass
1015 * Signature: (Ljava/lang/Class;)Z
1017 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1022 * These are local overrides for various environment variables in Emacs.
1023 * Please do not remove this and leave it at the end of the file, where
1024 * Emacs will automagically detect them.
1025 * ---------------------------------------------------------------------
1028 * indent-tabs-mode: t
1032 * vim:noexpandtab:sw=4:ts=4: