1 /* src/native/vm/VMClass.c - java/lang/VMClass
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Roman Obermaiser
29 Changes: Joseph Wenninger
33 $Id: VMClass.c 4551 2006-03-03 00:00:39Z twisti $
45 #include "mm/memory.h"
46 #include "native/jni.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Class.h"
49 #include "native/include/java_lang_ClassLoader.h"
50 #include "native/include/java_lang_Object.h"
51 #include "native/include/java_lang_VMClass.h"
52 #include "native/include/java_lang_reflect_Constructor.h"
53 #include "native/include/java_lang_reflect_Field.h"
54 #include "native/include/java_lang_reflect_Method.h"
55 #include "native/include/java_security_ProtectionDomain.h"
56 #include "toolbox/logging.h"
57 #include "vm/builtin.h"
58 #include "vm/exceptions.h"
59 #include "vm/global.h"
60 #include "vm/initialize.h"
61 #include "vm/loader.h"
62 #include "vm/resolve.h"
63 #include "vm/stringlocal.h"
67 * Class: java/lang/VMClass
69 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
71 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
78 /* illegal argument */
83 /* name must not contain '/' (mauve test) */
85 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
88 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
93 /* create utf string in which '.' is replaced by '/' */
95 u = javastring_toutf(name, true);
97 /* try to load, ... */
99 if (!(c = load_class_from_classloader(u, (java_objectheader *) loader))) {
102 xclass = (*exceptionptr)->vftbl->class;
104 /* if the exception is a NoClassDefFoundError, we replace it with a
105 ClassNotFoundException, otherwise return the exception */
107 if (xclass == class_java_lang_NoClassDefFoundError) {
108 /* clear exceptionptr, because builtin_new checks for
109 ExceptionInInitializerError */
110 *exceptionptr = NULL;
113 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
124 /* ...and initialize it, if required */
127 if (!initialize_class(c))
130 return (java_lang_Class *) c;
135 * Class: java/lang/VMClass
136 * Method: getClassLoader
137 * Signature: ()Ljava/lang/ClassLoader;
139 JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *klass)
143 c = (classinfo *) klass;
145 return (java_lang_ClassLoader *) c->classloader;
150 * Class: java/lang/VMClass
151 * Method: getComponentType
152 * Signature: ()Ljava/lang/Class;
154 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, java_lang_Class *klass)
158 arraydescriptor *desc;
160 c = (classinfo *) klass;
161 desc = c->vftbl->arraydesc;
166 if (desc->arraytype == ARRAYTYPE_OBJECT)
167 comp = desc->componentvftbl->class;
169 comp = primitivetype_table[desc->arraytype].class_primitive;
171 return (java_lang_Class *) comp;
176 * Class: java/lang/VMClass
177 * Method: getDeclaredConstructors
178 * Signature: (Z)[Ljava/lang/reflect/Constructor;
180 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
183 methodinfo *m; /* the current method to be represented */
184 java_objectarray *oa; /* result: array of Method-objects */
185 java_objectheader *o;
186 java_lang_reflect_Constructor *rc;
187 s4 public_methods; /* number of public methods of the class */
191 c = (classinfo *) klass;
193 /* determine number of constructors */
195 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
198 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
199 (m->name == utf_init))
203 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
208 for (i = 0, pos = 0; i < c->methodscount; i++) {
211 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
212 (m->name == utf_init)) {
214 if (!(o = native_new_and_init(class_java_lang_reflect_Constructor)))
217 /* initialize instance fields */
219 rc = (java_lang_reflect_Constructor *) o;
221 rc->clazz = (java_lang_Class *) c;
224 /* store object into array */
235 * Class: java/lang/VMClass
236 * Method: getDeclaredClasses
237 * Signature: (Z)[Ljava/lang/Class;
239 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
242 classref_or_classinfo outer;
244 s4 declaredclasscount; /* number of declared classes */
245 s4 pos; /* current declared class */
246 java_objectarray *oa; /* array of declared classes */
249 c = (classinfo *) klass;
250 declaredclasscount = 0;
252 if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
253 (c->name->text[0] != '[')) {
254 /* determine number of declared classes */
256 for (i = 0; i < c->innerclasscount; i++) {
257 outer = c->innerclass[i].outer_class;
259 /* check if outer_class is a classref or a real class and
260 get the class name from the structure */
262 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
264 /* outer class is this class */
266 if ((outername == c->name) &&
267 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
268 declaredclasscount++;
272 /* allocate Class[] and check for OOM */
274 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
279 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
280 outer = c->innerclass[i].outer_class;
282 /* check if outer_class is a classref or a real class and
283 get the class name from the structure */
285 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
287 /* outer class is this class */
289 if ((outername == c->name) &&
290 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
293 if (!resolve_classref_or_classinfo(NULL,
294 c->innerclass[i].inner_class,
295 resolveEager, false, false,
299 if (!(inner->state & CLASS_LINKED))
300 if (!link_class(inner))
303 oa->data[pos++] = (java_objectheader *) inner;
312 * Class: java/lang/VMClass
313 * Method: getDeclaringClass
314 * Signature: ()Ljava/lang/Class;
316 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
319 classref_or_classinfo inner;
324 c = (classinfo *) klass;
326 if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
327 (c->name->text[0] != '[')) {
329 if (c->innerclasscount == 0) /* no innerclasses exist */
332 for (i = 0; i < c->innerclasscount; i++) {
333 inner = c->innerclass[i].inner_class;
335 /* check if inner_class is a classref or a real class and
336 get the class name from the structure */
338 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
340 /* innerclass is this class */
342 if (innername == c->name) {
343 /* maybe the outer class is not loaded yet */
345 if (!resolve_classref_or_classinfo(NULL,
346 c->innerclass[i].outer_class,
347 resolveEager, false, false,
351 if (!(outer->state & CLASS_LINKED))
352 if (!link_class(outer))
355 return (java_lang_Class *) outer;
360 /* return NULL for arrayclasses and primitive classes */
367 * Class: java/lang/VMClass
368 * Method: getDeclaredFields
369 * Signature: (Z)[Ljava/lang/reflect/Field;
371 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
374 java_objectarray *oa; /* result: array of field-objects */
376 java_objectheader *o;
377 java_lang_reflect_Field *rf;
378 s4 public_fields; /* number of elements in field-array */
382 c = (classinfo *) klass;
384 /* determine number of fields */
386 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
387 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
390 /* create array of fields */
392 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
397 /* get the fields and store in the array */
399 for (i = 0, pos = 0; i < c->fieldscount; i++) {
402 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
403 /* create Field object */
405 if (!(o = native_new_and_init(class_java_lang_reflect_Field)))
408 /* initialize instance fields */
410 rf = (java_lang_reflect_Field *) o;
412 rf->declaringClass = (java_lang_Class *) c;
413 rf->name = javastring_new(f->name);
416 /* store object into array */
427 * Class: java/lang/VMClass
428 * Method: getInterfaces
429 * Signature: ()[Ljava/lang/Class;
431 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *klass)
435 java_objectarray *oa;
438 c = (classinfo *) klass;
440 if (!(c->state & CLASS_LINKED))
444 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
449 for (i = 0; i < c->interfacescount; i++) {
450 ic = c->interfaces[i].cls;
452 oa->data[i] = (java_objectheader *) ic;
460 * Class: java/lang/VMClass
461 * Method: getDeclaredMethods
462 * Signature: (Z)[Ljava/lang/reflect/Method;
464 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
467 java_objectheader *o;
468 java_lang_reflect_Method *rm;
469 java_objectarray *oa; /* result: array of Method-objects */
470 methodinfo *m; /* the current method to be represented */
471 s4 public_methods; /* number of public methods of the class */
475 c = (classinfo *) klass;
478 /* JOWENN: array classes do not declare methods according to mauve
479 test. It should be considered, if we should return to my old
480 clone method overriding instead of declaring it as a member
483 if (Java_java_lang_VMClass_isArray(env, clazz, klass))
484 return builtin_anewarray(0, class_java_lang_reflect_Method);
486 /* determine number of methods */
488 for (i = 0; i < c->methodscount; i++) {
491 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
492 ((m->name != utf_init) && (m->name != utf_clinit)) &&
493 !(m->flags & ACC_MIRANDA))
497 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
502 for (i = 0, pos = 0; i < c->methodscount; i++) {
505 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
506 ((m->name != utf_init) && (m->name != utf_clinit)) &&
507 !(m->flags & ACC_MIRANDA)) {
509 if (!(o = native_new_and_init(class_java_lang_reflect_Method)))
512 /* initialize instance fields */
514 rm = (java_lang_reflect_Method *) o;
516 rm->declaringClass = (java_lang_Class *) m->class;
517 rm->name = javastring_new(m->name);
520 /* store object into array */
531 * Class: java/lang/VMClass
532 * Method: getModifiers
535 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
538 classref_or_classinfo inner;
539 classref_or_classinfo outer;
543 c = (classinfo *) klass;
545 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
546 /* search for passed class as inner class */
548 for (i = 0; i < c->innerclasscount; i++) {
549 inner = c->innerclass[i].inner_class;
550 outer = c->innerclass[i].outer_class;
552 /* Check if inner is a classref or a real class and get
553 the name of the structure */
555 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
557 /* innerclass is this class */
559 if (innername == c->name) {
560 /* has the class actually an outer class? */
563 /* return flags got from the outer class file */
564 return c->innerclass[i].flags;
571 /* passed class is no inner class or it was not requested */
578 * Class: java/lang/VMClass
580 * Signature: ()Ljava/lang/String;
582 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *klass)
588 c = (classinfo *) klass;
589 s = (java_lang_String *) javastring_new(c->name);
594 /* return string where '/' is replaced by '.' */
596 for (i = 0; i < s->value->header.size; i++) {
597 if (s->value->data[i] == '/')
598 s->value->data[i] = '.';
606 * Class: java/lang/Class
607 * Method: getSuperclass
608 * Signature: ()Ljava/lang/Class;
610 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
615 c = (classinfo *) klass;
618 if (c->flags & ACC_INTERFACE)
624 return (java_lang_Class *) sc;
629 * Class: java/lang/Class
633 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *klass)
635 classinfo *c = (classinfo *) klass;
637 if (!(c->state & CLASS_LINKED))
641 return (c->vftbl->arraydesc != NULL);
646 * Class: java/lang/Class
647 * Method: isAssignableFrom
648 * Signature: (Ljava/lang/Class;)Z
650 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
655 kc = (classinfo *) klass;
656 cc = (classinfo *) c;
659 exceptions_throw_nullpointerexception();
663 if (!(kc->state & CLASS_LINKED))
667 if (!(cc->state & CLASS_LINKED))
671 /* XXX this may be wrong for array classes */
673 return builtin_isanysubclass(cc, kc);
678 * Class: java/lang/Class
680 * Signature: (Ljava/lang/Object;)Z
682 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
685 java_objectheader *ob;
687 c = (classinfo *) klass;
688 ob = (java_objectheader *) o;
690 if (!(c->state & CLASS_LINKED))
694 return builtin_instanceof(ob, c);
699 * Class: java/lang/Class
700 * Method: isInterface
703 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
707 c = (classinfo *) klass;
709 if (c->flags & ACC_INTERFACE)
717 * Class: java/lang/Class
718 * Method: isPrimitive
721 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *klass)
726 c = (classinfo *) klass;
728 /* search table of primitive classes */
730 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
731 if (primitivetype_table[i].class_primitive == c)
739 * Class: java/lang/VMClass
740 * Method: throwException
741 * Signature: (Ljava/lang/Throwable;)V
743 JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
745 *exceptionptr = (java_objectheader *) t;
750 * These are local overrides for various environment variables in Emacs.
751 * Please do not remove this and leave it at the end of the file, where
752 * Emacs will automagically detect them.
753 * ---------------------------------------------------------------------
756 * indent-tabs-mode: t
760 * vim:noexpandtab:sw=4:ts=4: