1 // natClass.cc - Implementation of java.lang.Class native methods.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
4 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
19 #pragma implementation "Class.h"
23 #include <java-threads.h>
25 #include <java/lang/Class.h>
26 #include <java/lang/ClassLoader.h>
27 #include <java/lang/String.h>
28 #include <java/lang/reflect/Modifier.h>
29 #include <java/lang/reflect/Member.h>
30 #include <java/lang/reflect/Method.h>
31 #include <java/lang/reflect/Field.h>
32 #include <java/lang/reflect/Constructor.h>
33 #include <java/lang/AbstractMethodError.h>
34 #include <java/lang/ArrayStoreException.h>
35 #include <java/lang/ClassCastException.h>
36 #include <java/lang/ClassNotFoundException.h>
37 #include <java/lang/ExceptionInInitializerError.h>
38 #include <java/lang/IllegalAccessException.h>
39 #include <java/lang/IllegalAccessError.h>
40 #include <java/lang/IllegalArgumentException.h>
41 #include <java/lang/IncompatibleClassChangeError.h>
42 #include <java/lang/NoSuchFieldError.h>
43 #include <java/lang/ArrayIndexOutOfBoundsException.h>
44 #include <java/lang/InstantiationException.h>
45 #include <java/lang/NoClassDefFoundError.h>
46 #include <java/lang/NoSuchFieldException.h>
47 #include <java/lang/NoSuchMethodError.h>
48 #include <java/lang/NoSuchMethodException.h>
49 #include <java/lang/Thread.h>
50 #include <java/lang/NullPointerException.h>
51 #include <java/lang/RuntimePermission.h>
52 #include <java/lang/System.h>
53 #include <java/lang/SecurityManager.h>
54 #include <java/lang/StringBuffer.h>
55 #include <java/lang/VMClassLoader.h>
56 #include <gcj/method.h>
57 #include <gnu/gcj/RawData.h>
58 #include <java/lang/VerifyError.h>
60 #include <java-cpool.h>
61 #include <java-interp.h>
62 #include <java-assert.h>
63 #include <java-stack.h>
64 #include <execution.h>
71 java::lang::Class::forName (jstring className, jboolean initialize,
72 java::lang::ClassLoader *loader)
75 throw new java::lang::NullPointerException;
77 jsize length = _Jv_GetStringUTFLength (className);
79 _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);
81 _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
83 if (! _Jv_VerifyClassName (name))
84 throw new java::lang::ClassNotFoundException (className);
86 jclass klass = (buffer[0] == '['
87 ? _Jv_FindClassFromSignature (name->chars(), loader)
88 : _Jv_FindClass (name, loader));
91 throw new java::lang::ClassNotFoundException (className);
94 _Jv_InitClass (klass);
100 java::lang::Class::forName (jstring className)
102 java::lang::ClassLoader *loader = NULL;
104 jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
106 loader = caller->getClassLoaderInternal();
108 return forName (className, true, loader);
111 java::lang::ClassLoader *
112 java::lang::Class::getClassLoader (void)
114 java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
117 jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
118 ClassLoader *caller_loader = NULL;
120 caller_loader = caller->getClassLoaderInternal();
122 // If the caller has a non-null class loader, and that loader
123 // is not this class' loader or an ancestor thereof, then do a
125 if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
126 s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
132 java::lang::reflect::Constructor *
133 java::lang::Class::getConstructor (JArray<jclass> *param_types)
135 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
137 jstring partial_sig = getSignature (param_types, true);
138 jint hash = partial_sig->hashCode ();
140 int i = isPrimitive () ? 0 : method_count;
143 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
144 && _Jv_equal (methods[i].signature, partial_sig, hash))
146 // Found it. For getConstructor, the constructor must be
148 using namespace java::lang::reflect;
149 if (! Modifier::isPublic(methods[i].accflags))
151 Constructor *cons = new Constructor ();
152 cons->offset = (char *) (&methods[i]) - (char *) methods;
153 cons->declaringClass = this;
157 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
160 JArray<java::lang::reflect::Constructor *> *
161 java::lang::Class::getDeclaredConstructors (jboolean publicOnly)
163 int numConstructors = 0;
164 int max = isPrimitive () ? 0 : method_count;
166 for (i = max; --i >= 0; )
168 _Jv_Method *method = &methods[i];
169 if (method->name == NULL
170 || ! _Jv_equalUtf8Consts (method->name, init_name))
173 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
177 JArray<java::lang::reflect::Constructor *> *result
178 = (JArray<java::lang::reflect::Constructor *> *)
179 JvNewObjectArray (numConstructors,
180 &java::lang::reflect::Constructor::class$,
182 java::lang::reflect::Constructor** cptr = elements (result);
183 for (i = 0; i < max; i++)
185 _Jv_Method *method = &methods[i];
186 if (method->name == NULL
187 || ! _Jv_equalUtf8Consts (method->name, init_name))
190 && ! java::lang::reflect::Modifier::isPublic(method->accflags))
192 java::lang::reflect::Constructor *cons
193 = new java::lang::reflect::Constructor ();
194 cons->offset = (char *) method - (char *) methods;
195 cons->declaringClass = this;
201 java::lang::reflect::Constructor *
202 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
204 memberAccessCheck(java::lang::reflect::Member::DECLARED);
206 jstring partial_sig = getSignature (param_types, true);
207 jint hash = partial_sig->hashCode ();
209 int i = isPrimitive () ? 0 : method_count;
212 if (_Jv_equalUtf8Consts (methods[i].name, init_name)
213 && _Jv_equal (methods[i].signature, partial_sig, hash))
216 using namespace java::lang::reflect;
217 Constructor *cons = new Constructor ();
218 cons->offset = (char *) (&methods[i]) - (char *) methods;
219 cons->declaringClass = this;
223 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
226 java::lang::reflect::Field *
227 java::lang::Class::getField (jstring name, jint hash)
229 java::lang::reflect::Field* rfield;
230 for (int i = 0; i < field_count; i++)
232 _Jv_Field *field = &fields[i];
233 if (! _Jv_equal (field->name, name, hash))
235 if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
237 rfield = new java::lang::reflect::Field ();
238 rfield->offset = (char*) field - (char*) fields;
239 rfield->declaringClass = this;
243 jclass superclass = getSuperclass();
244 if (superclass == NULL)
246 rfield = superclass->getField(name, hash);
247 for (int i = 0; i < interface_count && rfield == NULL; ++i)
248 rfield = interfaces[i]->getField (name, hash);
252 java::lang::reflect::Field *
253 java::lang::Class::getDeclaredField (jstring name)
255 memberAccessCheck(java::lang::reflect::Member::DECLARED);
256 int hash = name->hashCode();
257 for (int i = 0; i < field_count; i++)
259 _Jv_Field *field = &fields[i];
260 if (! _Jv_equal (field->name, name, hash))
262 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
263 rfield->offset = (char*) field - (char*) fields;
264 rfield->declaringClass = this;
268 throw new java::lang::NoSuchFieldException (name);
271 JArray<java::lang::reflect::Field *> *
272 java::lang::Class::getDeclaredFields (jboolean public_only)
278 for (int i = 0; i < field_count; ++i)
280 _Jv_Field *field = &fields[i];
281 if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
288 JArray<java::lang::reflect::Field *> *result
289 = (JArray<java::lang::reflect::Field *> *)
290 JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
291 java::lang::reflect::Field** fptr = elements (result);
292 for (int i = 0; i < field_count; i++)
294 _Jv_Field *field = &fields[i];
296 && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
298 java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
299 rfield->offset = (char*) field - (char*) fields;
300 rfield->declaringClass = this;
307 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
310 buffer->append((jchar) method_count);
313 jstring name = getName();
314 if (name->charAt(0) != '[')
315 buffer->append((jchar) 'L');
316 buffer->append(name);
317 if (name->charAt(0) != '[')
318 buffer->append((jchar) ';');
322 // This doesn't have to be native. It is an implementation detail
323 // only called from the C++ code, though, so maybe this is clearer.
325 java::lang::Class::getSignature (JArray<jclass> *param_types,
326 jboolean is_constructor)
328 java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
329 buf->append((jchar) '(');
330 // A NULL param_types means "no parameters".
331 if (param_types != NULL)
333 jclass *v = elements (param_types);
334 for (int i = 0; i < param_types->length; ++i)
335 v[i]->getSignature(buf);
337 buf->append((jchar) ')');
339 buf->append((jchar) 'V');
340 return buf->toString();
343 java::lang::reflect::Method *
344 java::lang::Class::_getDeclaredMethod (jstring name,
345 JArray<jclass> *param_types)
347 jstring partial_sig = getSignature (param_types, false);
348 jint p_len = partial_sig->length();
349 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
350 int i = isPrimitive () ? 0 : method_count;
353 if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
354 && _Jv_equaln (methods[i].signature, partial_sig, p_len)
355 && (methods[i].accflags
356 & java::lang::reflect::Modifier::INVISIBLE) == 0)
359 using namespace java::lang::reflect;
360 Method *rmethod = new Method ();
361 rmethod->offset = (char*) (&methods[i]) - (char*) methods;
362 rmethod->declaringClass = this;
369 JArray<java::lang::reflect::Method *> *
370 java::lang::Class::getDeclaredMethods (void)
372 memberAccessCheck(java::lang::reflect::Member::DECLARED);
375 int max = isPrimitive () ? 0 : method_count;
377 for (i = max; --i >= 0; )
379 _Jv_Method *method = &methods[i];
380 if (method->name == NULL
381 || _Jv_equalUtf8Consts (method->name, clinit_name)
382 || _Jv_equalUtf8Consts (method->name, init_name)
383 || _Jv_equalUtf8Consts (method->name, finit_name)
384 || (methods[i].accflags
385 & java::lang::reflect::Modifier::INVISIBLE) != 0)
389 JArray<java::lang::reflect::Method *> *result
390 = (JArray<java::lang::reflect::Method *> *)
391 JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
392 java::lang::reflect::Method** mptr = elements (result);
393 for (i = 0; i < max; i++)
395 _Jv_Method *method = &methods[i];
396 if (method->name == NULL
397 || _Jv_equalUtf8Consts (method->name, clinit_name)
398 || _Jv_equalUtf8Consts (method->name, init_name)
399 || _Jv_equalUtf8Consts (method->name, finit_name)
400 || (methods[i].accflags
401 & java::lang::reflect::Modifier::INVISIBLE) != 0)
403 java::lang::reflect::Method* rmethod
404 = new java::lang::reflect::Method ();
405 rmethod->offset = (char*) method - (char*) methods;
406 rmethod->declaringClass = this;
413 java::lang::Class::getName (void)
415 return name->toString();
419 java::lang::Class::getDeclaredClasses (jboolean /*publicOnly*/)
421 // Until we have inner classes, it always makes sense to return an
423 JArray<jclass> *result
424 = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
430 java::lang::Class::getDeclaringClass (void)
432 // Until we have inner classes, it makes sense to always return
438 java::lang::Class::getInterfaces (void)
440 jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
441 jobject *data = elements (r);
442 for (int i = 0; i < interface_count; ++i)
444 typedef unsigned int uaddr __attribute__ ((mode (pointer)));
445 data[i] = interfaces[i];
446 if ((uaddr)data[i] < (uaddr)constants.size)
447 fprintf (stderr, "ERROR !!!\n");
449 return reinterpret_cast<JArray<jclass> *> (r);
452 java::lang::reflect::Method *
453 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
455 jstring partial_sig = getSignature (param_types, false);
456 jint p_len = partial_sig->length();
457 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
459 for (Class *klass = this; klass; klass = klass->getSuperclass())
461 int i = klass->isPrimitive () ? 0 : klass->method_count;
464 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
465 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
466 && (klass->methods[i].accflags
467 & java::lang::reflect::Modifier::INVISIBLE) == 0)
470 using namespace java::lang::reflect;
472 // Method must be public.
473 if (! Modifier::isPublic (klass->methods[i].accflags))
476 Method *rmethod = new Method ();
477 rmethod->offset = ((char *) (&klass->methods[i])
478 - (char *) klass->methods);
479 rmethod->declaringClass = klass;
485 // If we haven't found a match, and this class is an interface, then
486 // check all the superinterfaces.
489 for (int i = 0; i < interface_count; ++i)
491 using namespace java::lang::reflect;
492 Method *rmethod = interfaces[i]->_getMethod (name, param_types);
501 // This is a very slow implementation, since it re-scans all the
502 // methods we've already listed to make sure we haven't duplicated a
503 // method. It also over-estimates the required size, so we have to
504 // shrink the result array later.
506 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
511 // First examine all local methods
512 for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
514 _Jv_Method *method = &methods[i];
515 if (method->name == NULL
516 || _Jv_equalUtf8Consts (method->name, clinit_name)
517 || _Jv_equalUtf8Consts (method->name, init_name)
518 || _Jv_equalUtf8Consts (method->name, finit_name)
520 & java::lang::reflect::Modifier::INVISIBLE) != 0)
522 // Only want public methods.
523 if (! java::lang::reflect::Modifier::isPublic (method->accflags))
526 // This is where we over-count the slots required if we aren't
527 // filling the result for real.
531 java::lang::reflect::Method **mp = elements (result);
532 // If we already have a method with this name and signature,
533 // then ignore this one. This can happen with virtual
535 for (int j = 0; j < offset; ++j)
537 _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
538 if (_Jv_equalUtf8Consts (method->name, meth_2->name)
539 && _Jv_equalUtf8Consts (method->signature,
552 using namespace java::lang::reflect;
553 Method *rmethod = new Method ();
554 rmethod->offset = (char *) method - (char *) methods;
555 rmethod->declaringClass = this;
556 Method **mp = elements (result);
557 mp[offset + count] = rmethod;
563 // Now examine superclasses.
564 if (getSuperclass () != NULL)
566 jint s_count = getSuperclass()->_getMethods (result, offset);
571 // Finally, examine interfaces.
572 for (int i = 0; i < interface_count; ++i)
574 int f_count = interfaces[i]->_getMethods (result, offset);
582 JArray<java::lang::reflect::Method *> *
583 java::lang::Class::getMethods (void)
585 using namespace java::lang::reflect;
587 memberAccessCheck(Member::PUBLIC);
589 // This will overestimate the size we need.
590 jint count = _getMethods (NULL, 0);
592 JArray<Method *> *result
593 = ((JArray<Method *> *) JvNewObjectArray (count,
597 // When filling the array for real, we get the actual count. Then
598 // we resize the array.
599 jint real_count = _getMethods (result, 0);
601 if (real_count != count)
604 = ((JArray<Method *> *) JvNewObjectArray (real_count,
608 Method **destp = elements (r2);
609 Method **srcp = elements (result);
611 for (int i = 0; i < real_count; ++i)
621 java::lang::Class::isAssignableFrom (jclass klass)
623 // Arguments may not have been initialized, given ".class" syntax.
624 _Jv_InitClass (this);
625 _Jv_InitClass (klass);
626 return _Jv_IsAssignableFrom (klass, this);
630 java::lang::Class::isInstance (jobject obj)
634 _Jv_InitClass (this);
635 return _Jv_IsAssignableFrom (JV_CLASS (obj), this);
639 java::lang::Class::newInstance (void)
641 memberAccessCheck(java::lang::reflect::Member::PUBLIC);
646 || java::lang::reflect::Modifier::isAbstract(accflags))
647 throw new java::lang::InstantiationException (getName ());
649 _Jv_InitClass (this);
651 _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
653 throw new java::lang::InstantiationException (getName());
655 jobject r = _Jv_AllocObject (this);
656 ((void (*) (jobject)) meth->ncode) (r);
661 java::lang::Class::finalize (void)
663 engine->unregister(this);
666 // This implements the initialization process for a class. From Spec
669 java::lang::Class::initializeClass (void)
671 // Short-circuit to avoid needless locking.
672 if (state == JV_STATE_DONE)
675 // Step 1. We introduce a new scope so we can synchronize more
678 JvSynchronize sync (this);
680 if (state < JV_STATE_LINKED)
684 _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
686 catch (java::lang::Throwable *x)
688 // Turn into a NoClassDefFoundError.
689 java::lang::NoClassDefFoundError *result
690 = new java::lang::NoClassDefFoundError(getName());
691 result->initCause(x);
697 java::lang::Thread *self = java::lang::Thread::currentThread();
698 self = (java::lang::Thread *) ((long) self | 1);
699 while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
703 if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
707 if (state == JV_STATE_ERROR)
708 throw new java::lang::NoClassDefFoundError (getName());
712 _Jv_Linker::wait_for_state (this, JV_STATE_LINKED);
713 state = JV_STATE_IN_PROGRESS;
717 if (! isInterface () && superclass)
721 _Jv_InitClass (superclass);
723 catch (java::lang::Throwable *except)
725 // Caught an exception.
726 JvSynchronize sync (this);
727 state = JV_STATE_ERROR;
733 // Steps 8, 9, 10, 11.
736 _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
739 ((void (*) (void)) meth->ncode) ();
741 catch (java::lang::Throwable *except)
743 if (! java::lang::Error::class$.isInstance(except))
747 except = new ExceptionInInitializerError (except);
749 catch (java::lang::Throwable *t)
755 JvSynchronize sync (this);
756 state = JV_STATE_ERROR;
761 JvSynchronize sync (this);
762 state = JV_STATE_DONE;
766 // Only used by serialization
767 java::lang::reflect::Field *
768 java::lang::Class::getPrivateField (jstring name)
770 int hash = name->hashCode ();
772 java::lang::reflect::Field* rfield;
773 for (int i = 0; i < field_count; i++)
775 _Jv_Field *field = &fields[i];
776 if (! _Jv_equal (field->name, name, hash))
778 rfield = new java::lang::reflect::Field ();
779 rfield->offset = (char*) field - (char*) fields;
780 rfield->declaringClass = this;
784 jclass superclass = getSuperclass();
785 if (superclass == NULL)
787 rfield = superclass->getPrivateField(name);
788 for (int i = 0; i < interface_count && rfield == NULL; ++i)
789 rfield = interfaces[i]->getPrivateField (name);
793 // Only used by serialization
794 java::lang::reflect::Method *
795 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
797 jstring partial_sig = getSignature (param_types, false);
798 jint p_len = partial_sig->length();
799 _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
800 for (Class *klass = this; klass; klass = klass->getSuperclass())
802 int i = klass->isPrimitive () ? 0 : klass->method_count;
805 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
806 && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
809 using namespace java::lang::reflect;
811 Method *rmethod = new Method ();
812 rmethod->offset = ((char *) (&klass->methods[i])
813 - (char *) klass->methods);
814 rmethod->declaringClass = klass;
819 throw new java::lang::NoSuchMethodException (name);
822 // Private accessor method for Java code to retrieve the protection domain.
823 java::security::ProtectionDomain *
824 java::lang::Class::getProtectionDomain0 ()
826 return protectionDomain;
830 java::lang::Class::getSigners()
836 java::lang::Class::setSigners(JArray<jobject> *s)
844 // Some class-related convenience functions.
847 // Find a method declared in the class. If it is not declared locally
848 // (or if it is inherited), return NULL.
850 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
851 _Jv_Utf8Const *signature)
853 for (int i = 0; i < klass->method_count; ++i)
855 if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
856 && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
857 return &klass->methods[i];
863 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
864 _Jv_Utf8Const *signature,
865 jclass *declarer_result)
867 for (; klass; klass = klass->getSuperclass())
869 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
874 *declarer_result = klass;
882 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
883 #define MCACHE_SIZE 1023
891 static _Jv_mcache method_cache[MCACHE_SIZE + 1];
894 _Jv_FindMethodInCache (jclass klass,
896 _Jv_Utf8Const *signature)
898 int index = name->hash16 () & MCACHE_SIZE;
899 _Jv_mcache *mc = method_cache + index;
900 _Jv_Method *m = mc->method;
902 if (mc->klass == klass
903 && m != NULL // thread safe check
904 && _Jv_equalUtf8Consts (m->name, name)
905 && _Jv_equalUtf8Consts (m->signature, signature))
906 return mc->method->ncode;
911 _Jv_AddMethodToCache (jclass klass,
914 _Jv_MonitorEnter (&java::lang::Class::class$);
916 int index = method->name->hash16 () & MCACHE_SIZE;
918 method_cache[index].method = method;
919 method_cache[index].klass = klass;
921 _Jv_MonitorExit (&java::lang::Class::class$);
925 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
926 _Jv_Utf8Const *signature)
928 using namespace java::lang::reflect;
930 void *ncode = _Jv_FindMethodInCache (klass, name, signature);
934 for (; klass; klass = klass->getSuperclass())
936 _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
940 if (Modifier::isStatic(meth->accflags))
941 throw new java::lang::IncompatibleClassChangeError
942 (_Jv_GetMethodString (klass, meth));
943 if (Modifier::isAbstract(meth->accflags))
944 throw new java::lang::AbstractMethodError
945 (_Jv_GetMethodString (klass, meth));
946 if (! Modifier::isPublic(meth->accflags))
947 throw new java::lang::IllegalAccessError
948 (_Jv_GetMethodString (klass, meth));
950 _Jv_AddMethodToCache (klass, meth);
954 throw new java::lang::IncompatibleClassChangeError;
957 // Fast interface method lookup by index.
959 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
961 _Jv_IDispatchTable *cldt = klass->idt;
962 int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx;
963 return cldt->cls.itable[idx];
967 _Jv_IsAssignableFrom (jclass source, jclass target)
969 if (source == target)
972 // If target is array, so must source be.
973 while (target->isArray ())
975 if (! source->isArray())
977 target = target->getComponentType();
978 source = source->getComponentType();
981 if (target->isInterface())
983 // Abstract classes have no IDT, and IDTs provide no way to check
984 // two interfaces for assignability.
986 (source->idt == NULL || source->isInterface(), false))
987 return _Jv_InterfaceAssignableFrom (source, target);
989 _Jv_IDispatchTable *cl_idt = source->idt;
990 _Jv_IDispatchTable *if_idt = target->idt;
992 if (__builtin_expect ((if_idt == NULL), false))
993 return false; // No class implementing TARGET has been loaded.
994 jshort cl_iindex = cl_idt->cls.iindex;
995 if (cl_iindex < if_idt->iface.ioffsets[0])
997 jshort offset = if_idt->iface.ioffsets[cl_iindex];
998 if (offset != -1 && offset < cl_idt->cls.itable_length
999 && cl_idt->cls.itable[offset] == target)
1005 // Primitive TYPE classes are only assignable to themselves.
1006 if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1009 if (target == &java::lang::Object::class$)
1011 else if (source->ancestors == NULL || target->ancestors == NULL)
1013 // We need this case when either SOURCE or TARGET has not has
1014 // its constant-time tables prepared.
1016 // At this point we know that TARGET can't be Object, so it is
1017 // safe to use that as the termination point.
1018 while (source && source != &java::lang::Object::class$)
1020 if (source == target)
1022 source = source->getSuperclass();
1025 else if (source->depth >= target->depth
1026 && source->ancestors[source->depth - target->depth] == target)
1032 // Interface type checking, the slow way. Returns TRUE if IFACE is a
1033 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1034 // or a class with no interface dispatch table.
1036 _Jv_InterfaceAssignableFrom (jclass source, jclass iface)
1038 for (int i = 0; i < source->interface_count; i++)
1040 jclass interface = source->interfaces[i];
1041 if (iface == interface
1042 || _Jv_InterfaceAssignableFrom (interface, iface))
1046 if (!source->isInterface()
1047 && source->superclass
1048 && _Jv_InterfaceAssignableFrom (source->superclass, iface))
1055 _Jv_IsInstanceOf(jobject obj, jclass cl)
1057 if (__builtin_expect (!obj, false))
1059 return _Jv_IsAssignableFrom (JV_CLASS (obj), cl);
1063 _Jv_CheckCast (jclass c, jobject obj)
1065 if (__builtin_expect
1066 (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false))
1067 throw new java::lang::ClassCastException
1068 ((new java::lang::StringBuffer
1069 (obj->getClass()->getName()))->append
1070 (JvNewStringUTF(" cannot be cast to "))->append
1071 (c->getName())->toString());
1077 _Jv_CheckArrayStore (jobject arr, jobject obj)
1081 JvAssert (arr != NULL);
1082 jclass elt_class = (JV_CLASS (arr))->getComponentType();
1083 if (elt_class == &java::lang::Object::class$)
1085 jclass obj_class = JV_CLASS (obj);
1086 if (__builtin_expect
1087 (! _Jv_IsAssignableFrom (obj_class, elt_class), false))
1088 throw new java::lang::ArrayStoreException
1089 ((new java::lang::StringBuffer
1090 (JvNewStringUTF("Cannot store ")))->append
1091 (obj_class->getName())->append
1092 (JvNewStringUTF(" in array of type "))->append
1093 (elt_class->getName())->toString());
1098 _Jv_IsAssignableFromSlow (jclass source, jclass target)
1100 // First, strip arrays.
1101 while (target->isArray ())
1103 // If target is array, source must be as well.
1104 if (! source->isArray ())
1106 target = target->getComponentType ();
1107 source = source->getComponentType ();
1111 if (target == &java::lang::Object::class$)
1114 // Ensure that the classes have their supers installed.
1115 _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
1116 _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);
1120 if (source == target)
1123 if (target->isPrimitive () || source->isPrimitive ())
1126 if (target->isInterface ())
1128 for (int i = 0; i < source->interface_count; ++i)
1130 // We use a recursive call because we also need to
1131 // check superinterfaces.
1132 if (_Jv_IsAssignableFromSlow (source->getInterface (i), target))
1136 source = source->getSuperclass ();
1138 while (source != NULL);
1143 // Lookup an interface method by name. This is very similar to
1144 // purpose to _getMethod, but the interfaces are quite different. It
1145 // might be a good idea for _getMethod to call this function.
1147 // Return true of the method is found, with the class in FOUND_CLASS
1148 // and the index in INDEX.
1150 _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
1151 const _Jv_Utf8Const *utf_name,
1152 const _Jv_Utf8Const *utf_sig)
1154 for (jclass klass = search_class; klass; klass = klass->getSuperclass())
1156 // FIXME: Throw an exception?
1157 if (!klass->isInterface ())
1160 int i = klass->method_count;
1163 if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1164 && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
1167 using namespace java::lang::reflect;
1169 // FIXME: Method must be public. Throw an exception?
1170 if (! Modifier::isPublic (klass->methods[i].accflags))
1173 found_class = klass;
1174 // Interface method indexes count from 1.
1181 // If we haven't found a match, and this class is an interface, then
1182 // check all the superinterfaces.
1183 if (search_class->isInterface())
1185 for (int i = 0; i < search_class->interface_count; ++i)
1187 using namespace java::lang::reflect;
1188 bool found = _Jv_getInterfaceMethod (search_class->interfaces[i],