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 8305 2007-08-15 13:49:26Z panzi $
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);
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)
306 java_objectarray *oa;
309 c = (classinfo *) klass;
311 if (!(c->state & CLASS_LINKED))
315 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
320 for (i = 0; i < c->interfacescount; i++) {
321 ic = c->interfaces[i].cls;
331 * Class: java/lang/Class
332 * Method: getComponentType
333 * Signature: ()Ljava/lang/Class;
335 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
339 arraydescriptor *desc;
341 c = (classinfo *) klass;
343 /* XXX maybe we could find a way to do this without linking. */
344 /* This way should be safe and easy, however. */
346 if (!(c->state & CLASS_LINKED))
350 desc = c->vftbl->arraydesc;
355 if (desc->arraytype == ARRAYTYPE_OBJECT)
356 comp = desc->componentvftbl->class;
358 comp = primitive_class_get_by_type(desc->arraytype);
360 return (java_lang_Class *) comp;
365 * Class: java/lang/Class
366 * Method: getModifiers
369 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
372 classref_or_classinfo inner;
373 classref_or_classinfo outer;
377 c = (classinfo *) klass;
379 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
380 /* search for passed class as inner class */
382 for (i = 0; i < c->innerclasscount; i++) {
383 inner = c->innerclass[i].inner_class;
384 outer = c->innerclass[i].outer_class;
386 /* Check if inner is a classref or a real class and get
387 the name of the structure */
389 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
391 /* innerclass is this class */
393 if (innername == c->name) {
394 /* has the class actually an outer class? */
397 /* return flags got from the outer class file */
398 return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
400 return c->flags & ACC_CLASS_REFLECT_MASK;
405 /* passed class is no inner class or it was not requested */
407 return c->flags & ACC_CLASS_REFLECT_MASK;
412 * Class: java/lang/Class
413 * Method: getDeclaringClass
414 * Signature: ()Ljava/lang/Class;
416 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
420 c = (classinfo *) klass;
422 return (java_lang_Class *) class_get_declaringclass(c);
427 * Class: java/lang/Class
428 * Method: getDeclaredClasses
429 * Signature: (Z)[Ljava/lang/Class;
431 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
434 classref_or_classinfo outer;
436 s4 declaredclasscount; /* number of declared classes */
437 s4 pos; /* current declared class */
438 java_objectarray *oa; /* array of declared classes */
441 c = (classinfo *) klass;
442 declaredclasscount = 0;
444 if (!class_is_primitive(c) && (c->name->text[0] != '[')) {
445 /* determine number of declared classes */
447 for (i = 0; i < c->innerclasscount; i++) {
448 outer = c->innerclass[i].outer_class;
450 /* check if outer_class is a classref or a real class and
451 get the class name from the structure */
453 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
455 /* outer class is this class */
457 if ((outername == c->name) &&
458 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
459 declaredclasscount++;
463 /* allocate Class[] and check for OOM */
465 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
470 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
471 outer = c->innerclass[i].outer_class;
473 /* check if outer_class is a classref or a real class and
474 get the class name from the structure */
476 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
478 /* outer class is this class */
480 if ((outername == c->name) &&
481 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
484 if ((inner = resolve_classref_or_classinfo_eager(
485 c->innerclass[i].inner_class,
489 if (!(inner->state & CLASS_LINKED))
490 if (!link_class(inner))
493 oa->data[pos++] = inner;
502 * Class: java/lang/Class
503 * Method: getDeclaredFields
504 * Signature: (Z)[Ljava/lang/reflect/Field;
506 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
509 java_objectarray *oa; /* result: array of field-objects */
511 java_lang_reflect_Field *rf;
512 s4 public_fields; /* number of elements in field-array */
516 c = (classinfo *) klass;
518 /* determine number of fields */
520 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
521 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
524 /* create array of fields */
526 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
531 /* get the fields and store in the array */
533 for (i = 0, pos = 0; i < c->fieldscount; i++) {
536 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
537 /* create Field object */
539 rf = reflect_field_new(f);
541 /* store object into array */
543 oa->data[pos++] = rf;
552 * Class: java/lang/Class
553 * Method: getDeclaredMethods
554 * Signature: (Z)[Ljava/lang/reflect/Method;
556 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
559 java_lang_reflect_Method *rm;
560 java_objectarray *oa; /* result: array of Method-objects */
561 methodinfo *m; /* the current method to be represented */
562 s4 public_methods; /* number of public methods of the class */
566 c = (classinfo *) klass;
570 /* JOWENN: array classes do not declare methods according to mauve
571 test. It should be considered, if we should return to my old
572 clone method overriding instead of declaring it as a member
575 if (class_is_array(c))
576 return builtin_anewarray(0, class_java_lang_reflect_Method);
578 /* determine number of methods */
580 for (i = 0; i < c->methodscount; i++) {
583 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
584 ((m->name != utf_init) && (m->name != utf_clinit)) &&
585 !(m->flags & ACC_MIRANDA))
589 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
594 for (i = 0, pos = 0; i < c->methodscount; i++) {
597 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
598 ((m->name != utf_init) && (m->name != utf_clinit)) &&
599 !(m->flags & ACC_MIRANDA)) {
600 /* create Method object */
602 rm = reflect_method_new(m);
604 /* store object into array */
606 oa->data[pos++] = rm;
615 * Class: java/lang/Class
616 * Method: getDeclaredConstructors
617 * Signature: (Z)[Ljava/lang/reflect/Constructor;
619 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
622 methodinfo *m; /* the current method to be represented */
623 java_objectarray *oa; /* result: array of Method-objects */
624 java_lang_reflect_Constructor *rc;
625 s4 public_methods; /* number of public methods of the class */
629 c = (classinfo *) klass;
631 /* determine number of constructors */
633 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
636 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
637 (m->name == utf_init))
641 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
646 for (i = 0, pos = 0; i < c->methodscount; i++) {
649 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
650 (m->name == utf_init)) {
651 /* create Constructor object */
653 rc = reflect_constructor_new(m);
655 /* store object into array */
657 oa->data[pos++] = rc;
666 * Class: java/lang/Class
667 * Method: getClassLoader
668 * Signature: ()Ljava/lang/ClassLoader;
670 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
674 c = (classinfo *) klass;
676 return (java_lang_ClassLoader *) c->classloader;
679 #endif /* defined(ENABLE_JAVASE) */
683 * Class: java/lang/Class
687 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
691 c = (classinfo *) this;
693 return class_is_array(c);
697 #if defined(ENABLE_JAVASE)
700 * Class: java/lang/Class
701 * Method: throwException
702 * Signature: (Ljava/lang/Throwable;)V
704 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
708 o = (java_handle_t *) t;
710 exceptions_set_exception(o);
714 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
716 * Class: java/lang/Class
717 * Method: getDeclaredAnnotations
718 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
720 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
722 classinfo *c = (classinfo*)klass;
723 static methodinfo *m_parseAnnotationsIntoArray = NULL;
724 utf *utf_parseAnnotationsIntoArray = NULL;
725 utf *utf_desc = NULL;
726 java_bytearray *annotations = NULL;
727 sun_reflect_ConstantPool *constantPool = NULL;
729 java_lang_Object *o = (java_lang_Object*)klass;
732 exceptions_throw_nullpointerexception();
736 /* Return null for arrays and primitives: */
737 if (class_is_primitive(c) || class_is_array(c)) {
741 if (c->annotations != NULL) {
742 size = c->annotations->size;
743 annotations = builtin_newarray_byte(size);
745 if(annotations != NULL) {
746 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
751 (sun_reflect_ConstantPool*)native_new_and_init(
752 class_sun_reflect_ConstantPool);
754 if(constantPool == NULL) {
759 LLNI_field_set_ref(constantPool, constantPoolOop, o);
761 /* only resolve the method the first time */
762 if (m_parseAnnotationsIntoArray == NULL) {
763 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
764 utf_desc = utf_new_char(
765 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
766 "[Ljava/lang/annotation/Annotation;");
768 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
773 m_parseAnnotationsIntoArray = class_resolveclassmethod(
774 class_sun_reflect_annotation_AnnotationParser,
775 utf_parseAnnotationsIntoArray,
777 class_java_lang_Class,
780 if (m_parseAnnotationsIntoArray == NULL) {
781 /* method not found */
786 return vm_call_method(
787 m_parseAnnotationsIntoArray, NULL,
788 annotations, constantPool, klass);
794 * Class: java/lang/Class
795 * Method: getEnclosingClass
796 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
798 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
801 classref_or_classinfo cr;
804 c = (classinfo *) klass;
806 /* get enclosing class */
808 cr = c->enclosingclass;
813 /* resolve the class if necessary */
815 if (IS_CLASSREF(cr)) {
816 ec = resolve_classref_eager(cr.ref);
824 return (java_lang_Class *) ec;
828 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
830 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
831 _Jv_java_lang_Class_getEnclosingMethod.
833 *******************************************************************************/
835 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
837 classref_or_classinfo cr;
838 constant_nameandtype *cn;
842 /* get enclosing class and method */
844 cr = c->enclosingclass;
845 cn = c->enclosingmethod;
847 /* check for enclosing class and method */
855 /* resolve the class if necessary */
857 if (IS_CLASSREF(cr)) {
858 ec = resolve_classref_eager(cr.ref);
866 /* find method in enclosing class */
868 m = class_findmethod(ec, cn->name, cn->descriptor);
871 exceptions_throw_internalerror("Enclosing method doesn't exist");
880 * Class: java/lang/Class
881 * Method: getEnclosingConstructor
882 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
884 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
888 java_lang_reflect_Constructor *rc;
890 c = (classinfo *) klass;
892 /* get enclosing method */
894 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
899 /* check for <init> */
901 if (m->name != utf_init)
904 /* create Constructor object */
906 rc = reflect_constructor_new(m);
913 * Class: java/lang/Class
914 * Method: getEnclosingMethod
915 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
917 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
921 java_lang_reflect_Method *rm;
923 c = (classinfo *) klass;
925 /* get enclosing method */
927 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
932 /* check for <init> */
934 if (m->name == utf_init)
937 /* create java.lang.reflect.Method object */
939 rm = reflect_method_new(m);
946 * Class: java/lang/Class
947 * Method: getClassSignature
948 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
950 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
955 c = (classinfo *) klass;
957 if (c->signature == NULL)
960 o = javastring_new(c->signature);
962 /* in error case o is NULL */
964 return (java_lang_String *) o;
970 * Class: java/lang/Class
971 * Method: isAnonymousClass
972 * Signature: (Ljava/lang/Class;)Z
974 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
978 * Class: java/lang/VMClass
979 * Method: isLocalClass
980 * Signature: (Ljava/lang/Class;)Z
982 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
986 * Class: java/lang/VMClass
987 * Method: isMemberClass
988 * Signature: (Ljava/lang/Class;)Z
990 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
993 #endif /* ENABLE_JAVASE */
997 * These are local overrides for various environment variables in Emacs.
998 * Please do not remove this and leave it at the end of the file, where
999 * Emacs will automagically detect them.
1000 * ---------------------------------------------------------------------
1003 * indent-tabs-mode: t
1007 * vim:noexpandtab:sw=4:ts=4: