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 4126 2006-01-10 20:55:41Z twisti $
42 #include "mm/memory.h"
43 #include "native/jni.h"
44 #include "native/native.h"
45 #include "native/include/java_lang_Class.h"
46 #include "native/include/java_lang_ClassLoader.h"
47 #include "native/include/java_lang_Object.h"
48 #include "native/include/java_lang_VMClass.h"
49 #include "native/include/java_lang_reflect_Constructor.h"
50 #include "native/include/java_lang_reflect_Field.h"
51 #include "native/include/java_lang_reflect_Method.h"
52 #include "native/include/java_security_ProtectionDomain.h"
53 #include "toolbox/logging.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/initialize.h"
58 #include "vm/loader.h"
59 #include "vm/resolve.h"
60 #include "vm/stringlocal.h"
64 * Class: java/lang/VMClass
66 * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
68 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
75 /* illegal argument */
80 /* name must not contain '/' (mauve test) */
82 for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
85 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
90 /* create utf string in which '.' is replaced by '/' */
92 u = javastring_toutf(name, true);
94 /* try to load, ... */
96 if (!(c = load_class_from_classloader(u, (java_objectheader *) loader))) {
99 xclass = (*exceptionptr)->vftbl->class;
101 /* if the exception is a NoClassDefFoundError, we replace it with a
102 ClassNotFoundException, otherwise return the exception */
104 if (xclass == class_java_lang_NoClassDefFoundError) {
105 /* clear exceptionptr, because builtin_new checks for
106 ExceptionInInitializerError */
107 *exceptionptr = NULL;
110 new_exception_javastring(string_java_lang_ClassNotFoundException, name);
121 /* ...and initialize it, if required */
124 if (!initialize_class(c))
127 return (java_lang_Class *) c;
132 * Class: java/lang/VMClass
133 * Method: getClassLoader
134 * Signature: ()Ljava/lang/ClassLoader;
136 JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *klass)
140 c = (classinfo *) klass;
142 return (java_lang_ClassLoader *) c->classloader;
147 * Class: java/lang/VMClass
148 * Method: getComponentType
149 * Signature: ()Ljava/lang/Class;
151 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, java_lang_Class *klass)
155 arraydescriptor *desc;
157 c = (classinfo *) klass;
158 desc = c->vftbl->arraydesc;
163 if (desc->arraytype == ARRAYTYPE_OBJECT)
164 comp = desc->componentvftbl->class;
166 comp = primitivetype_table[desc->arraytype].class_primitive;
168 return (java_lang_Class *) comp;
173 * Class: java/lang/VMClass
174 * Method: getDeclaredConstructors
175 * Signature: (Z)[Ljava/lang/reflect/Constructor;
177 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
180 methodinfo *m; /* the current method to be represented */
181 java_objectarray *oa; /* result: array of Method-objects */
182 java_objectheader *o;
183 java_lang_reflect_Constructor *rc;
184 s4 public_methods; /* number of public methods of the class */
188 c = (classinfo *) klass;
190 /* determine number of constructors */
192 for (i = 0, public_methods = 0; i < c->methodscount; i++) {
195 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
196 (m->name == utf_init))
200 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
205 for (i = 0, pos = 0; i < c->methodscount; i++) {
208 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
209 (m->name == utf_init)) {
211 if (!(o = native_new_and_init(class_java_lang_reflect_Constructor)))
214 /* initialize instance fields */
216 rc = (java_lang_reflect_Constructor *) o;
218 rc->clazz = (java_lang_Class *) c;
221 /* store object into array */
232 * Class: java/lang/VMClass
233 * Method: getDeclaredClasses
234 * Signature: (Z)[Ljava/lang/Class;
236 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
239 classref_or_classinfo outer;
241 s4 declaredclasscount; /* number of declared classes */
242 s4 pos; /* current declared class */
243 java_objectarray *oa; /* array of declared classes */
246 c = (classinfo *) klass;
247 declaredclasscount = 0;
249 if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
250 (c->name->text[0] != '[')) {
251 /* determine number of declared classes */
253 for (i = 0; i < c->innerclasscount; i++) {
254 outer = c->innerclass[i].outer_class;
256 /* check if outer_class is a classref or a real class and
257 get the class name from the structure */
259 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
261 /* outer class is this class */
263 if ((outername == c->name) &&
264 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
265 declaredclasscount++;
269 /* allocate Class[] and check for OOM */
271 oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
276 for (i = 0, pos = 0; i < c->innerclasscount; i++) {
277 outer = c->innerclass[i].outer_class;
279 /* check if outer_class is a classref or a real class and
280 get the class name from the structure */
282 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
284 /* outer class is this class */
286 if ((outername == c->name) &&
287 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
290 if (!resolve_classref_or_classinfo(NULL,
291 c->innerclass[i].inner_class,
292 resolveEager, false, false,
296 if (!(inner->state & CLASS_LINKED))
297 if (!link_class(inner))
300 oa->data[pos++] = (java_objectheader *) inner;
309 * Class: java/lang/VMClass
310 * Method: getDeclaringClass
311 * Signature: ()Ljava/lang/Class;
313 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
316 classref_or_classinfo inner;
321 c = (classinfo *) klass;
323 if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
324 (c->name->text[0] != '[')) {
326 if (c->innerclasscount == 0) /* no innerclasses exist */
329 for (i = 0; i < c->innerclasscount; i++) {
330 inner = c->innerclass[i].inner_class;
332 /* check if inner_class is a classref or a real class and
333 get the class name from the structure */
335 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
337 /* innerclass is this class */
339 if (innername == c->name) {
340 /* maybe the outer class is not loaded yet */
342 if (!resolve_classref_or_classinfo(NULL,
343 c->innerclass[i].outer_class,
344 resolveEager, false, false,
348 if (!(outer->state & CLASS_LINKED))
349 if (!link_class(outer))
352 return (java_lang_Class *) outer;
357 /* return NULL for arrayclasses and primitive classes */
364 * Class: java/lang/VMClass
365 * Method: getDeclaredFields
366 * Signature: (Z)[Ljava/lang/reflect/Field;
368 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
371 java_objectarray *oa; /* result: array of field-objects */
373 java_objectheader *o;
374 java_lang_reflect_Field *rf;
375 s4 public_fields; /* number of elements in field-array */
379 c = (classinfo *) klass;
381 /* determine number of fields */
383 for (i = 0, public_fields = 0; i < c->fieldscount; i++)
384 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
387 /* create array of fields */
389 oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
394 /* get the fields and store in the array */
396 for (i = 0, pos = 0; i < c->fieldscount; i++) {
399 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
400 /* create Field object */
402 if (!(o = native_new_and_init(class_java_lang_reflect_Field)))
405 /* initialize instance fields */
407 rf = (java_lang_reflect_Field *) o;
409 rf->declaringClass = (java_lang_Class *) c;
410 rf->name = javastring_new(f->name);
413 /* store object into array */
424 * Class: java/lang/VMClass
425 * Method: getInterfaces
426 * Signature: ()[Ljava/lang/Class;
428 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *klass)
432 java_objectarray *oa;
435 c = (classinfo *) klass;
437 if (!(c->state & CLASS_LINKED))
441 oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
446 for (i = 0; i < c->interfacescount; i++) {
447 ic = c->interfaces[i].cls;
449 oa->data[i] = (java_objectheader *) ic;
457 * Class: java/lang/VMClass
458 * Method: getDeclaredMethods
459 * Signature: (Z)[Ljava/lang/reflect/Method;
461 JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
464 java_objectheader *o;
465 java_lang_reflect_Method *rm;
466 java_objectarray *oa; /* result: array of Method-objects */
467 methodinfo *m; /* the current method to be represented */
468 s4 public_methods; /* number of public methods of the class */
472 c = (classinfo *) klass;
475 /* JOWENN: array classes do not declare methods according to mauve
476 test. It should be considered, if we should return to my old
477 clone method overriding instead of declaring it as a member
480 if (Java_java_lang_VMClass_isArray(env, clazz, klass))
481 return builtin_anewarray(0, class_java_lang_reflect_Method);
483 /* determine number of methods */
485 for (i = 0; i < c->methodscount; i++) {
488 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
489 ((m->name != utf_init) && (m->name != utf_clinit)))
493 oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
498 for (i = 0, pos = 0; i < c->methodscount; i++) {
501 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
502 ((m->name != utf_init) && (m->name != utf_clinit))) {
504 if (!(o = native_new_and_init(class_java_lang_reflect_Method)))
507 /* initialize instance fields */
509 rm = (java_lang_reflect_Method *) o;
511 rm->declaringClass = klass;
512 rm->name = javastring_new(m->name);
515 /* store object into array */
526 * Class: java/lang/VMClass
527 * Method: getModifiers
530 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
533 classref_or_classinfo inner;
534 classref_or_classinfo outer;
538 c = (classinfo *) klass;
540 if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
541 /* search for passed class as inner class */
543 for (i = 0; i < c->innerclasscount; i++) {
544 inner = c->innerclass[i].inner_class;
545 outer = c->innerclass[i].outer_class;
547 /* Check if inner is a classref or a real class and get
548 the name of the structure */
550 innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
552 /* innerclass is this class */
554 if (innername == c->name) {
555 /* has the class actually an outer class? */
558 /* return flags got from the outer class file */
559 return c->innerclass[i].flags;
566 /* passed class is no inner class or it was not requested */
573 * Class: java/lang/VMClass
575 * Signature: ()Ljava/lang/String;
577 JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *klass)
583 c = (classinfo *) klass;
584 s = (java_lang_String *) javastring_new(c->name);
589 /* return string where '/' is replaced by '.' */
591 for (i = 0; i < s->value->header.size; i++) {
592 if (s->value->data[i] == '/')
593 s->value->data[i] = '.';
601 * Class: java/lang/Class
602 * Method: getSuperclass
603 * Signature: ()Ljava/lang/Class;
605 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
610 c = (classinfo *) klass;
613 if (c->flags & ACC_INTERFACE)
619 return (java_lang_Class *) sc;
624 * Class: java/lang/Class
628 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *klass)
630 classinfo *c = (classinfo *) klass;
632 if (!(c->state & CLASS_LINKED))
636 return (c->vftbl->arraydesc != NULL);
641 * Class: java/lang/Class
642 * Method: isAssignableFrom
643 * Signature: (Ljava/lang/Class;)Z
645 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
650 kc = (classinfo *) klass;
651 cc = (classinfo *) c;
654 exceptions_throw_nullpointerexception();
658 if (!(kc->state & CLASS_LINKED))
662 if (!(cc->state & CLASS_LINKED))
666 /* XXX this may be wrong for array classes */
668 return builtin_isanysubclass(cc, kc);
673 * Class: java/lang/Class
675 * Signature: (Ljava/lang/Object;)Z
677 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
680 java_objectheader *ob;
682 c = (classinfo *) klass;
683 ob = (java_objectheader *) o;
685 if (!(c->state & CLASS_LINKED))
689 return builtin_instanceof(ob, c);
694 * Class: java/lang/Class
695 * Method: isInterface
698 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
702 c = (classinfo *) klass;
704 if (c->flags & ACC_INTERFACE)
712 * Class: java/lang/Class
713 * Method: isPrimitive
716 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *klass)
721 c = (classinfo *) klass;
723 /* search table of primitive classes */
725 for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
726 if (primitivetype_table[i].class_primitive == c)
734 * Class: java/lang/VMClass
735 * Method: throwException
736 * Signature: (Ljava/lang/Throwable;)V
738 JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
740 *exceptionptr = (java_objectheader *) t;
745 * These are local overrides for various environment variables in Emacs.
746 * Please do not remove this and leave it at the end of the file, where
747 * Emacs will automagically detect them.
748 * ---------------------------------------------------------------------
751 * indent-tabs-mode: t