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
;
884 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
885 #define MCACHE_SIZE 31
893 static __thread _Jv_mcache
*method_cache
;
897 _Jv_FindMethodInCache (jclass klass
,
899 _Jv_Utf8Const
*signature
)
902 _Jv_mcache
*cache
= method_cache
;
905 int index
= name
->hash16 () & MCACHE_SIZE
;
906 _Jv_mcache
*mc
= &cache
[index
];
907 _Jv_Method
*m
= mc
->method
;
909 if (mc
->klass
== klass
910 && _Jv_equalUtf8Consts (m
->name
, name
)
911 && _Jv_equalUtf8Consts (m
->signature
, signature
))
912 return mc
->method
->ncode
;
919 _Jv_AddMethodToCache (jclass klass
, _Jv_Method
*method
)
922 if (method_cache
== NULL
)
923 method_cache
= (_Jv_mcache
*) _Jv_MallocUnchecked((MCACHE_SIZE
+ 1)
924 * sizeof (_Jv_mcache
));
925 // If the allocation failed, just keep going.
926 if (method_cache
!= NULL
)
928 int index
= method
->name
->hash16 () & MCACHE_SIZE
;
929 method_cache
[index
].method
= method
;
930 method_cache
[index
].klass
= klass
;
935 // Free this thread's method cache. We explicitly manage this memory
936 // as the GC does not yet know how to scan TLS on all platforms.
938 _Jv_FreeMethodCache ()
941 if (method_cache
!= NULL
)
943 _Jv_Free(method_cache
);
950 _Jv_LookupInterfaceMethod (jclass klass
, _Jv_Utf8Const
*name
,
951 _Jv_Utf8Const
*signature
)
953 using namespace java::lang::reflect
;
955 void *ncode
= _Jv_FindMethodInCache (klass
, name
, signature
);
959 for (; klass
; klass
= klass
->getSuperclass())
961 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
965 if (Modifier::isStatic(meth
->accflags
))
966 throw new java::lang::IncompatibleClassChangeError
967 (_Jv_GetMethodString (klass
, meth
));
968 if (Modifier::isAbstract(meth
->accflags
))
969 throw new java::lang::AbstractMethodError
970 (_Jv_GetMethodString (klass
, meth
));
971 if (! Modifier::isPublic(meth
->accflags
))
972 throw new java::lang::IllegalAccessError
973 (_Jv_GetMethodString (klass
, meth
));
975 _Jv_AddMethodToCache (klass
, meth
);
979 throw new java::lang::IncompatibleClassChangeError
;
982 // Fast interface method lookup by index.
984 _Jv_LookupInterfaceMethodIdx (jclass klass
, jclass iface
, int method_idx
)
986 _Jv_IDispatchTable
*cldt
= klass
->idt
;
987 int idx
= iface
->idt
->iface
.ioffsets
[cldt
->cls
.iindex
] + method_idx
;
988 return cldt
->cls
.itable
[idx
];
992 _Jv_IsAssignableFrom (jclass source
, jclass target
)
994 if (source
== target
)
997 // If target is array, so must source be.
998 while (target
->isArray ())
1000 if (! source
->isArray())
1002 target
= target
->getComponentType();
1003 source
= source
->getComponentType();
1006 if (target
->isInterface())
1008 // Abstract classes have no IDT, and IDTs provide no way to check
1009 // two interfaces for assignability.
1010 if (__builtin_expect
1011 (source
->idt
== NULL
|| source
->isInterface(), false))
1012 return _Jv_InterfaceAssignableFrom (source
, target
);
1014 _Jv_IDispatchTable
*cl_idt
= source
->idt
;
1015 _Jv_IDispatchTable
*if_idt
= target
->idt
;
1017 if (__builtin_expect ((if_idt
== NULL
), false))
1018 return false; // No class implementing TARGET has been loaded.
1019 jshort cl_iindex
= cl_idt
->cls
.iindex
;
1020 if (cl_iindex
< if_idt
->iface
.ioffsets
[0])
1022 jshort offset
= if_idt
->iface
.ioffsets
[cl_iindex
];
1023 if (offset
!= -1 && offset
< cl_idt
->cls
.itable_length
1024 && cl_idt
->cls
.itable
[offset
] == target
)
1030 // Primitive TYPE classes are only assignable to themselves.
1031 if (__builtin_expect (target
->isPrimitive() || source
->isPrimitive(), false))
1034 if (target
== &java::lang::Object::class$
)
1036 else if (source
->ancestors
== NULL
|| target
->ancestors
== NULL
)
1038 // We need this case when either SOURCE or TARGET has not has
1039 // its constant-time tables prepared.
1041 // At this point we know that TARGET can't be Object, so it is
1042 // safe to use that as the termination point.
1043 while (source
&& source
!= &java::lang::Object::class$
)
1045 if (source
== target
)
1047 source
= source
->getSuperclass();
1050 else if (source
->depth
>= target
->depth
1051 && source
->ancestors
[source
->depth
- target
->depth
] == target
)
1057 // Interface type checking, the slow way. Returns TRUE if IFACE is a
1058 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1059 // or a class with no interface dispatch table.
1061 _Jv_InterfaceAssignableFrom (jclass source
, jclass iface
)
1063 for (int i
= 0; i
< source
->interface_count
; i
++)
1065 jclass interface
= source
->interfaces
[i
];
1066 if (iface
== interface
1067 || _Jv_InterfaceAssignableFrom (interface
, iface
))
1071 if (!source
->isInterface()
1072 && source
->superclass
1073 && _Jv_InterfaceAssignableFrom (source
->superclass
, iface
))
1080 _Jv_IsInstanceOf(jobject obj
, jclass cl
)
1082 if (__builtin_expect (!obj
, false))
1084 return _Jv_IsAssignableFrom (JV_CLASS (obj
), cl
);
1088 _Jv_CheckCast (jclass c
, jobject obj
)
1090 if (__builtin_expect
1091 (obj
!= NULL
&& ! _Jv_IsAssignableFrom(JV_CLASS (obj
), c
), false))
1092 throw new java::lang::ClassCastException
1093 ((new java::lang::StringBuffer
1094 (obj
->getClass()->getName()))->append
1095 (JvNewStringUTF(" cannot be cast to "))->append
1096 (c
->getName())->toString());
1102 _Jv_CheckArrayStore (jobject arr
, jobject obj
)
1106 JvAssert (arr
!= NULL
);
1107 jclass elt_class
= (JV_CLASS (arr
))->getComponentType();
1108 if (elt_class
== &java::lang::Object::class$
)
1110 jclass obj_class
= JV_CLASS (obj
);
1111 if (__builtin_expect
1112 (! _Jv_IsAssignableFrom (obj_class
, elt_class
), false))
1113 throw new java::lang::ArrayStoreException
1114 ((new java::lang::StringBuffer
1115 (JvNewStringUTF("Cannot store ")))->append
1116 (obj_class
->getName())->append
1117 (JvNewStringUTF(" in array of type "))->append
1118 (elt_class
->getName())->toString());
1123 _Jv_IsAssignableFromSlow (jclass source
, jclass target
)
1125 // First, strip arrays.
1126 while (target
->isArray ())
1128 // If target is array, source must be as well.
1129 if (! source
->isArray ())
1131 target
= target
->getComponentType ();
1132 source
= source
->getComponentType ();
1136 if (target
== &java::lang::Object::class$
)
1139 // Ensure that the classes have their supers installed.
1140 _Jv_Linker::wait_for_state (source
, JV_STATE_LOADING
);
1141 _Jv_Linker::wait_for_state (target
, JV_STATE_LOADING
);
1145 if (source
== target
)
1148 if (target
->isPrimitive () || source
->isPrimitive ())
1151 if (target
->isInterface ())
1153 for (int i
= 0; i
< source
->interface_count
; ++i
)
1155 // We use a recursive call because we also need to
1156 // check superinterfaces.
1157 if (_Jv_IsAssignableFromSlow (source
->getInterface (i
), target
))
1161 source
= source
->getSuperclass ();
1163 while (source
!= NULL
);
1168 // Lookup an interface method by name. This is very similar to
1169 // purpose to _getMethod, but the interfaces are quite different. It
1170 // might be a good idea for _getMethod to call this function.
1172 // Return true of the method is found, with the class in FOUND_CLASS
1173 // and the index in INDEX.
1175 _Jv_getInterfaceMethod (jclass search_class
, jclass
&found_class
, int &index
,
1176 const _Jv_Utf8Const
*utf_name
,
1177 const _Jv_Utf8Const
*utf_sig
)
1179 for (jclass klass
= search_class
; klass
; klass
= klass
->getSuperclass())
1181 // FIXME: Throw an exception?
1182 if (!klass
->isInterface ())
1185 int i
= klass
->method_count
;
1188 if (_Jv_equalUtf8Consts (klass
->methods
[i
].name
, utf_name
)
1189 && _Jv_equalUtf8Consts (klass
->methods
[i
].signature
, utf_sig
))
1192 using namespace java::lang::reflect
;
1194 // FIXME: Method must be public. Throw an exception?
1195 if (! Modifier::isPublic (klass
->methods
[i
].accflags
))
1198 found_class
= klass
;
1199 // Interface method indexes count from 1.
1206 // If we haven't found a match, and this class is an interface, then
1207 // check all the superinterfaces.
1208 if (search_class
->isInterface())
1210 for (int i
= 0; i
< search_class
->interface_count
; ++i
)
1212 using namespace java::lang::reflect
;
1213 bool found
= _Jv_getInterfaceMethod (search_class
->interfaces
[i
],