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 8288 2007-08-10 15:12:00Z 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)
135 java_objectheader *cl;
143 #if defined(ENABLE_JAVASE)
144 cl = (java_objectheader *) loader;
147 /* illegal argument */
150 exceptions_throw_nullpointerexception();
154 /* create utf string in which '.' is replaced by '/' */
156 ufile = javastring_toutf((java_objectheader *) name, true);
157 uname = javastring_toutf((java_objectheader *) 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)
204 java_objectheader *ob;
206 c = (classinfo *) klass;
207 ob = (java_objectheader *) 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;
323 oa->data[i] = (java_objectheader *) ic;
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++] = (java_objectheader *) 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++] = (java_objectheader *) 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++] = (java_objectheader *) 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++] = (java_objectheader *) 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)
706 java_objectheader *o;
708 o = (java_objectheader *) 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;
731 exceptions_throw_nullpointerexception();
735 /* Return null for arrays and primitives: */
736 if (class_is_primitive(c) || class_is_array(c)) {
740 if (c->annotations != NULL) {
741 size = c->annotations->size;
742 annotations = builtin_newarray_byte(size);
744 if(annotations != NULL) {
745 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
750 (sun_reflect_ConstantPool*)native_new_and_init(
751 class_sun_reflect_ConstantPool);
753 if(constantPool == NULL) {
758 constantPool->constantPoolOop = (java_lang_Object*)klass;
760 /* only resolve the method the first time */
761 if (m_parseAnnotationsIntoArray == NULL) {
762 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
763 utf_desc = utf_new_char(
764 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
765 "[Ljava/lang/annotation/Annotation;");
767 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
772 m_parseAnnotationsIntoArray = class_resolveclassmethod(
773 class_sun_reflect_annotation_AnnotationParser,
774 utf_parseAnnotationsIntoArray,
776 class_java_lang_Class,
779 if (m_parseAnnotationsIntoArray == NULL) {
780 /* method not found */
785 return vm_call_method(
786 m_parseAnnotationsIntoArray, NULL,
787 annotations, constantPool, klass);
793 * Class: java/lang/Class
794 * Method: getEnclosingClass
795 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
797 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
800 classref_or_classinfo cr;
803 c = (classinfo *) klass;
805 /* get enclosing class */
807 cr = c->enclosingclass;
812 /* resolve the class if necessary */
814 if (IS_CLASSREF(cr)) {
815 ec = resolve_classref_eager(cr.ref);
823 return (java_lang_Class *) ec;
827 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
829 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
830 _Jv_java_lang_Class_getEnclosingMethod.
832 *******************************************************************************/
834 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
836 classref_or_classinfo cr;
837 constant_nameandtype *cn;
841 /* get enclosing class and method */
843 cr = c->enclosingclass;
844 cn = c->enclosingmethod;
846 /* check for enclosing class and method */
854 /* resolve the class if necessary */
856 if (IS_CLASSREF(cr)) {
857 ec = resolve_classref_eager(cr.ref);
865 /* find method in enclosing class */
867 m = class_findmethod(ec, cn->name, cn->descriptor);
870 exceptions_throw_internalerror("Enclosing method doesn't exist");
879 * Class: java/lang/Class
880 * Method: getEnclosingConstructor
881 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
883 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
887 java_lang_reflect_Constructor *rc;
889 c = (classinfo *) klass;
891 /* get enclosing method */
893 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
898 /* check for <init> */
900 if (m->name != utf_init)
903 /* create Constructor object */
905 rc = reflect_constructor_new(m);
912 * Class: java/lang/Class
913 * Method: getEnclosingMethod
914 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
916 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
920 java_lang_reflect_Method *rm;
922 c = (classinfo *) klass;
924 /* get enclosing method */
926 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
931 /* check for <init> */
933 if (m->name == utf_init)
936 /* create java.lang.reflect.Method object */
938 rm = reflect_method_new(m);
945 * Class: java/lang/Class
946 * Method: getClassSignature
947 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
949 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
952 java_objectheader *o;
954 c = (classinfo *) klass;
956 if (c->signature == NULL)
959 o = javastring_new(c->signature);
961 /* in error case o is NULL */
963 return (java_lang_String *) o;
969 * Class: java/lang/Class
970 * Method: isAnonymousClass
971 * Signature: (Ljava/lang/Class;)Z
973 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
977 * Class: java/lang/VMClass
978 * Method: isLocalClass
979 * Signature: (Ljava/lang/Class;)Z
981 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
985 * Class: java/lang/VMClass
986 * Method: isMemberClass
987 * Signature: (Ljava/lang/Class;)Z
989 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
992 #endif /* ENABLE_JAVASE */
996 * These are local overrides for various environment variables in Emacs.
997 * Please do not remove this and leave it at the end of the file, where
998 * Emacs will automagically detect them.
999 * ---------------------------------------------------------------------
1002 * indent-tabs-mode: t
1006 * vim:noexpandtab:sw=4:ts=4: