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_Class.c 8179 2007-07-05 11:21:08Z michi $
38 #include "mm/memory.h"
40 #include "native/jni.h"
41 #include "native/native.h"
43 /* keep this order of the native includes */
45 #include "native/include/java_lang_String.h"
47 #if defined(ENABLE_JAVASE)
48 # if defined(WITH_CLASSPATH_SUN)
49 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
51 # include "native/include/java_lang_ClassLoader.h"
54 #include "native/include/java_lang_Object.h"
55 #include "native/include/java_lang_Class.h"
57 #if defined(ENABLE_JAVASE)
58 # include "native/include/java_lang_reflect_Constructor.h"
59 # include "native/include/java_lang_reflect_Field.h"
60 # include "native/include/java_lang_reflect_Method.h"
63 #include "native/vm/java_lang_Class.h"
64 #include "native/vm/java_lang_String.h"
66 #if defined(ENABLE_JAVASE)
67 # include "native/vm/reflect.h"
70 #include "toolbox/logging.h"
72 #include "vm/builtin.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/initialize.h"
76 #include "vm/resolve.h"
77 #include "vm/stringlocal.h"
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81 #include "vmcore/primitive.h"
85 * Class: java/lang/Class
87 * Signature: ()Ljava/lang/String;
89 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
95 c = (classinfo *) klass;
97 /* create a java string */
99 s = (java_lang_String *) javastring_new(c->name);
104 /* return string where '/' is replaced by '.' */
106 for (i = 0; i < s->value->header.size; i++) {
107 if (s->value->data[i] == '/')
108 s->value->data[i] = '.';
116 * Class: java/lang/Class
118 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
120 #if defined(ENABLE_JAVASE)
121 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
122 #elif defined(ENABLE_JAVAME_CLDC1_1)
123 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
126 #if defined(ENABLE_JAVASE)
135 #if defined(ENABLE_JAVASE)
136 cl = loader_hashtable_classloader_add((java_objectheader *) loader);
139 /* illegal argument */
142 exceptions_throw_nullpointerexception();
146 /* create utf string in which '.' is replaced by '/' */
148 ufile = javastring_toutf((java_objectheader *) name, true);
149 uname = javastring_toutf((java_objectheader *) name, false);
151 /* name must not contain '/' (mauve test) */
153 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
155 exceptions_throw_classnotfoundexception(uname);
160 /* try to load, ... */
162 #if defined(ENABLE_JAVASE)
163 c = load_class_from_classloader(ufile, cl);
164 #elif defined(ENABLE_JAVAME_CLDC1_1)
165 c = load_class_bootstrap(ufile);
176 /* ...and initialize it, if required */
178 #if defined(ENABLE_JAVASE)
181 if (!initialize_class(c))
184 return (java_lang_Class *) c;
189 * Class: java/lang/Class
191 * Signature: (Ljava/lang/Object;)Z
193 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
196 java_objectheader *ob;
198 c = (classinfo *) klass;
199 ob = (java_objectheader *) o;
201 if (!(c->state & CLASS_LINKED))
205 return builtin_instanceof(ob, c);
210 * Class: java/lang/Class
211 * Method: isAssignableFrom
212 * Signature: (Ljava/lang/Class;)Z
214 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
219 kc = (classinfo *) klass;
220 cc = (classinfo *) c;
223 exceptions_throw_nullpointerexception();
227 if (!(kc->state & CLASS_LINKED))
231 if (!(cc->state & CLASS_LINKED))
235 return class_isanysubclass(cc, kc);
240 * Class: java/lang/Class
241 * Method: isInterface
244 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
248 c = (classinfo *) this;
250 return class_is_interface(c);
254 #if defined(ENABLE_JAVASE)
257 * Class: java/lang/Class
258 * Method: isPrimitive
261 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
266 c = (classinfo *) klass;
268 result = primitive_class_is_primitive(c);
275 * Class: java/lang/Class
276 * Method: getSuperclass
277 * Signature: ()Ljava/lang/Class;
279 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
284 c = (classinfo *) klass;
286 /* for java.lang.Object, primitive and Void classes we return NULL */
291 /* for interfaces we also return NULL */
293 if (c->flags & ACC_INTERFACE)
296 /* we may have to resolve the super class reference */
298 if ((sc = resolve_classref_or_classinfo_eager(c->super, true)) == NULL)
301 /* store the resolution */
305 return (java_lang_Class *) sc;
310 * Class: java/lang/Class
311 * Method: getInterfaces
312 * Signature: ()[Ljava/lang/Class;
314 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
318 java_objectarray *oa;
321 c = (classinfo *) klass;
323 if (!(c->state & CLASS_LINKED))
327 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
332 for (i = 0; i < c->interfacescount; i++) {
333 ic = c->interfaces[i].cls;
335 oa->data[i] = (java_objectheader *) ic;
343 * Class: java/lang/Class
344 * Method: getComponentType
345 * Signature: ()Ljava/lang/Class;
347 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
351 arraydescriptor *desc;
353 c = (classinfo *) klass;
355 /* XXX maybe we could find a way to do this without linking. */
356 /* This way should be safe and easy, however. */
358 if (!(c->state & CLASS_LINKED))
362 desc = c->vftbl->arraydesc;
367 if (desc->arraytype == ARRAYTYPE_OBJECT)
368 comp = desc->componentvftbl->class;
370 comp = primitive_class_get_by_type(desc->arraytype);
372 return (java_lang_Class *) comp;
377 * Class: java/lang/Class
378 * Method: getModifiers
381 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
384 classref_or_classinfo inner;
385 classref_or_classinfo outer;
389 c = (classinfo *) klass;
391 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
392 /* search for passed class as inner class */
394 for (i = 0; i < c->innerclasscount; i++) {
395 inner = c->innerclass[i].inner_class;
396 outer = c->innerclass[i].outer_class;
398 /* Check if inner is a classref or a real class and get
399 the name of the structure */
401 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
403 /* innerclass is this class */
405 if (innername == c->name) {
406 /* has the class actually an outer class? */
409 /* return flags got from the outer class file */
410 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
412 return c->flags & ACC_CLASS_REFLECT_MASK;
417 /* passed class is no inner class or it was not requested */
419 return c->flags & ACC_CLASS_REFLECT_MASK;
424 * Class: java/lang/Class
425 * Method: getDeclaringClass
426 * Signature: ()Ljava/lang/Class;
428 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
431 classref_or_classinfo inner;
436 c = (classinfo *) klass;
438 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
439 if (c->innerclasscount == 0) /* no innerclasses exist */
442 for (i = 0; i < c->innerclasscount; i++) {
443 inner = c->innerclass[i].inner_class;
445 /* check if inner_class is a classref or a real class and
446 get the class name from the structure */
448 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
450 /* innerclass is this class */
452 if (innername == c->name) {
453 /* maybe the outer class is not loaded yet */
455 if ((outer = resolve_classref_or_classinfo_eager(
456 c->innerclass[i].outer_class,
460 if (!(outer->state & CLASS_LINKED))
461 if (!link_class(outer))
464 return (java_lang_Class *) outer;
469 /* return NULL for arrayclasses and primitive classes */
476 * Class: java/lang/Class
477 * Method: getDeclaredClasses
478 * Signature: (Z)[Ljava/lang/Class;
480 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
483 classref_or_classinfo outer;
485 s4 declaredclasscount; /* number of declared classes */
486 s4 pos; /* current declared class */
487 java_objectarray *oa; /* array of declared classes */
490 c = (classinfo *) klass;
491 declaredclasscount = 0;
493 if (!primitive_class_is_primitive(c) && (c->name->text[0] != '[')) {
494 /* determine number of declared classes */
496 for (i = 0; i < c->innerclasscount; i++) {
497 outer = c->innerclass[i].outer_class;
499 /* check if outer_class is a classref or a real class and
500 get the class name from the structure */
502 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
504 /* outer class is this class */
506 if ((outername == c->name) &&
507 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
508 declaredclasscount++;
512 /* allocate Class[] and check for OOM */
514 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
519 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
520 outer = c->innerclass[i].outer_class;
522 /* check if outer_class is a classref or a real class and
523 get the class name from the structure */
525 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
527 /* outer class is this class */
529 if ((outername == c->name) &&
530 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
533 if ((inner = resolve_classref_or_classinfo_eager(
534 c->innerclass[i].inner_class,
538 if (!(inner->state & CLASS_LINKED))
539 if (!link_class(inner))
542 oa->data[pos++] = (java_objectheader *) inner;
551 * Class: java/lang/Class
552 * Method: getDeclaredFields
553 * Signature: (Z)[Ljava/lang/reflect/Field;
555 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
558 java_objectarray *oa; /* result: array of field-objects */
560 java_lang_reflect_Field *rf;
561 s4 public_fields; /* number of elements in field-array */
565 c = (classinfo *) klass;
567 /* determine number of fields */
569 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
570 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
573 /* create array of fields */
575 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
580 /* get the fields and store in the array */
582 for (i = 0, pos = 0; i < c->fieldscount; i++) {
585 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
586 /* create Field object */
588 rf = reflect_field_new(f);
590 /* store object into array */
592 oa->data[pos++] = (java_objectheader *) rf;
601 * Class: java/lang/Class
602 * Method: getDeclaredMethods
603 * Signature: (Z)[Ljava/lang/reflect/Method;
605 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
608 java_lang_reflect_Method *rm;
609 java_objectarray *oa; /* result: array of Method-objects */
610 methodinfo *m; /* the current method to be represented */
611 s4 public_methods; /* number of public methods of the class */
615 c = (classinfo *) klass;
619 /* JOWENN: array classes do not declare methods according to mauve
620 test. It should be considered, if we should return to my old
621 clone method overriding instead of declaring it as a member
624 if (class_is_array(c))
625 return builtin_anewarray(0, class_java_lang_reflect_Method);
627 /* determine number of methods */
629 for (i = 0; i < c->methodscount; i++) {
632 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
633 ((m->name != utf_init) && (m->name != utf_clinit)) &&
634 !(m->flags & ACC_MIRANDA))
638 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
643 for (i = 0, pos = 0; i < c->methodscount; i++) {
646 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
647 ((m->name != utf_init) && (m->name != utf_clinit)) &&
648 !(m->flags & ACC_MIRANDA)) {
649 /* create Method object */
651 rm = reflect_method_new(m);
653 /* store object into array */
655 oa->data[pos++] = (java_objectheader *) rm;
664 * Class: java/lang/Class
665 * Method: getDeclaredConstructors
666 * Signature: (Z)[Ljava/lang/reflect/Constructor;
668 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
671 methodinfo *m; /* the current method to be represented */
672 java_objectarray *oa; /* result: array of Method-objects */
673 java_lang_reflect_Constructor *rc;
674 s4 public_methods; /* number of public methods of the class */
678 c = (classinfo *) klass;
680 /* determine number of constructors */
682 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
685 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
686 (m->name == utf_init))
690 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
695 for (i = 0, pos = 0; i < c->methodscount; i++) {
698 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
699 (m->name == utf_init)) {
700 /* create Constructor object */
702 rc = reflect_constructor_new(m);
704 /* store object into array */
706 oa->data[pos++] = (java_objectheader *) rc;
715 * Class: java/lang/Class
716 * Method: getClassLoader
717 * Signature: ()Ljava/lang/ClassLoader;
719 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
723 c = (classinfo *) klass;
725 if (c->classloader == NULL)
728 return (java_lang_ClassLoader *) c->classloader->object;
731 #endif /* defined(ENABLE_JAVASE) */
735 * Class: java/lang/Class
739 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
743 c = (classinfo *) this;
745 return class_is_array(c);
749 #if defined(ENABLE_JAVASE)
752 * Class: java/lang/Class
753 * Method: throwException
754 * Signature: (Ljava/lang/Throwable;)V
756 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
758 java_objectheader *o;
760 o = (java_objectheader *) t;
762 exceptions_set_exception(o);
768 * Class: java/lang/Class
769 * Method: getDeclaredAnnotations
770 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
772 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
779 * Class: java/lang/Class
780 * Method: getEnclosingClass
781 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
783 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
786 classref_or_classinfo cr;
789 c = (classinfo *) klass;
791 /* get enclosing class */
793 cr = c->enclosingclass;
798 /* resolve the class if necessary */
800 if (IS_CLASSREF(cr)) {
801 ec = resolve_classref_eager(cr.ref);
809 return (java_lang_Class *) ec;
813 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
815 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
816 _Jv_java_lang_Class_getEnclosingMethod.
818 *******************************************************************************/
820 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
822 classref_or_classinfo cr;
823 constant_nameandtype *cn;
827 /* get enclosing class and method */
829 cr = c->enclosingclass;
830 cn = c->enclosingmethod;
832 /* check for enclosing class and method */
840 /* resolve the class if necessary */
842 if (IS_CLASSREF(cr)) {
843 ec = resolve_classref_eager(cr.ref);
851 /* find method in enclosing class */
853 m = class_findmethod(ec, cn->name, cn->descriptor);
856 exceptions_throw_internalerror("Enclosing method doesn't exist");
865 * Class: java/lang/Class
866 * Method: getEnclosingConstructor
867 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
869 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
873 java_lang_reflect_Constructor *rc;
875 c = (classinfo *) klass;
877 /* get enclosing method */
879 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
884 /* check for <init> */
886 if (m->name != utf_init)
889 /* create Constructor object */
891 rc = reflect_constructor_new(m);
898 * Class: java/lang/Class
899 * Method: getEnclosingMethod
900 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
902 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
906 java_lang_reflect_Method *rm;
908 c = (classinfo *) klass;
910 /* get enclosing method */
912 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
917 /* check for <init> */
919 if (m->name == utf_init)
922 /* create java.lang.reflect.Method object */
924 rm = reflect_method_new(m);
931 * Class: java/lang/Class
932 * Method: getClassSignature
933 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
935 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
938 java_objectheader *o;
940 c = (classinfo *) klass;
942 if (c->signature == NULL)
945 o = javastring_new(c->signature);
947 /* in error case o is NULL */
949 return (java_lang_String *) o;
955 * Class: java/lang/Class
956 * Method: isAnonymousClass
957 * Signature: (Ljava/lang/Class;)Z
959 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
963 * Class: java/lang/VMClass
964 * Method: isLocalClass
965 * Signature: (Ljava/lang/Class;)Z
967 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
971 * Class: java/lang/VMClass
972 * Method: isMemberClass
973 * Signature: (Ljava/lang/Class;)Z
975 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
978 #endif /* ENABLE_JAVASE */
982 * These are local overrides for various environment variables in Emacs.
983 * Please do not remove this and leave it at the end of the file, where
984 * Emacs will automagically detect them.
985 * ---------------------------------------------------------------------
988 * indent-tabs-mode: t
992 * vim:noexpandtab:sw=4:ts=4: