1 /* src/native/vm/VMClass.c - java/lang/VMClass
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Roman Obermaiser
29 Changes: Joseph Wenninger
32 $Id: VMClass.c 2655 2005-06-13 14:12:34Z twisti $
40 #include "mm/memory.h"
41 #include "native/jni.h"
42 #include "native/native.h"
43 #include "native/include/java_lang_Class.h"
44 #include "native/include/java_lang_ClassLoader.h"
45 #include "native/include/java_lang_Object.h"
46 #include "native/include/java_lang_VMClass.h"
47 #include "native/include/java_lang_reflect_Constructor.h"
48 #include "native/include/java_lang_reflect_Field.h"
49 #include "native/include/java_lang_reflect_Method.h"
50 #include "native/include/java_security_ProtectionDomain.h"
51 #include "toolbox/logging.h"
52 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/initialize.h"
56 #include "vm/loader.h"
57 #include "vm/stringlocal.h"
58 #include "vm/tables.h"
59 #include "vm/resolve.h"
62 /* for selecting public members */
63 #define MEMBER_PUBLIC 0
67 * Class: java/lang/VMClass
69 * Signature: (Ljava/lang/String;)Ljava/lang/Class;
71 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *s)
75 /* XXX TWISTI: we currently use the classpath default implementation, maybe
76 we change this someday to a faster native version */
81 /* illegal argument */
86 /* create utf string in which '.' is replaced by '/' */
88 u = javastring_toutf(s, true);
90 /* try to load, ... */
92 if (!(c = load_class_bootstrap(u))) {
95 xclass = (*exceptionptr)->vftbl->class;
97 /* if the exception is a NoClassDefFoundError, we replace it with a
98 ClassNotFoundException, otherwise return the exception */
100 if (xclass == class_java_lang_NoClassDefFoundError) {
101 /* clear exceptionptr, because builtin_new checks for
102 ExceptionInInitializerError */
103 *exceptionptr = NULL;
106 new_exception_javastring(string_java_lang_ClassNotFoundException, s);
117 /* ...and initialize it */
122 use_class_as_object(c);
124 return (java_lang_Class *) c;
130 * Class: java/lang/VMClass
131 * Method: getClassLoader
132 * Signature: ()Ljava/lang/ClassLoader;
134 JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *that)
136 return (java_lang_ClassLoader *) ((classinfo *) that)->classloader;
141 * Class: java/lang/VMClass
142 * Method: getComponentType
143 * Signature: ()Ljava/lang/Class;
145 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, java_lang_Class *that)
147 classinfo *thisclass = (classinfo *) that;
149 arraydescriptor *desc;
151 if ((desc = thisclass->vftbl->arraydesc) != NULL) {
152 if (desc->arraytype == ARRAYTYPE_OBJECT)
153 c = desc->componentvftbl->class;
155 c = primitivetype_table[desc->arraytype].class_primitive;
158 use_class_as_object(c);
161 return (java_lang_Class *) c;
166 * Class: java/lang/VMClass
167 * Method: getDeclaredConstructors
168 * Signature: (Z)[Ljava/lang/reflect/Constructor;
170 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 public_only)
174 java_objectheader *o;
175 java_objectarray *array_constructor; /* result: array of Method-objects */
176 java_objectarray *exceptiontypes; /* the exceptions thrown by the method */
177 methodinfo *m; /* the current method to be represented */
178 int public_methods = 0; /* number of public methods of the class */
182 c = (classinfo *) that;
184 /* determine number of constructors */
186 for (i = 0; i < c->methodscount; i++)
187 if (((c->methods[i].flags & ACC_PUBLIC) || !public_only) &&
188 (c->methods[i].name == utf_init))
192 builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
194 if (!array_constructor)
197 for (i = 0; i < c->methodscount; i++) {
198 if ((c->methods[i].flags & ACC_PUBLIC) || !public_only){
200 if (m->name != utf_init)
203 o = native_new_and_init(class_java_lang_reflect_Constructor);
204 array_constructor->data[pos++] = o;
206 /* array of exceptions declared to be thrown, information not available !! */
207 exceptiontypes = builtin_anewarray(0, class_java_lang_Class);
209 /* class_showconstantpool(class_constructor);*/
210 /* initialize instance fields */
211 /* ((java_lang_reflect_Constructor*)o)->flag=(m->flags & (ACC_PRIVATE | ACC_PUBLIC | ACC_PROTECTED));*/
213 setfield_critical(class_java_lang_reflect_Constructor,
218 (jobject) c /*this*/);
220 setfield_critical(class_java_lang_reflect_Constructor,
227 /* setfield_critical(class_constructor,o,"flag", "I", jint, (m->flags & (ACC_PRIVATE |
228 ACC_PUBLIC | ACC_PROTECTED))); */
230 setfield_critical(class_java_lang_reflect_Constructor,
233 "[Ljava/lang/Class;",
235 (jobject) exceptiontypes);
237 setfield_critical(class_java_lang_reflect_Constructor,
240 "[Ljava/lang/Class;",
242 (jobject) get_parametertypes(m));
246 return array_constructor;
251 * Class: java/lang/VMClass
252 * Method: getDeclaredClasses
253 * Signature: (Z)[Ljava/lang/Class;
255 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 publicOnly)
257 /* XXX fix the public only case */
259 classinfo *c = (classinfo *) that;
260 int pos = 0; /* current declared class */
261 int declaredclasscount = 0; /* number of declared classes */
262 java_objectarray *result; /* array of declared classes */
263 int notPublicOnly = !publicOnly;
269 /*printf("PublicOnly: %d\n",publicOnly);*/
270 if (!Java_java_lang_VMClass_isPrimitive(env, clazz, (java_lang_Class *) c) && (c->name->text[0] != '[')) {
271 /* determine number of declared classes */
272 for (i = 0; i < c->innerclasscount; i++) {
273 if ( (c->innerclass[i].outer_class.cls == c) && (notPublicOnly || (c->innerclass[i].flags & ACC_PUBLIC)))
274 /* outer class is this class */
275 declaredclasscount++;
279 /*class_showmethods(c); */
281 result = builtin_anewarray(declaredclasscount, class_java_lang_Class);
283 for (i = 0; i < c->innerclasscount; i++) {
287 if (!resolve_classref_or_classinfo(NULL,c->innerclass[i].inner_class,resolveEager,false,&inner))
289 if (!resolve_classref_or_classinfo(NULL,c->innerclass[i].outer_class,resolveEager,false,&inner))
292 if ((outer == c) && (notPublicOnly || (inner->flags & ACC_PUBLIC))) {
293 /* outer class is this class, store innerclass in array */
294 use_class_as_object(inner);
295 result->data[pos++] = (java_objectheader *) inner;
304 * Class: java/lang/VMClass
305 * Method: getDeclaringClass
306 * Signature: ()Ljava/lang/Class;
308 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, struct java_lang_Class *that)
312 classinfo *c = (classinfo *) that;
314 if (that && !Java_java_lang_VMClass_isPrimitive(env, clazz,that) && (c->name->text[0] != '[')) {
317 if (c->innerclasscount == 0) /* no innerclasses exist */
320 for (i = 0; i < c->innerclasscount; i++) {
321 classinfo *inner = c->innerclass[i].inner_class.cls;
322 classinfo *outer = c->innerclass[i].outer_class.cls;
325 /* innerclass is this class */
326 use_class_as_object(outer);
327 return (java_lang_Class *) outer;
332 /* return NULL for arrayclasses and primitive classes */
337 java_lang_reflect_Field* cacao_getField0(JNIEnv *env, java_lang_Class *that, java_lang_String *name, s4 public_only)
340 fieldinfo *f; /* the field to be represented */
341 java_lang_reflect_Field *o; /* result: field-object */
344 c = (classinfo *) that;
346 /* create Field object */
348 o = (java_lang_reflect_Field *)
349 native_new_and_init(class_java_lang_reflect_Field);
351 /* get fieldinfo entry */
353 idx = class_findfield_index_approx(c, javastring_toutf(name, false));
356 *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
360 f = &(c->fields[idx]);
363 if (public_only && !(f->flags & ACC_PUBLIC)) {
364 /* field is not public and public only had been requested*/
366 new_exception(string_java_lang_NoSuchFieldException);
370 /* initialize instance fields */
372 setfield_critical(class_java_lang_reflect_Field,
377 (jobject) that /*this*/);
379 /* ((java_lang_reflect_Field*)(o))->flag=f->flags;*/
380 /* save type in slot-field for faster processing */
381 /* setfield_critical(c,o,"flag", "I", jint, (jint) f->flags); */
382 /*o->flag = f->flags;*/
384 setfield_critical(class_java_lang_reflect_Field,
391 setfield_critical(class_java_lang_reflect_Field,
394 "Ljava/lang/String;",
398 /*setfield_critical(c,o,"type", "Ljava/lang/Class;", jclass, fieldtype);*/
408 * Class: java/lang/VMClass
409 * Method: getDeclaredFields
410 * Signature: (Z)[Ljava/lang/reflect/Field;
412 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 public_only)
415 java_objectarray *array_field; /* result: array of field-objects */
417 int public_fields = 0; /* number of elements in field-array */
421 c = (classinfo *) that;
423 /* determine number of fields */
425 for (i = 0; i < c->fieldscount; i++)
426 if ((c->fields[i].flags & ACC_PUBLIC) || (!public_only))
429 /* create array of fields */
432 builtin_anewarray(public_fields, class_java_lang_reflect_Field);
434 /* creation of array failed */
439 /* get the fields and store in the array */
441 for (i = 0; i < c->fieldscount; i++) {
442 if ((c->fields[i].flags & ACC_PUBLIC) || (!public_only)) {
443 s = (java_lang_String *) javastring_new(c->fields[i].name);
445 array_field->data[pos++] = (java_objectheader *)
446 cacao_getField0(env, that, s, public_only);
455 * Class: java/lang/VMClass
456 * Method: getInterfaces
457 * Signature: ()[Ljava/lang/Class;
459 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *that)
461 classinfo *c = (classinfo *) that;
465 a = builtin_anewarray(c->interfacescount, class_java_lang_Class);
470 for (i = 0; i < c->interfacescount; i++) {
471 use_class_as_object(c->interfaces[i].cls);
473 a->data[i] = (java_objectheader *) c->interfaces[i].cls;
480 java_lang_reflect_Method* cacao_getMethod0(JNIEnv *env, java_lang_Class *that, java_lang_String *name, java_objectarray *types, s4 which)
483 java_lang_reflect_Method* o; /* result: Method-object */
484 java_objectarray *exceptiontypes; /* the exceptions thrown by the method */
485 methodinfo *m; /* the method to be represented */
487 clazz = (classinfo *) that;
489 o = (java_lang_reflect_Method *)
490 native_new_and_init(class_java_lang_reflect_Method);
492 /* find the method */
494 m = class_resolvemethod_approx(clazz,
495 javastring_toutf(name, false),
496 create_methodsig(types, 0));
498 if (!m || (which == MEMBER_PUBLIC && !(m->flags & ACC_PUBLIC))) {
499 /* no apropriate method was found */
500 *exceptionptr = new_exception(string_java_lang_NoSuchMethodException);
504 /* array of exceptions declared to be thrown, information not available! */
506 exceptiontypes = builtin_anewarray(0, class_java_lang_Class);
508 /* initialize instance fields */
510 setfield_critical(class_java_lang_reflect_Method,
515 (jobject) clazz /*this*/);
517 setfield_critical(class_java_lang_reflect_Method,
520 "[Ljava/lang/Class;",
524 setfield_critical(class_java_lang_reflect_Method,
527 "[Ljava/lang/Class;",
529 (jobject) exceptiontypes);
531 setfield_critical(class_java_lang_reflect_Method,
534 "Ljava/lang/String;",
536 (jobject) javastring_new(m->name));
538 setfield_critical(class_java_lang_reflect_Method,
545 setfield_critical(class_java_lang_reflect_Method,
552 setfield_critical(class_java_lang_reflect_Method,
564 * Class: java/lang/VMClass
565 * Method: getDeclaredMethods
566 * Signature: (Z)[Ljava/lang/reflect/Method;
568 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 public_only)
571 java_objectheader *o;
572 java_objectarray *array_method; /* result: array of Method-objects */
573 java_objectarray *exceptiontypes; /* the exceptions thrown by the method */
574 methodinfo *m; /* the current method to be represented */
575 int public_methods = 0; /* number of public methods of the class */
579 c = (classinfo *) that;
581 /* JOWENN: array classes do not declare methods according to mauve test. */
582 /* It should be considered, if we should return to my old clone method */
583 /* overriding instead of declaring it as a member function. */
585 if (Java_java_lang_VMClass_isArray(env, clazz, that))
586 return builtin_anewarray(0, class_java_lang_reflect_Method);
588 /* determine number of methods */
590 for (i = 0; i < c->methodscount; i++)
591 if ((((c->methods[i].flags & ACC_PUBLIC)) || (!public_only)) &&
593 ((c->methods[i].name == utf_init) ||
594 (c->methods[i].name == utf_clinit))
599 class_showmethods(class_method);
605 builtin_anewarray(public_methods, class_java_lang_reflect_Method);
610 for (i = 0; i < c->methodscount; i++) {
611 if (((c->methods[i].flags & ACC_PUBLIC) || (!public_only)) &&
613 ((c->methods[i].name == utf_init) ||
614 (c->methods[i].name == utf_clinit))
618 o = native_new_and_init(class_java_lang_reflect_Method);
619 array_method->data[pos++] = o;
621 /* array of exceptions declared to be thrown, information not available !! */
622 exceptiontypes = builtin_anewarray(0, class_java_lang_Class);
625 /* initialize instance fields */
626 /* ((java_lang_reflect_Method*)o)->flag=(m->flags &
627 (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_ABSTRACT | ACC_STATIC | ACC_FINAL |
628 ACC_SYNCHRONIZED | ACC_NATIVE | ACC_STRICT)
631 setfield_critical(class_java_lang_reflect_Method,
636 (jobject) c /*this*/);
638 setfield_critical(class_java_lang_reflect_Method,
641 "Ljava/lang/String;",
643 (jobject) javastring_new(m->name));
645 /* setfield_critical(class_method,o,"flag", "I", jint, (m->flags &
646 (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_ABSTRACT | ACC_STATIC | ACC_FINAL |
647 ACC_SYNCHRONIZED | ACC_NATIVE | ACC_STRICT)));*/
649 setfield_critical(class_java_lang_reflect_Method,
656 /* setfield_critical(class_method,o,"returnType", "Ljava/lang/Class;", jclass, get_returntype(m));
657 setfield_critical(class_method,o,"exceptionTypes", "[Ljava/lang/Class;", jobject, (jobject) exceptiontypes);
658 setfield_critical(class_method,o,"parameterTypes", "[Ljava/lang/Class;", jobject, (jobject) get_parametertypes(m));*/
667 * Class: java/lang/VMClass
668 * Method: getModifiers
671 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *that)
673 classinfo *c = (classinfo *) that;
680 * Class: java/lang/VMClass
682 * Signature: ()Ljava/lang/String;
684 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *that)
690 c = (classinfo *) that;
691 s = (java_lang_String *) javastring_new(c->name);
696 /* return string where '/' is replaced by '.' */
698 for (i = 0; i < s->value->header.size; i++) {
699 if (s->value->data[i] == '/')
700 s->value->data[i] = '.';
708 * Class: java/lang/VMClass
709 * Method: getBeautifiedName
710 * Signature: (Ljava/lang/Class;)Ljava/lang/String;
712 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getBeautifiedName(JNIEnv *env, jclass clazz, java_lang_Class *par1)
715 classinfo *c = (classinfo *) (par1);
717 char *utf__ptr = c->name->text; /* current position in utf-text */
718 char **utf_ptr = &utf__ptr;
719 char *desc_end = UTF_END(c->name); /* points behind utf string */
726 log_text("Java_java_lang_VMClass_getBeautifiedName");
727 utf_display(c->name);
728 log_text("beautifying");
731 while ( *utf_ptr != desc_end ) {
732 if (utf_nextu2(utf_ptr)=='[') dimCnt++;
735 utf__ptr = (*utf_ptr) - 1;
741 utf_display(c->name);
745 if (((*utf_ptr) + 1) == desc_end) {
746 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
747 if (primitivetype_table[i].typesig == (*utf__ptr)) {
748 len = dimCnt * 2 + strlen(primitivetype_table[i].name);
749 str = MNEW(char, len + 1);
750 strcpy(str, primitivetype_table[i].name);
758 len = dimCnt + strlen(c->name->text) - 2;
759 str = MNEW(char, len + 1);
760 strncpy(str, ++utf__ptr, len - 2 * dimCnt);
762 len = strlen(c->name->text);
763 str = MNEW(char, len + 1);
764 strncpy(str, utf__ptr, len);
769 dimCnt = len - 2 * dimCnt;
771 for (i = len - 1; i >= dimCnt; i = i - 2) {
776 s = javastring_new(utf_new_char(str));
777 MFREE(str, char, len + 1);
781 /* return string where '/' is replaced by '.' */
782 for (i = 0; i < s->value->header.size; i++) {
783 if (s->value->data[i] == '/') s->value->data[i] = '.';
792 * Class: java/lang/Class
793 * Method: getSuperclass
794 * Signature: ()Ljava/lang/Class;
796 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *that)
798 classinfo *cl = (classinfo *) that;
799 classinfo *c = cl->super.cls;
801 if (cl->flags & ACC_INTERFACE)
807 use_class_as_object(c);
809 return (java_lang_Class *) c;
814 * Class: java/lang/Class
818 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *that)
820 classinfo *c = (classinfo *) that;
822 return c->vftbl->arraydesc != NULL;
827 * Class: java/lang/Class
828 * Method: isAssignableFrom
829 * Signature: (Ljava/lang/Class;)Z
831 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *that, java_lang_Class *sup)
834 *exceptionptr = new_nullpointerexception();
838 /* XXX this may be wrong for array classes */
839 return builtin_isanysubclass((classinfo*)sup, (classinfo*)that);
845 * Class: java/lang/Class
847 * Signature: (Ljava/lang/Object;)Z
849 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *that, java_lang_Object *obj)
851 return builtin_instanceof((java_objectheader*)obj, (classinfo*)that);
856 * Class: java/lang/Class
857 * Method: isInterface
860 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *that)
862 classinfo *c = (classinfo *) that;
864 if (c->flags & ACC_INTERFACE)
872 * Class: java/lang/Class
873 * Method: isPrimitive
876 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *that)
879 classinfo *c = (classinfo *) that;
881 /* search table of primitive classes */
882 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
883 if (primitivetype_table[i].class_primitive == c)
891 * Class: java/lang/VMClass
895 JNIEXPORT void JNICALL Java_java_lang_VMClass_initialize(JNIEnv *env, jclass clazz, java_lang_Class *c)
899 ci = (classinfo *) c;
901 /* initialize class */
903 if (!ci->initialized) {
904 /* No need to check return value, because initialize_class already */
905 /* sets the exception pointer. */
906 (void) initialize_class(ci);
912 * Class: java/lang/VMClass
913 * Method: loadArrayClass
914 * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class;
916 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_loadArrayClass(JNIEnv *env, jclass clazz, java_lang_String *name, java_lang_ClassLoader *classloader)
921 /* create utf string with `.' replaced by `/' */
923 u = javastring_toutf(name, true);
925 /* load the array class */
927 if (!load_class_from_classloader(u,(java_objectheader*)classloader,&c))
930 use_class_as_object(c);
932 return (java_lang_Class *) c;
937 * Class: java/lang/VMClass
938 * Method: throwException
939 * Signature: (Ljava/lang/Throwable;)V
941 JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
943 *exceptionptr = (java_objectheader *) t;
948 * These are local overrides for various environment variables in Emacs.
949 * Please do not remove this and leave it at the end of the file, where
950 * Emacs will automagically detect them.
951 * ---------------------------------------------------------------------
954 * indent-tabs-mode: t