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 8335 2007-08-17 11:04:35Z michi $
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)
86 #include "vmcore/annotation.h"
87 #include "native/include/sun_reflect_ConstantPool.h"
91 * Class: java/lang/Class
93 * Signature: ()Ljava/lang/String;
95 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
99 java_handle_chararray_t *ca;
102 c = (classinfo *) klass;
104 /* create a java string */
106 s = (java_lang_String *) javastring_new(c->name);
111 /* return string where '/' is replaced by '.' */
113 LLNI_field_get_ref(s, value, ca);
115 for (i = 0; i < LLNI_array_size(ca); i++) {
116 if (LLNI_array_direct(ca, i) == '/')
117 LLNI_array_direct(ca, i) = '.';
125 * Class: java/lang/Class
127 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
129 #if defined(ENABLE_JAVASE)
130 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
131 #elif defined(ENABLE_JAVAME_CLDC1_1)
132 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
135 #if defined(ENABLE_JAVASE)
144 #if defined(ENABLE_JAVASE)
145 cl = loader_hashtable_classloader_add((java_handle_t *) loader);
148 /* illegal argument */
151 exceptions_throw_nullpointerexception();
155 /* create utf string in which '.' is replaced by '/' */
157 ufile = javastring_toutf((java_handle_t *) name, true);
158 uname = javastring_toutf((java_handle_t *) name, false);
160 /* name must not contain '/' (mauve test) */
162 for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
164 exceptions_throw_classnotfoundexception(uname);
169 /* try to load, ... */
171 #if defined(ENABLE_JAVASE)
172 c = load_class_from_classloader(ufile, cl);
173 #elif defined(ENABLE_JAVAME_CLDC1_1)
174 c = load_class_bootstrap(ufile);
185 /* ...and initialize it, if required */
187 #if defined(ENABLE_JAVASE)
190 if (!initialize_class(c))
193 return (java_lang_Class *) c;
198 * Class: java/lang/Class
200 * Signature: (Ljava/lang/Object;)Z
202 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
207 c = (classinfo *) klass;
208 ob = (java_handle_t *) o;
210 if (!(c->state & CLASS_LINKED))
214 return builtin_instanceof(ob, c);
219 * Class: java/lang/Class
220 * Method: isAssignableFrom
221 * Signature: (Ljava/lang/Class;)Z
223 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
228 kc = (classinfo *) klass;
229 cc = (classinfo *) c;
232 exceptions_throw_nullpointerexception();
236 if (!(kc->state & CLASS_LINKED))
240 if (!(cc->state & CLASS_LINKED))
244 return class_isanysubclass(cc, kc);
249 * Class: java/lang/Class
250 * Method: isInterface
253 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
257 c = (classinfo *) this;
259 return class_is_interface(c);
263 #if defined(ENABLE_JAVASE)
266 * Class: java/lang/Class
267 * Method: isPrimitive
270 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
274 c = (classinfo *) klass;
276 return class_is_primitive(c);
281 * Class: java/lang/Class
282 * Method: getSuperclass
283 * Signature: ()Ljava/lang/Class;
285 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
290 c = (classinfo *) klass;
292 super = class_get_superclass(c);
294 return (java_lang_Class *) super;
299 * Class: java/lang/Class
300 * Method: getInterfaces
301 * Signature: ()[Ljava/lang/Class;
303 java_handle_objectarray_t *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
306 java_handle_objectarray_t *oa;
308 c = (classinfo *) klass;
310 oa = class_get_interfaces(c);
317 * Class: java/lang/Class
318 * Method: getComponentType
319 * Signature: ()Ljava/lang/Class;
321 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
325 arraydescriptor *desc;
327 c = (classinfo *) klass;
329 /* XXX maybe we could find a way to do this without linking. */
330 /* This way should be safe and easy, however. */
332 if (!(c->state & CLASS_LINKED))
336 desc = c->vftbl->arraydesc;
341 if (desc->arraytype == ARRAYTYPE_OBJECT)
342 comp = desc->componentvftbl->class;
344 comp = primitive_class_get_by_type(desc->arraytype);
346 return (java_lang_Class *) comp;
351 * Class: java/lang/Class
352 * Method: getModifiers
355 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
358 classref_or_classinfo inner;
359 classref_or_classinfo outer;
363 c = (classinfo *) klass;
365 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
366 /* search for passed class as inner class */
368 for (i = 0; i < c->innerclasscount; i++) {
369 inner = c->innerclass[i].inner_class;
370 outer = c->innerclass[i].outer_class;
372 /* Check if inner is a classref or a real class and get
373 the name of the structure */
375 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
377 /* innerclass is this class */
379 if (innername == c->name) {
380 /* has the class actually an outer class? */
383 /* return flags got from the outer class file */
384 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
386 return c->flags & ACC_CLASS_REFLECT_MASK;
391 /* passed class is no inner class or it was not requested */
393 return c->flags & ACC_CLASS_REFLECT_MASK;
398 * Class: java/lang/Class
399 * Method: getDeclaringClass
400 * Signature: ()Ljava/lang/Class;
402 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
406 c = (classinfo *) klass;
408 return (java_lang_Class *) class_get_declaringclass(c);
413 * Class: java/lang/Class
414 * Method: getDeclaredClasses
415 * Signature: (Z)[Ljava/lang/Class;
417 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
420 java_handle_objectarray_t *oa;
422 c = (classinfo *) klass;
424 oa = class_get_declaredclasses(c, publicOnly);
431 * Class: java/lang/Class
432 * Method: getDeclaredFields
433 * Signature: (Z)[Ljava/lang/reflect/Field;
435 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
438 java_handle_objectarray_t *oa; /* result: array of field-objects */
440 java_lang_reflect_Field *rf;
441 s4 public_fields; /* number of elements in field-array */
445 c = (classinfo *) klass;
447 /* determine number of fields */
449 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
450 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
453 /* create array of fields */
455 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
460 /* get the fields and store in the array */
462 for (i = 0, pos = 0; i < c->fieldscount; i++) {
465 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
466 /* create Field object */
468 rf = reflect_field_new(f);
470 /* store object into array */
472 LLNI_objectarray_element_set(oa, pos, rf);
482 * Class: java/lang/Class
483 * Method: getDeclaredMethods
484 * Signature: (Z)[Ljava/lang/reflect/Method;
486 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
489 java_lang_reflect_Method *rm;
490 java_handle_objectarray_t *oa; /* result: array of Method-objects */
491 methodinfo *m; /* the current method to be represented */
492 s4 public_methods; /* number of public methods of the class */
496 c = (classinfo *) klass;
500 /* JOWENN: array classes do not declare methods according to mauve
501 test. It should be considered, if we should return to my old
502 clone method overriding instead of declaring it as a member
505 if (class_is_array(c))
506 return builtin_anewarray(0, class_java_lang_reflect_Method);
508 /* determine number of methods */
510 for (i = 0; i < c->methodscount; i++) {
513 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
514 ((m->name != utf_init) && (m->name != utf_clinit)) &&
515 !(m->flags & ACC_MIRANDA))
519 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
524 for (i = 0, pos = 0; i < c->methodscount; i++) {
527 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
528 ((m->name != utf_init) && (m->name != utf_clinit)) &&
529 !(m->flags & ACC_MIRANDA)) {
530 /* create Method object */
532 rm = reflect_method_new(m);
534 /* store object into array */
536 LLNI_objectarray_element_set(oa, pos, rm);
546 * Class: java/lang/Class
547 * Method: getDeclaredConstructors
548 * Signature: (Z)[Ljava/lang/reflect/Constructor;
550 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
553 methodinfo *m; /* the current method to be represented */
554 java_handle_objectarray_t *oa; /* result: array of Method-objects */
555 java_lang_reflect_Constructor *rc;
556 s4 public_methods; /* number of public methods of the class */
560 c = (classinfo *) klass;
562 /* determine number of constructors */
564 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
567 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
568 (m->name == utf_init))
572 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
577 for (i = 0, pos = 0; i < c->methodscount; i++) {
580 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
581 (m->name == utf_init)) {
582 /* create Constructor object */
584 rc = reflect_constructor_new(m);
586 /* store object into array */
588 LLNI_objectarray_element_set(oa, pos, rc);
598 * Class: java/lang/Class
599 * Method: getClassLoader
600 * Signature: ()Ljava/lang/ClassLoader;
602 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
606 c = (classinfo *) klass;
608 if (c->classloader == NULL)
611 return (java_lang_ClassLoader *) c->classloader->object;
614 #endif /* defined(ENABLE_JAVASE) */
618 * Class: java/lang/Class
622 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
626 c = (classinfo *) this;
628 return class_is_array(c);
632 #if defined(ENABLE_JAVASE)
635 * Class: java/lang/Class
636 * Method: throwException
637 * Signature: (Ljava/lang/Throwable;)V
639 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
643 o = (java_handle_t *) t;
645 exceptions_set_exception(o);
649 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
651 * Class: java/lang/Class
652 * Method: getDeclaredAnnotations
653 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
655 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
657 classinfo *c = (classinfo*)klass;
658 static methodinfo *m_parseAnnotationsIntoArray = NULL;
659 utf *utf_parseAnnotationsIntoArray = NULL;
660 utf *utf_desc = NULL;
661 java_handle_bytearray_t *annotations = NULL;
662 sun_reflect_ConstantPool *constantPool = NULL;
664 java_lang_Object *constantPoolOop = (java_lang_Object*)klass;
667 exceptions_throw_nullpointerexception();
671 /* Return null for arrays and primitives: */
672 if (class_is_primitive(c) || class_is_array(c)) {
676 if (c->annotations != NULL) {
677 size = c->annotations->size;
678 annotations = builtin_newarray_byte(size);
680 if(annotations != NULL) {
681 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
686 (sun_reflect_ConstantPool*)native_new_and_init(
687 class_sun_reflect_ConstantPool);
689 if(constantPool == NULL) {
694 LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
696 /* only resolve the method the first time */
697 if (m_parseAnnotationsIntoArray == NULL) {
698 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
699 utf_desc = utf_new_char(
700 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
701 "[Ljava/lang/annotation/Annotation;");
703 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
708 m_parseAnnotationsIntoArray = class_resolveclassmethod(
709 class_sun_reflect_annotation_AnnotationParser,
710 utf_parseAnnotationsIntoArray,
712 class_java_lang_Class,
715 if (m_parseAnnotationsIntoArray == NULL) {
716 /* method not found */
721 return (java_handle_objectarray_t*)vm_call_method(
722 m_parseAnnotationsIntoArray, NULL,
723 annotations, constantPool, klass);
729 * Class: java/lang/Class
730 * Method: getEnclosingClass
731 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
733 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
736 classref_or_classinfo cr;
739 c = (classinfo *) klass;
741 /* get enclosing class */
743 cr = c->enclosingclass;
748 /* resolve the class if necessary */
750 if (IS_CLASSREF(cr)) {
751 ec = resolve_classref_eager(cr.ref);
759 return (java_lang_Class *) ec;
763 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
765 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
766 _Jv_java_lang_Class_getEnclosingMethod.
768 *******************************************************************************/
770 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
772 classref_or_classinfo cr;
773 constant_nameandtype *cn;
777 /* get enclosing class and method */
779 cr = c->enclosingclass;
780 cn = c->enclosingmethod;
782 /* check for enclosing class and method */
790 /* resolve the class if necessary */
792 if (IS_CLASSREF(cr)) {
793 ec = resolve_classref_eager(cr.ref);
801 /* find method in enclosing class */
803 m = class_findmethod(ec, cn->name, cn->descriptor);
806 exceptions_throw_internalerror("Enclosing method doesn't exist");
815 * Class: java/lang/Class
816 * Method: getEnclosingConstructor
817 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
819 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
823 java_lang_reflect_Constructor *rc;
825 c = (classinfo *) klass;
827 /* get enclosing method */
829 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
834 /* check for <init> */
836 if (m->name != utf_init)
839 /* create Constructor object */
841 rc = reflect_constructor_new(m);
848 * Class: java/lang/Class
849 * Method: getEnclosingMethod
850 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
852 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
856 java_lang_reflect_Method *rm;
858 c = (classinfo *) klass;
860 /* get enclosing method */
862 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
867 /* check for <init> */
869 if (m->name == utf_init)
872 /* create java.lang.reflect.Method object */
874 rm = reflect_method_new(m);
881 * Class: java/lang/Class
882 * Method: getClassSignature
883 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
885 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
890 c = (classinfo *) klass;
892 if (c->signature == NULL)
895 o = javastring_new(c->signature);
897 /* in error case o is NULL */
899 return (java_lang_String *) o;
905 * Class: java/lang/Class
906 * Method: isAnonymousClass
907 * Signature: (Ljava/lang/Class;)Z
909 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
913 * Class: java/lang/VMClass
914 * Method: isLocalClass
915 * Signature: (Ljava/lang/Class;)Z
917 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
921 * Class: java/lang/VMClass
922 * Method: isMemberClass
923 * Signature: (Ljava/lang/Class;)Z
925 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
928 #endif /* ENABLE_JAVASE */
932 * These are local overrides for various environment variables in Emacs.
933 * Please do not remove this and leave it at the end of the file, where
934 * Emacs will automagically detect them.
935 * ---------------------------------------------------------------------
938 * indent-tabs-mode: t
942 * vim:noexpandtab:sw=4:ts=4: