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 8307 2007-08-15 15:20:47Z twisti $
38 #include "mm/memory.h"
40 #include "native/jni.h"
41 #include "native/llni.h"
42 #include "native/native.h"
44 /* keep this order of the native includes */
46 #include "native/include/java_lang_String.h"
48 #if defined(ENABLE_JAVASE)
49 # if defined(WITH_CLASSPATH_SUN)
50 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
52 # include "native/include/java_lang_ClassLoader.h"
55 #include "native/include/java_lang_Object.h"
56 #include "native/include/java_lang_Class.h"
58 #if defined(ENABLE_JAVASE)
59 # include "native/include/java_lang_reflect_Constructor.h"
60 # include "native/include/java_lang_reflect_Field.h"
61 # include "native/include/java_lang_reflect_Method.h"
64 #include "native/vm/java_lang_Class.h"
65 #include "native/vm/java_lang_String.h"
67 #if defined(ENABLE_JAVASE)
68 # include "native/vm/reflect.h"
71 #include "toolbox/logging.h"
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/primitive.h"
78 #include "vm/resolve.h"
79 #include "vm/stringlocal.h"
81 #include "vmcore/class.h"
82 #include "vmcore/loader.h"
84 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
85 #include "vmcore/annotation.h"
86 #include "native/include/sun_reflect_ConstantPool.h"
90 * Class: java/lang/Class
92 * Signature: ()Ljava/lang/String;
94 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
101 c = (classinfo *) klass;
103 /* create a java string */
105 s = (java_lang_String *) javastring_new(c->name);
110 /* return string where '/' is replaced by '.' */
112 LLNI_field_get_ref(s, value, ca);
114 for (i = 0; i < ca->header.size; i++) {
115 if (ca->data[i] == '/')
124 * Class: java/lang/Class
126 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
128 #if defined(ENABLE_JAVASE)
129 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
130 #elif defined(ENABLE_JAVAME_CLDC1_1)
131 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
134 #if defined(ENABLE_JAVASE)
143 #if defined(ENABLE_JAVASE)
144 cl = (classloader *) loader;
147 /* illegal argument */
150 exceptions_throw_nullpointerexception();
154 /* create utf string in which '.' is replaced by '/' */
156 ufile = javastring_toutf((java_handle_t *) name, true);
157 uname = javastring_toutf((java_handle_t *) name, false);
159 /* name must not contain '/' (mauve test) */
161 for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
163 exceptions_throw_classnotfoundexception(uname);
168 /* try to load, ... */
170 #if defined(ENABLE_JAVASE)
171 c = load_class_from_classloader(ufile, cl);
172 #elif defined(ENABLE_JAVAME_CLDC1_1)
173 c = load_class_bootstrap(ufile);
184 /* ...and initialize it, if required */
186 #if defined(ENABLE_JAVASE)
189 if (!initialize_class(c))
192 return (java_lang_Class *) c;
197 * Class: java/lang/Class
199 * Signature: (Ljava/lang/Object;)Z
201 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
206 c = (classinfo *) klass;
207 ob = (java_handle_t *) o;
209 if (!(c->state & CLASS_LINKED))
213 return builtin_instanceof(ob, c);
218 * Class: java/lang/Class
219 * Method: isAssignableFrom
220 * Signature: (Ljava/lang/Class;)Z
222 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
227 kc = (classinfo *) klass;
228 cc = (classinfo *) c;
231 exceptions_throw_nullpointerexception();
235 if (!(kc->state & CLASS_LINKED))
239 if (!(cc->state & CLASS_LINKED))
243 return class_isanysubclass(cc, kc);
248 * Class: java/lang/Class
249 * Method: isInterface
252 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
256 c = (classinfo *) this;
258 return class_is_interface(c);
262 #if defined(ENABLE_JAVASE)
265 * Class: java/lang/Class
266 * Method: isPrimitive
269 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
273 c = (classinfo *) klass;
275 return class_is_primitive(c);
280 * Class: java/lang/Class
281 * Method: getSuperclass
282 * Signature: ()Ljava/lang/Class;
284 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
289 c = (classinfo *) klass;
291 super = class_get_superclass(c);
293 return (java_lang_Class *) super;
298 * Class: java/lang/Class
299 * Method: getInterfaces
300 * Signature: ()[Ljava/lang/Class;
302 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
305 java_objectarray *oa;
307 c = (classinfo *) klass;
309 oa = class_get_interfaces(c);
316 * Class: java/lang/Class
317 * Method: getComponentType
318 * Signature: ()Ljava/lang/Class;
320 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
324 arraydescriptor *desc;
326 c = (classinfo *) klass;
328 /* XXX maybe we could find a way to do this without linking. */
329 /* This way should be safe and easy, however. */
331 if (!(c->state & CLASS_LINKED))
335 desc = c->vftbl->arraydesc;
340 if (desc->arraytype == ARRAYTYPE_OBJECT)
341 comp = desc->componentvftbl->class;
343 comp = primitive_class_get_by_type(desc->arraytype);
345 return (java_lang_Class *) comp;
350 * Class: java/lang/Class
351 * Method: getModifiers
354 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
357 classref_or_classinfo inner;
358 classref_or_classinfo outer;
362 c = (classinfo *) klass;
364 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
365 /* search for passed class as inner class */
367 for (i = 0; i < c->innerclasscount; i++) {
368 inner = c->innerclass[i].inner_class;
369 outer = c->innerclass[i].outer_class;
371 /* Check if inner is a classref or a real class and get
372 the name of the structure */
374 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
376 /* innerclass is this class */
378 if (innername == c->name) {
379 /* has the class actually an outer class? */
382 /* return flags got from the outer class file */
383 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
385 return c->flags & ACC_CLASS_REFLECT_MASK;
390 /* passed class is no inner class or it was not requested */
392 return c->flags & ACC_CLASS_REFLECT_MASK;
397 * Class: java/lang/Class
398 * Method: getDeclaringClass
399 * Signature: ()Ljava/lang/Class;
401 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
405 c = (classinfo *) klass;
407 return (java_lang_Class *) class_get_declaringclass(c);
412 * Class: java/lang/Class
413 * Method: getDeclaredClasses
414 * Signature: (Z)[Ljava/lang/Class;
416 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
419 classref_or_classinfo outer;
421 s4 declaredclasscount; /* number of declared classes */
422 s4 pos; /* current declared class */
423 java_objectarray *oa; /* array of declared classes */
426 c = (classinfo *) klass;
427 declaredclasscount = 0;
429 if (!class_is_primitive(c) && (c->name->text[0] != '[')) {
430 /* determine number of declared classes */
432 for (i = 0; i < c->innerclasscount; i++) {
433 outer = c->innerclass[i].outer_class;
435 /* check if outer_class is a classref or a real class and
436 get the class name from the structure */
438 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
440 /* outer class is this class */
442 if ((outername == c->name) &&
443 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
444 declaredclasscount++;
448 /* allocate Class[] and check for OOM */
450 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
455 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
456 outer = c->innerclass[i].outer_class;
458 /* check if outer_class is a classref or a real class and
459 get the class name from the structure */
461 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
463 /* outer class is this class */
465 if ((outername == c->name) &&
466 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
469 if ((inner = resolve_classref_or_classinfo_eager(
470 c->innerclass[i].inner_class,
474 if (!(inner->state & CLASS_LINKED))
475 if (!link_class(inner))
478 oa->data[pos++] = inner;
487 * Class: java/lang/Class
488 * Method: getDeclaredFields
489 * Signature: (Z)[Ljava/lang/reflect/Field;
491 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
494 java_objectarray *oa; /* result: array of field-objects */
496 java_lang_reflect_Field *rf;
497 s4 public_fields; /* number of elements in field-array */
501 c = (classinfo *) klass;
503 /* determine number of fields */
505 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
506 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
509 /* create array of fields */
511 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
516 /* get the fields and store in the array */
518 for (i = 0, pos = 0; i < c->fieldscount; i++) {
521 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
522 /* create Field object */
524 rf = reflect_field_new(f);
526 /* store object into array */
528 oa->data[pos++] = rf;
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_lang_reflect_Method *rm;
545 java_objectarray *oa; /* result: array of Method-objects */
546 methodinfo *m; /* the current method to be represented */
547 s4 public_methods; /* number of public methods of the class */
551 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 (class_is_array(c))
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)) {
585 /* create Method object */
587 rm = reflect_method_new(m);
589 /* store object into array */
591 oa->data[pos++] = rm;
600 * Class: java/lang/Class
601 * Method: getDeclaredConstructors
602 * Signature: (Z)[Ljava/lang/reflect/Constructor;
604 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
607 methodinfo *m; /* the current method to be represented */
608 java_objectarray *oa; /* result: array of Method-objects */
609 java_lang_reflect_Constructor *rc;
610 s4 public_methods; /* number of public methods of the class */
614 c = (classinfo *) klass;
616 /* determine number of constructors */
618 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
621 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
622 (m->name == utf_init))
626 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
631 for (i = 0, pos = 0; i < c->methodscount; i++) {
634 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
635 (m->name == utf_init)) {
636 /* create Constructor object */
638 rc = reflect_constructor_new(m);
640 /* store object into array */
642 oa->data[pos++] = rc;
651 * Class: java/lang/Class
652 * Method: getClassLoader
653 * Signature: ()Ljava/lang/ClassLoader;
655 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
659 c = (classinfo *) klass;
661 return (java_lang_ClassLoader *) c->classloader;
664 #endif /* defined(ENABLE_JAVASE) */
668 * Class: java/lang/Class
672 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
676 c = (classinfo *) this;
678 return class_is_array(c);
682 #if defined(ENABLE_JAVASE)
685 * Class: java/lang/Class
686 * Method: throwException
687 * Signature: (Ljava/lang/Throwable;)V
689 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
693 o = (java_handle_t *) t;
695 exceptions_set_exception(o);
699 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
701 * Class: java/lang/Class
702 * Method: getDeclaredAnnotations
703 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
705 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
707 classinfo *c = (classinfo*)klass;
708 static methodinfo *m_parseAnnotationsIntoArray = NULL;
709 utf *utf_parseAnnotationsIntoArray = NULL;
710 utf *utf_desc = NULL;
711 java_bytearray *annotations = NULL;
712 sun_reflect_ConstantPool *constantPool = NULL;
714 java_lang_Object *o = (java_lang_Object*)klass;
717 exceptions_throw_nullpointerexception();
721 /* Return null for arrays and primitives: */
722 if (class_is_primitive(c) || class_is_array(c)) {
726 if (c->annotations != NULL) {
727 size = c->annotations->size;
728 annotations = builtin_newarray_byte(size);
730 if(annotations != NULL) {
731 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
736 (sun_reflect_ConstantPool*)native_new_and_init(
737 class_sun_reflect_ConstantPool);
739 if(constantPool == NULL) {
744 LLNI_field_set_ref(constantPool, constantPoolOop, o);
746 /* only resolve the method the first time */
747 if (m_parseAnnotationsIntoArray == NULL) {
748 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
749 utf_desc = utf_new_char(
750 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
751 "[Ljava/lang/annotation/Annotation;");
753 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
758 m_parseAnnotationsIntoArray = class_resolveclassmethod(
759 class_sun_reflect_annotation_AnnotationParser,
760 utf_parseAnnotationsIntoArray,
762 class_java_lang_Class,
765 if (m_parseAnnotationsIntoArray == NULL) {
766 /* method not found */
771 return vm_call_method(
772 m_parseAnnotationsIntoArray, NULL,
773 annotations, constantPool, 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)
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: