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/resolve.h"
65 #include "vm/stringlocal.h"
67 #include "vmcore/class.h"
68 #include "vmcore/loader.h"
69 #include "vmcore/primitive.h"
73 * Class: java/lang/Class
75 * Signature: ()Ljava/lang/String;
77 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
83 c = (classinfo *) klass;
85 /* create a java string */
87 s = (java_lang_String *) javastring_new(c->name);
92 /* return string where '/' is replaced by '.' */
94 for (i = 0; i < s->value->header.size; i++) {
95 if (s->value->data[i] == '/')
96 s->value->data[i] = '.';
104 * Class: java/lang/Class
106 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
108 #if defined(ENABLE_JAVASE)
109 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
110 #elif defined(ENABLE_JAVAME_CLDC1_1)
111 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
114 #if defined(ENABLE_JAVASE)
115 java_objectheader *cl;
120 java_objectheader *xptr;
125 #if defined(ENABLE_JAVASE)
126 cl = (java_objectheader *) loader;
129 /* illegal argument */
132 exceptions_throw_nullpointerexception();
136 /* create utf string in which '.' is replaced by '/' */
138 ufile = javastring_toutf((java_objectheader *) name, true);
139 uname = javastring_toutf((java_objectheader *) name, false);
141 /* name must not contain '/' (mauve test) */
143 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
145 exceptions_throw_classnotfoundexception(uname);
150 /* try to load, ... */
152 #if defined(ENABLE_JAVASE)
153 c = load_class_from_classloader(ufile, cl);
154 #elif defined(ENABLE_JAVAME_CLDC1_1)
155 c = load_class_bootstrap(ufile);
159 xptr = exceptions_get_exception();
161 xclass = xptr->vftbl->class;
163 /* if the exception is a NoClassDefFoundError, we replace it with a
164 ClassNotFoundException, otherwise return the exception */
166 if (xclass == class_java_lang_NoClassDefFoundError) {
167 /* clear exceptionptr, because builtin_new checks for
168 ExceptionInInitializerError */
169 exceptions_clear_exception();
171 exceptions_throw_classnotfoundexception(uname);
182 /* ...and initialize it, if required */
184 #if defined(ENABLE_JAVASE)
187 if (!initialize_class(c))
190 return (java_lang_Class *) c;
195 * Class: java/lang/Class
197 * Signature: (Ljava/lang/Object;)Z
199 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
202 java_objectheader *ob;
204 c = (classinfo *) klass;
205 ob = (java_objectheader *) o;
207 if (!(c->state & CLASS_LINKED))
211 return builtin_instanceof(ob, c);
216 * Class: java/lang/Class
217 * Method: isAssignableFrom
218 * Signature: (Ljava/lang/Class;)Z
220 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
225 kc = (classinfo *) klass;
226 cc = (classinfo *) c;
229 exceptions_throw_nullpointerexception();
233 if (!(kc->state & CLASS_LINKED))
237 if (!(cc->state & CLASS_LINKED))
241 return class_isanysubclass(cc, kc);
246 * Class: java/lang/Class
247 * Method: isInterface
250 s4 _Jv_java_lang_Class_isInterface(java_lang_Class *klass)
254 c = (classinfo *) klass;
256 if (c->flags & ACC_INTERFACE)
263 #if defined(ENABLE_JAVASE)
266 * Class: java/lang/Class
267 * Method: isPrimitive
270 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
275 c = (classinfo *) klass;
277 result = primitive_class_is_primitive(c);
284 * Class: java/lang/Class
285 * Method: getSuperclass
286 * Signature: ()Ljava/lang/Class;
288 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
293 c = (classinfo *) klass;
295 /* for java.lang.Object, primitive and Void classes we return NULL */
300 /* for interfaces we also return NULL */
302 if (c->flags & ACC_INTERFACE)
305 /* we may have to resolve the super class reference */
307 if ((sc = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
310 /* store the resolution */
314 return (java_lang_Class *) sc;
319 * Class: java/lang/Class
320 * Method: getInterfaces
321 * Signature: ()[Ljava/lang/Class;
323 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
327 java_objectarray *oa;
330 c = (classinfo *) klass;
332 if (!(c->state & CLASS_LINKED))
336 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
341 for (i = 0; i < c->interfacescount; i++) {
342 ic = c->interfaces[i].cls;
344 oa->data[i] = (java_objectheader *) ic;
352 * Class: java/lang/Class
353 * Method: getComponentType
354 * Signature: ()Ljava/lang/Class;
356 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
360 arraydescriptor *desc;
362 c = (classinfo *) klass;
364 /* XXX maybe we could find a way to do this without linking. */
365 /* This way should be safe and easy, however. */
367 if (!(c->state & CLASS_LINKED))
371 desc = c->vftbl->arraydesc;
376 if (desc->arraytype == ARRAYTYPE_OBJECT)
377 comp = desc->componentvftbl->class;
379 comp = primitive_class_get_by_type(desc->arraytype);
381 return (java_lang_Class *) comp;
386 * Class: java/lang/Class
387 * Method: getModifiers
390 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
393 classref_or_classinfo inner;
394 classref_or_classinfo outer;
398 c = (classinfo *) klass;
400 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
401 /* search for passed class as inner class */
403 for (i = 0; i < c->innerclasscount; i++) {
404 inner = c->innerclass[i].inner_class;
405 outer = c->innerclass[i].outer_class;
407 /* Check if inner is a classref or a real class and get
408 the name of the structure */
410 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
412 /* innerclass is this class */
414 if (innername == c->name) {
415 /* has the class actually an outer class? */
418 /* return flags got from the outer class file */
419 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
421 return c->flags & ACC_CLASS_REFLECT_MASK;
426 /* passed class is no inner class or it was not requested */
428 return c->flags & ACC_CLASS_REFLECT_MASK;
433 * Class: java/lang/Class
434 * Method: getDeclaringClass
435 * Signature: ()Ljava/lang/Class;
437 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
440 classref_or_classinfo inner;
445 c = (classinfo *) klass;
447 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
448 if (c->innerclasscount == 0) /* no innerclasses exist */
451 for (i = 0; i < c->innerclasscount; i++) {
452 inner = c->innerclass[i].inner_class;
454 /* check if inner_class is a classref or a real class and
455 get the class name from the structure */
457 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
459 /* innerclass is this class */
461 if (innername == c->name) {
462 /* maybe the outer class is not loaded yet */
464 if ((outer = resolve_classref_or_classinfo_eager(
465 c->innerclass[i].outer_class,
469 if (!(outer->state & CLASS_LINKED))
470 if (!link_class(outer))
473 return (java_lang_Class *) outer;
478 /* return NULL for arrayclasses and primitive classes */
485 * Class: java/lang/Class
486 * Method: getDeclaredClasses
487 * Signature: (Z)[Ljava/lang/Class;
489 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
492 classref_or_classinfo outer;
494 s4 declaredclasscount; /* number of declared classes */
495 s4 pos; /* current declared class */
496 java_objectarray *oa; /* array of declared classes */
499 c = (classinfo *) klass;
500 declaredclasscount = 0;
502 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
503 /* determine number of declared classes */
505 for (i = 0; i < c->innerclasscount; i++) {
506 outer = c->innerclass[i].outer_class;
508 /* check if outer_class is a classref or a real class and
509 get the class name from the structure */
511 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
513 /* outer class is this class */
515 if ((outername == c->name) &&
516 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
517 declaredclasscount++;
521 /* allocate Class[] and check for OOM */
523 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
528 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
529 outer = c->innerclass[i].outer_class;
531 /* check if outer_class is a classref or a real class and
532 get the class name from the structure */
534 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
536 /* outer class is this class */
538 if ((outername == c->name) &&
539 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
542 if ((inner = resolve_classref_or_classinfo_eager(
543 c->innerclass[i].inner_class,
547 if (!(inner->state & CLASS_LINKED))
548 if (!link_class(inner))
551 oa->data[pos++] = (java_objectheader *) inner;
560 * Class: java/lang/Class
561 * Method: getDeclaredFields
562 * Signature: (Z)[Ljava/lang/reflect/Field;
564 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
567 java_objectarray *oa; /* result: array of field-objects */
569 java_objectheader *o;
570 java_lang_reflect_Field *rf;
571 s4 public_fields; /* number of elements in field-array */
575 c = (classinfo *) klass;
577 /* determine number of fields */
579 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
580 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
583 /* create array of fields */
585 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
590 /* get the fields and store in the array */
592 for (i = 0, pos = 0; i < c->fieldscount; i++) {
595 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
596 /* create Field object */
598 o = native_new_and_init(class_java_lang_reflect_Field);
603 /* initialize instance fields */
605 rf = (java_lang_reflect_Field *) o;
607 rf->declaringClass = (java_lang_Class *) c;
608 rf->name = (java_lang_String *) javastring_new(f->name);
611 /* store object into array */
622 * Class: java/lang/Class
623 * Method: getDeclaredMethods
624 * Signature: (Z)[Ljava/lang/reflect/Method;
626 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
629 java_objectheader *o;
630 java_lang_reflect_Method *rm;
631 java_objectarray *oa; /* result: array of Method-objects */
632 methodinfo *m; /* the current method to be represented */
633 s4 public_methods; /* number of public methods of the class */
637 c = (classinfo *) klass;
640 /* JOWENN: array classes do not declare methods according to mauve
641 test. It should be considered, if we should return to my old
642 clone method overriding instead of declaring it as a member
645 if (_Jv_java_lang_Class_isArray(klass))
646 return builtin_anewarray(0, class_java_lang_reflect_Method);
648 /* determine number of methods */
650 for (i = 0; i < c->methodscount; i++) {
653 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
654 ((m->name != utf_init) && (m->name != utf_clinit)) &&
655 !(m->flags & ACC_MIRANDA))
659 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
664 for (i = 0, pos = 0; i < c->methodscount; i++) {
667 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
668 ((m->name != utf_init) && (m->name != utf_clinit)) &&
669 !(m->flags & ACC_MIRANDA)) {
671 o = native_new_and_init(class_java_lang_reflect_Method);
676 /* initialize instance fields */
678 rm = (java_lang_reflect_Method *) o;
680 rm->declaringClass = (java_lang_Class *) m->class;
681 rm->name = (java_lang_String *) javastring_new(m->name);
684 /* store object into array */
695 * Class: java/lang/Class
696 * Method: getDeclaredConstructors
697 * Signature: (Z)[Ljava/lang/reflect/Constructor;
699 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
702 methodinfo *m; /* the current method to be represented */
703 java_objectarray *oa; /* result: array of Method-objects */
704 java_objectheader *o;
705 java_lang_reflect_Constructor *rc;
706 s4 public_methods; /* number of public methods of the class */
710 c = (classinfo *) klass;
712 /* determine number of constructors */
714 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
717 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
718 (m->name == utf_init))
722 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
727 for (i = 0, pos = 0; i < c->methodscount; i++) {
730 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
731 (m->name == utf_init)) {
733 o = native_new_and_init(class_java_lang_reflect_Constructor);
738 /* initialize instance fields */
740 rc = (java_lang_reflect_Constructor *) o;
742 rc->clazz = (java_lang_Class *) c;
745 /* store object into array */
756 * Class: java/lang/Class
757 * Method: getClassLoader
758 * Signature: ()Ljava/lang/ClassLoader;
760 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
764 c = (classinfo *) klass;
766 return (java_lang_ClassLoader *) c->classloader;
769 #endif /* defined(ENABLE_JAVASE) */
773 * Class: java/lang/Class
777 s4 _Jv_java_lang_Class_isArray(java_lang_Class *klass)
781 c = (classinfo *) klass;
783 if (!(c->state & CLASS_LINKED))
787 return (c->vftbl->arraydesc != NULL);
791 #if defined(ENABLE_JAVASE)
794 * Class: java/lang/Class
795 * Method: throwException
796 * Signature: (Ljava/lang/Throwable;)V
798 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
800 java_objectheader *o;
802 o = (java_objectheader *) t;
804 exceptions_set_exception(o);
810 * Class: java/lang/Class
811 * Method: getDeclaredAnnotations
812 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
814 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
821 * Class: java/lang/Class
822 * Method: getEnclosingClass
823 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
825 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
828 classref_or_classinfo cr;
831 c = (classinfo *) klass;
833 /* get enclosing class */
835 cr = c->enclosingclass;
840 /* resolve the class if necessary */
842 if (IS_CLASSREF(cr)) {
843 ec = resolve_classref_eager(cr.ref);
851 return (java_lang_Class *) ec;
855 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
857 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
858 _Jv_java_lang_Class_getEnclosingMethod.
860 *******************************************************************************/
862 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
864 classref_or_classinfo cr;
865 constant_nameandtype *cn;
869 /* get enclosing class and method */
871 cr = c->enclosingclass;
872 cn = c->enclosingmethod;
874 /* check for enclosing class and method */
882 /* resolve the class if necessary */
884 if (IS_CLASSREF(cr)) {
885 ec = resolve_classref_eager(cr.ref);
893 /* find method in enclosing class */
895 m = class_findmethod(ec, cn->name, cn->descriptor);
898 exceptions_throw_internalerror("Enclosing method doesn't exist");
907 * Class: java/lang/Class
908 * Method: getEnclosingConstructor
909 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
911 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
915 java_objectheader *o;
916 java_lang_reflect_Constructor *rc;
918 c = (classinfo *) klass;
920 /* get enclosing method */
922 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
927 /* check for <init> */
929 if (m->name != utf_init)
932 /* create java.lang.reflect.Constructor object */
934 o = native_new_and_init(class_java_lang_reflect_Constructor);
939 /* initialize instance fields */
941 rc = (java_lang_reflect_Constructor *) o;
943 rc->clazz = (java_lang_Class *) m->class;
944 rc->slot = m - m->class->methods; /* calculate method slot */
951 * Class: java/lang/Class
952 * Method: getEnclosingMethod
953 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
955 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
959 java_objectheader *o;
960 java_lang_reflect_Method *rm;
962 c = (classinfo *) klass;
964 /* get enclosing method */
966 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
971 /* check for <init> */
973 if (m->name == utf_init)
976 /* create java.lang.reflect.Method object */
978 o = native_new_and_init(class_java_lang_reflect_Method);
983 /* initialize instance fields */
985 rm = (java_lang_reflect_Method *) o;
987 rm->declaringClass = (java_lang_Class *) m->class;
988 rm->name = (java_lang_String *) javastring_new(m->name);
989 rm->slot = m - m->class->methods; /* calculate method slot */
996 * Class: java/lang/Class
997 * Method: getClassSignature
998 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
1000 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
1003 java_objectheader *o;
1005 c = (classinfo *) klass;
1007 if (c->signature == NULL)
1010 o = javastring_new(c->signature);
1012 /* in error case o is NULL */
1014 return (java_lang_String *) o;
1020 * Class: java/lang/Class
1021 * Method: isAnonymousClass
1022 * Signature: (Ljava/lang/Class;)Z
1024 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1028 * Class: java/lang/VMClass
1029 * Method: isLocalClass
1030 * Signature: (Ljava/lang/Class;)Z
1032 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1036 * Class: java/lang/VMClass
1037 * Method: isMemberClass
1038 * Signature: (Ljava/lang/Class;)Z
1040 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
1043 #endif /* ENABLE_JAVASE */
1047 * These are local overrides for various environment variables in Emacs.
1048 * Please do not remove this and leave it at the end of the file, where
1049 * Emacs will automagically detect them.
1050 * ---------------------------------------------------------------------
1053 * indent-tabs-mode: t
1057 * vim:noexpandtab:sw=4:ts=4: