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 8311 2007-08-15 17:03:40Z 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)
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)
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 < ca->header.size; i++) {
116 if (ca->data[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 = (classloader *) 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_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
306 java_objectarray *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_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
420 java_objectarray *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_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
438 java_objectarray *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 oa->data[pos++] = rf;
481 * Class: java/lang/Class
482 * Method: getDeclaredMethods
483 * Signature: (Z)[Ljava/lang/reflect/Method;
485 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
488 java_lang_reflect_Method *rm;
489 java_objectarray *oa; /* result: array of Method-objects */
490 methodinfo *m; /* the current method to be represented */
491 s4 public_methods; /* number of public methods of the class */
495 c = (classinfo *) klass;
499 /* JOWENN: array classes do not declare methods according to mauve
500 test. It should be considered, if we should return to my old
501 clone method overriding instead of declaring it as a member
504 if (class_is_array(c))
505 return builtin_anewarray(0, class_java_lang_reflect_Method);
507 /* determine number of methods */
509 for (i = 0; i < c->methodscount; i++) {
512 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
513 ((m->name != utf_init) && (m->name != utf_clinit)) &&
514 !(m->flags & ACC_MIRANDA))
518 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
523 for (i = 0, pos = 0; i < c->methodscount; i++) {
526 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
527 ((m->name != utf_init) && (m->name != utf_clinit)) &&
528 !(m->flags & ACC_MIRANDA)) {
529 /* create Method object */
531 rm = reflect_method_new(m);
533 /* store object into array */
535 oa->data[pos++] = rm;
544 * Class: java/lang/Class
545 * Method: getDeclaredConstructors
546 * Signature: (Z)[Ljava/lang/reflect/Constructor;
548 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
551 methodinfo *m; /* the current method to be represented */
552 java_objectarray *oa; /* result: array of Method-objects */
553 java_lang_reflect_Constructor *rc;
554 s4 public_methods; /* number of public methods of the class */
558 c = (classinfo *) klass;
560 /* determine number of constructors */
562 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
565 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
566 (m->name == utf_init))
570 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
575 for (i = 0, pos = 0; i < c->methodscount; i++) {
578 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
579 (m->name == utf_init)) {
580 /* create Constructor object */
582 rc = reflect_constructor_new(m);
584 /* store object into array */
586 oa->data[pos++] = rc;
595 * Class: java/lang/Class
596 * Method: getClassLoader
597 * Signature: ()Ljava/lang/ClassLoader;
599 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
603 c = (classinfo *) klass;
605 return (java_lang_ClassLoader *) c->classloader;
608 #endif /* defined(ENABLE_JAVASE) */
612 * Class: java/lang/Class
616 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
620 c = (classinfo *) this;
622 return class_is_array(c);
626 #if defined(ENABLE_JAVASE)
629 * Class: java/lang/Class
630 * Method: throwException
631 * Signature: (Ljava/lang/Throwable;)V
633 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
637 o = (java_handle_t *) t;
639 exceptions_set_exception(o);
643 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
645 * Class: java/lang/Class
646 * Method: getDeclaredAnnotations
647 * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
649 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
651 classinfo *c = (classinfo*)klass;
652 static methodinfo *m_parseAnnotationsIntoArray = NULL;
653 utf *utf_parseAnnotationsIntoArray = NULL;
654 utf *utf_desc = NULL;
655 java_bytearray *annotations = NULL;
656 sun_reflect_ConstantPool *constantPool = NULL;
658 java_lang_Object *constantPoolOop = (java_lang_Object*)klass;
661 exceptions_throw_nullpointerexception();
665 /* Return null for arrays and primitives: */
666 if (class_is_primitive(c) || class_is_array(c)) {
670 if (c->annotations != NULL) {
671 size = c->annotations->size;
672 annotations = builtin_newarray_byte(size);
674 if(annotations != NULL) {
675 MCOPY(annotations->data, c->annotations->data, uint8_t, size);
680 (sun_reflect_ConstantPool*)native_new_and_init(
681 class_sun_reflect_ConstantPool);
683 if(constantPool == NULL) {
688 LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
690 /* only resolve the method the first time */
691 if (m_parseAnnotationsIntoArray == NULL) {
692 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
693 utf_desc = utf_new_char(
694 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
695 "[Ljava/lang/annotation/Annotation;");
697 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
702 m_parseAnnotationsIntoArray = class_resolveclassmethod(
703 class_sun_reflect_annotation_AnnotationParser,
704 utf_parseAnnotationsIntoArray,
706 class_java_lang_Class,
709 if (m_parseAnnotationsIntoArray == NULL) {
710 /* method not found */
715 return (java_objectarray*)vm_call_method(
716 m_parseAnnotationsIntoArray, NULL,
717 annotations, constantPool, klass);
723 * Class: java/lang/Class
724 * Method: getEnclosingClass
725 * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
727 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
730 classref_or_classinfo cr;
733 c = (classinfo *) klass;
735 /* get enclosing class */
737 cr = c->enclosingclass;
742 /* resolve the class if necessary */
744 if (IS_CLASSREF(cr)) {
745 ec = resolve_classref_eager(cr.ref);
753 return (java_lang_Class *) ec;
757 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
759 Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
760 _Jv_java_lang_Class_getEnclosingMethod.
762 *******************************************************************************/
764 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
766 classref_or_classinfo cr;
767 constant_nameandtype *cn;
771 /* get enclosing class and method */
773 cr = c->enclosingclass;
774 cn = c->enclosingmethod;
776 /* check for enclosing class and method */
784 /* resolve the class if necessary */
786 if (IS_CLASSREF(cr)) {
787 ec = resolve_classref_eager(cr.ref);
795 /* find method in enclosing class */
797 m = class_findmethod(ec, cn->name, cn->descriptor);
800 exceptions_throw_internalerror("Enclosing method doesn't exist");
809 * Class: java/lang/Class
810 * Method: getEnclosingConstructor
811 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
813 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
817 java_lang_reflect_Constructor *rc;
819 c = (classinfo *) klass;
821 /* get enclosing method */
823 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
828 /* check for <init> */
830 if (m->name != utf_init)
833 /* create Constructor object */
835 rc = reflect_constructor_new(m);
842 * Class: java/lang/Class
843 * Method: getEnclosingMethod
844 * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
846 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
850 java_lang_reflect_Method *rm;
852 c = (classinfo *) klass;
854 /* get enclosing method */
856 m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
861 /* check for <init> */
863 if (m->name == utf_init)
866 /* create java.lang.reflect.Method object */
868 rm = reflect_method_new(m);
875 * Class: java/lang/Class
876 * Method: getClassSignature
877 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
879 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
884 c = (classinfo *) klass;
886 if (c->signature == NULL)
889 o = javastring_new(c->signature);
891 /* in error case o is NULL */
893 return (java_lang_String *) o;
899 * Class: java/lang/Class
900 * Method: isAnonymousClass
901 * Signature: (Ljava/lang/Class;)Z
903 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
907 * Class: java/lang/VMClass
908 * Method: isLocalClass
909 * Signature: (Ljava/lang/Class;)Z
911 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
915 * Class: java/lang/VMClass
916 * Method: isMemberClass
917 * Signature: (Ljava/lang/Class;)Z
919 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
922 #endif /* ENABLE_JAVASE */
926 * These are local overrides for various environment variables in Emacs.
927 * Please do not remove this and leave it at the end of the file, where
928 * Emacs will automagically detect them.
929 * ---------------------------------------------------------------------
932 * indent-tabs-mode: t
936 * vim:noexpandtab:sw=4:ts=4: