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")));
129 // This particular 'return' has been changed a couple of times over
130 // libgcj's history. This particular approach is a little weird,
131 // because it means that all classes linked into the application
132 // will see NULL for their class loader. This may confuse some
133 // applications that aren't expecting this; the solution is to use a
134 // different linking model for these applications. In the past we
135 // returned the system class loader in this case, but that is
136 // incorrect. Also, back then we didn't have other linkage models
141 java::lang::reflect::Constructor
*
142 java::lang::Class::getConstructor (JArray
<jclass
> *param_types
)
144 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
146 jstring partial_sig
= getSignature (param_types
, true);
147 jint hash
= partial_sig
->hashCode ();
149 int i
= isPrimitive () ? 0 : method_count
;
152 if (_Jv_equalUtf8Consts (methods
[i
].name
, init_name
)
153 && _Jv_equal (methods
[i
].signature
, partial_sig
, hash
))
155 // Found it. For getConstructor, the constructor must be
157 using namespace java::lang::reflect
;
158 if (! Modifier::isPublic(methods
[i
].accflags
))
160 Constructor
*cons
= new Constructor ();
161 cons
->offset
= (char *) (&methods
[i
]) - (char *) methods
;
162 cons
->declaringClass
= this;
166 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name
));
169 JArray
<java::lang::reflect::Constructor
*> *
170 java::lang::Class::_getConstructors (jboolean declared
)
172 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
174 int numConstructors
= 0;
175 int max
= isPrimitive () ? 0 : method_count
;
177 for (i
= max
; --i
>= 0; )
179 _Jv_Method
*method
= &methods
[i
];
180 if (method
->name
== NULL
181 || ! _Jv_equalUtf8Consts (method
->name
, init_name
))
184 && ! java::lang::reflect::Modifier::isPublic(method
->accflags
))
188 JArray
<java::lang::reflect::Constructor
*> *result
189 = (JArray
<java::lang::reflect::Constructor
*> *)
190 JvNewObjectArray (numConstructors
,
191 &java::lang::reflect::Constructor::class$
,
193 java::lang::reflect::Constructor
** cptr
= elements (result
);
194 for (i
= 0; i
< max
; i
++)
196 _Jv_Method
*method
= &methods
[i
];
197 if (method
->name
== NULL
198 || ! _Jv_equalUtf8Consts (method
->name
, init_name
))
201 && ! java::lang::reflect::Modifier::isPublic(method
->accflags
))
203 java::lang::reflect::Constructor
*cons
204 = new java::lang::reflect::Constructor ();
205 cons
->offset
= (char *) method
- (char *) methods
;
206 cons
->declaringClass
= this;
212 java::lang::reflect::Constructor
*
213 java::lang::Class::getDeclaredConstructor (JArray
<jclass
> *param_types
)
215 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
217 jstring partial_sig
= getSignature (param_types
, true);
218 jint hash
= partial_sig
->hashCode ();
220 int i
= isPrimitive () ? 0 : method_count
;
223 if (_Jv_equalUtf8Consts (methods
[i
].name
, init_name
)
224 && _Jv_equal (methods
[i
].signature
, partial_sig
, hash
))
227 using namespace java::lang::reflect
;
228 Constructor
*cons
= new Constructor ();
229 cons
->offset
= (char *) (&methods
[i
]) - (char *) methods
;
230 cons
->declaringClass
= this;
234 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name
));
237 java::lang::reflect::Field
*
238 java::lang::Class::getField (jstring name
, jint hash
)
240 java::lang::reflect::Field
* rfield
;
241 for (int i
= 0; i
< field_count
; i
++)
243 _Jv_Field
*field
= &fields
[i
];
244 if (! _Jv_equal (field
->name
, name
, hash
))
246 if (! (field
->getModifiers() & java::lang::reflect::Modifier::PUBLIC
))
248 rfield
= new java::lang::reflect::Field ();
249 rfield
->offset
= (char*) field
- (char*) fields
;
250 rfield
->declaringClass
= this;
254 jclass superclass
= getSuperclass();
255 if (superclass
== NULL
)
257 rfield
= superclass
->getField(name
, hash
);
258 for (int i
= 0; i
< interface_count
&& rfield
== NULL
; ++i
)
259 rfield
= interfaces
[i
]->getField (name
, hash
);
263 java::lang::reflect::Field
*
264 java::lang::Class::getDeclaredField (jstring name
)
266 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
267 int hash
= name
->hashCode();
268 for (int i
= 0; i
< field_count
; i
++)
270 _Jv_Field
*field
= &fields
[i
];
271 if (! _Jv_equal (field
->name
, name
, hash
))
273 java::lang::reflect::Field
* rfield
= new java::lang::reflect::Field ();
274 rfield
->offset
= (char*) field
- (char*) fields
;
275 rfield
->declaringClass
= this;
279 throw new java::lang::NoSuchFieldException (name
);
282 JArray
<java::lang::reflect::Field
*> *
283 java::lang::Class::getDeclaredFields (jboolean public_only
)
289 for (int i
= 0; i
< field_count
; ++i
)
291 _Jv_Field
*field
= &fields
[i
];
292 if ((field
->flags
& java::lang::reflect::Modifier::PUBLIC
))
299 JArray
<java::lang::reflect::Field
*> *result
300 = (JArray
<java::lang::reflect::Field
*> *)
301 JvNewObjectArray (size
, &java::lang::reflect::Field::class$
, NULL
);
302 java::lang::reflect::Field
** fptr
= elements (result
);
303 for (int i
= 0; i
< field_count
; i
++)
305 _Jv_Field
*field
= &fields
[i
];
307 && ! (field
->flags
& java::lang::reflect::Modifier::PUBLIC
))
309 java::lang::reflect::Field
* rfield
= new java::lang::reflect::Field ();
310 rfield
->offset
= (char*) field
- (char*) fields
;
311 rfield
->declaringClass
= this;
318 java::lang::Class::getSignature (java::lang::StringBuffer
*buffer
)
321 buffer
->append((jchar
) method_count
);
324 jstring name
= getName();
325 if (name
->charAt(0) != '[')
326 buffer
->append((jchar
) 'L');
327 buffer
->append(name
);
328 if (name
->charAt(0) != '[')
329 buffer
->append((jchar
) ';');
333 // This doesn't have to be native. It is an implementation detail
334 // only called from the C++ code, though, so maybe this is clearer.
336 java::lang::Class::getSignature (JArray
<jclass
> *param_types
,
337 jboolean is_constructor
)
339 java::lang::StringBuffer
*buf
= new java::lang::StringBuffer ();
340 buf
->append((jchar
) '(');
341 // A NULL param_types means "no parameters".
342 if (param_types
!= NULL
)
344 jclass
*v
= elements (param_types
);
345 for (int i
= 0; i
< param_types
->length
; ++i
)
346 v
[i
]->getSignature(buf
);
348 buf
->append((jchar
) ')');
350 buf
->append((jchar
) 'V');
351 return buf
->toString();
354 java::lang::reflect::Method
*
355 java::lang::Class::_getDeclaredMethod (jstring name
,
356 JArray
<jclass
> *param_types
)
358 jstring partial_sig
= getSignature (param_types
, false);
359 jint p_len
= partial_sig
->length();
360 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
361 int i
= isPrimitive () ? 0 : method_count
;
364 if (_Jv_equalUtf8Consts (methods
[i
].name
, utf_name
)
365 && _Jv_equaln (methods
[i
].signature
, partial_sig
, p_len
)
366 && (methods
[i
].accflags
367 & java::lang::reflect::Modifier::INVISIBLE
) == 0)
370 using namespace java::lang::reflect
;
371 Method
*rmethod
= new Method ();
372 rmethod
->offset
= (char*) (&methods
[i
]) - (char*) methods
;
373 rmethod
->declaringClass
= this;
380 JArray
<java::lang::reflect::Method
*> *
381 java::lang::Class::getDeclaredMethods (void)
383 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
386 int max
= isPrimitive () ? 0 : method_count
;
388 for (i
= max
; --i
>= 0; )
390 _Jv_Method
*method
= &methods
[i
];
391 if (method
->name
== NULL
392 || _Jv_equalUtf8Consts (method
->name
, clinit_name
)
393 || _Jv_equalUtf8Consts (method
->name
, init_name
)
394 || _Jv_equalUtf8Consts (method
->name
, finit_name
)
395 || (methods
[i
].accflags
396 & java::lang::reflect::Modifier::INVISIBLE
) != 0)
400 JArray
<java::lang::reflect::Method
*> *result
401 = (JArray
<java::lang::reflect::Method
*> *)
402 JvNewObjectArray (numMethods
, &java::lang::reflect::Method::class$
, NULL
);
403 java::lang::reflect::Method
** mptr
= elements (result
);
404 for (i
= 0; i
< max
; i
++)
406 _Jv_Method
*method
= &methods
[i
];
407 if (method
->name
== NULL
408 || _Jv_equalUtf8Consts (method
->name
, clinit_name
)
409 || _Jv_equalUtf8Consts (method
->name
, init_name
)
410 || _Jv_equalUtf8Consts (method
->name
, finit_name
)
411 || (methods
[i
].accflags
412 & java::lang::reflect::Modifier::INVISIBLE
) != 0)
414 java::lang::reflect::Method
* rmethod
415 = new java::lang::reflect::Method ();
416 rmethod
->offset
= (char*) method
- (char*) methods
;
417 rmethod
->declaringClass
= this;
424 java::lang::Class::getName (void)
426 return name
->toString();
430 java::lang::Class::getClasses (void)
432 // FIXME: security checking.
434 // Until we have inner classes, it always makes sense to return an
436 JArray
<jclass
> *result
437 = (JArray
<jclass
> *) JvNewObjectArray (0, &java::lang::Class::class$
,
443 java::lang::Class::getDeclaredClasses (void)
445 memberAccessCheck (java::lang::reflect::Member::DECLARED
);
446 // Until we have inner classes, it always makes sense to return an
448 JArray
<jclass
> *result
449 = (JArray
<jclass
> *) JvNewObjectArray (0, &java::lang::Class::class$
,
455 java::lang::Class::getDeclaringClass (void)
457 // Until we have inner classes, it makes sense to always return
463 java::lang::Class::getInterfaces (void)
465 jobjectArray r
= JvNewObjectArray (interface_count
, getClass (), NULL
);
466 jobject
*data
= elements (r
);
467 for (int i
= 0; i
< interface_count
; ++i
)
469 typedef unsigned int uaddr
__attribute__ ((mode (pointer
)));
470 data
[i
] = interfaces
[i
];
471 if ((uaddr
)data
[i
] < (uaddr
)constants
.size
)
472 fprintf (stderr
, "ERROR !!!\n");
474 return reinterpret_cast<JArray
<jclass
> *> (r
);
477 java::lang::reflect::Method
*
478 java::lang::Class::_getMethod (jstring name
, JArray
<jclass
> *param_types
)
480 jstring partial_sig
= getSignature (param_types
, false);
481 jint p_len
= partial_sig
->length();
482 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
484 for (Class
*klass
= this; klass
; klass
= klass
->getSuperclass())
486 int i
= klass
->isPrimitive () ? 0 : klass
->method_count
;
489 if (_Jv_equalUtf8Consts (klass
->methods
[i
].name
, utf_name
)
490 && _Jv_equaln (klass
->methods
[i
].signature
, partial_sig
, p_len
)
491 && (klass
->methods
[i
].accflags
492 & java::lang::reflect::Modifier::INVISIBLE
) == 0)
495 using namespace java::lang::reflect
;
497 // Method must be public.
498 if (! Modifier::isPublic (klass
->methods
[i
].accflags
))
501 Method
*rmethod
= new Method ();
502 rmethod
->offset
= ((char *) (&klass
->methods
[i
])
503 - (char *) klass
->methods
);
504 rmethod
->declaringClass
= klass
;
510 // If we haven't found a match, and this class is an interface, then
511 // check all the superinterfaces.
514 for (int i
= 0; i
< interface_count
; ++i
)
516 using namespace java::lang::reflect
;
517 Method
*rmethod
= interfaces
[i
]->_getMethod (name
, param_types
);
526 // This is a very slow implementation, since it re-scans all the
527 // methods we've already listed to make sure we haven't duplicated a
528 // method. It also over-estimates the required size, so we have to
529 // shrink the result array later.
531 java::lang::Class::_getMethods (JArray
<java::lang::reflect::Method
*> *result
,
536 // First examine all local methods
537 for (int i
= isPrimitive () ? 0 : method_count
; --i
>= 0; )
539 _Jv_Method
*method
= &methods
[i
];
540 if (method
->name
== NULL
541 || _Jv_equalUtf8Consts (method
->name
, clinit_name
)
542 || _Jv_equalUtf8Consts (method
->name
, init_name
)
543 || _Jv_equalUtf8Consts (method
->name
, finit_name
)
545 & java::lang::reflect::Modifier::INVISIBLE
) != 0)
547 // Only want public methods.
548 if (! java::lang::reflect::Modifier::isPublic (method
->accflags
))
551 // This is where we over-count the slots required if we aren't
552 // filling the result for real.
556 java::lang::reflect::Method
**mp
= elements (result
);
557 // If we already have a method with this name and signature,
558 // then ignore this one. This can happen with virtual
560 for (int j
= 0; j
< offset
; ++j
)
562 _Jv_Method
*meth_2
= _Jv_FromReflectedMethod (mp
[j
]);
563 if (_Jv_equalUtf8Consts (method
->name
, meth_2
->name
)
564 && _Jv_equalUtf8Consts (method
->signature
,
577 using namespace java::lang::reflect
;
578 Method
*rmethod
= new Method ();
579 rmethod
->offset
= (char *) method
- (char *) methods
;
580 rmethod
->declaringClass
= this;
581 Method
**mp
= elements (result
);
582 mp
[offset
+ count
] = rmethod
;
588 // Now examine superclasses.
589 if (getSuperclass () != NULL
)
591 jint s_count
= getSuperclass()->_getMethods (result
, offset
);
596 // Finally, examine interfaces.
597 for (int i
= 0; i
< interface_count
; ++i
)
599 int f_count
= interfaces
[i
]->_getMethods (result
, offset
);
607 JArray
<java::lang::reflect::Method
*> *
608 java::lang::Class::getMethods (void)
610 using namespace java::lang::reflect
;
612 memberAccessCheck(Member::PUBLIC
);
614 // This will overestimate the size we need.
615 jint count
= _getMethods (NULL
, 0);
617 JArray
<Method
*> *result
618 = ((JArray
<Method
*> *) JvNewObjectArray (count
,
622 // When filling the array for real, we get the actual count. Then
623 // we resize the array.
624 jint real_count
= _getMethods (result
, 0);
626 if (real_count
!= count
)
629 = ((JArray
<Method
*> *) JvNewObjectArray (real_count
,
633 Method
**destp
= elements (r2
);
634 Method
**srcp
= elements (result
);
636 for (int i
= 0; i
< real_count
; ++i
)
646 java::lang::Class::isAssignableFrom (jclass klass
)
648 // Arguments may not have been initialized, given ".class" syntax.
649 _Jv_InitClass (this);
650 _Jv_InitClass (klass
);
651 return _Jv_IsAssignableFrom (this, klass
);
655 java::lang::Class::isInstance (jobject obj
)
659 _Jv_InitClass (this);
660 return _Jv_IsAssignableFrom (this, JV_CLASS (obj
));
664 java::lang::Class::newInstance (void)
666 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
671 || java::lang::reflect::Modifier::isAbstract(accflags
))
672 throw new java::lang::InstantiationException (getName ());
674 _Jv_InitClass (this);
676 _Jv_Method
*meth
= _Jv_GetMethodLocal (this, init_name
, void_signature
);
678 throw new java::lang::InstantiationException (getName());
680 jobject r
= _Jv_AllocObject (this);
681 ((void (*) (jobject
)) meth
->ncode
) (r
);
686 java::lang::Class::finalize (void)
688 engine
->unregister(this);
691 // This implements the initialization process for a class. From Spec
694 java::lang::Class::initializeClass (void)
696 // Short-circuit to avoid needless locking.
697 if (state
== JV_STATE_DONE
)
700 // Step 1. We introduce a new scope so we can synchronize more
703 JvSynchronize
sync (this);
705 if (state
< JV_STATE_LINKED
)
709 _Jv_Linker::wait_for_state(this, JV_STATE_LINKED
);
711 catch (java::lang::Throwable
*x
)
713 // Turn into a NoClassDefFoundError.
714 java::lang::NoClassDefFoundError
*result
715 = new java::lang::NoClassDefFoundError(getName());
716 result
->initCause(x
);
722 java::lang::Thread
*self
= java::lang::Thread::currentThread();
723 self
= (java::lang::Thread
*) ((long) self
| 1);
724 while (state
== JV_STATE_IN_PROGRESS
&& thread
&& thread
!= self
)
728 if (state
== JV_STATE_DONE
|| state
== JV_STATE_IN_PROGRESS
)
732 if (state
== JV_STATE_ERROR
)
733 throw new java::lang::NoClassDefFoundError (getName());
737 _Jv_Linker::wait_for_state (this, JV_STATE_LINKED
);
738 state
= JV_STATE_IN_PROGRESS
;
742 if (! isInterface () && superclass
)
746 _Jv_InitClass (superclass
);
748 catch (java::lang::Throwable
*except
)
750 // Caught an exception.
751 JvSynchronize
sync (this);
752 state
= JV_STATE_ERROR
;
758 // Steps 8, 9, 10, 11.
761 _Jv_Method
*meth
= _Jv_GetMethodLocal (this, clinit_name
,
764 ((void (*) (void)) meth
->ncode
) ();
766 catch (java::lang::Throwable
*except
)
768 if (! java::lang::Error::class$
.isInstance(except
))
772 except
= new ExceptionInInitializerError (except
);
774 catch (java::lang::Throwable
*t
)
780 JvSynchronize
sync (this);
781 state
= JV_STATE_ERROR
;
786 JvSynchronize
sync (this);
787 state
= JV_STATE_DONE
;
791 // Only used by serialization
792 java::lang::reflect::Field
*
793 java::lang::Class::getPrivateField (jstring name
)
795 int hash
= name
->hashCode ();
797 java::lang::reflect::Field
* rfield
;
798 for (int i
= 0; i
< field_count
; i
++)
800 _Jv_Field
*field
= &fields
[i
];
801 if (! _Jv_equal (field
->name
, name
, hash
))
803 rfield
= new java::lang::reflect::Field ();
804 rfield
->offset
= (char*) field
- (char*) fields
;
805 rfield
->declaringClass
= this;
809 jclass superclass
= getSuperclass();
810 if (superclass
== NULL
)
812 rfield
= superclass
->getPrivateField(name
);
813 for (int i
= 0; i
< interface_count
&& rfield
== NULL
; ++i
)
814 rfield
= interfaces
[i
]->getPrivateField (name
);
818 // Only used by serialization
819 java::lang::reflect::Method
*
820 java::lang::Class::getPrivateMethod (jstring name
, JArray
<jclass
> *param_types
)
822 jstring partial_sig
= getSignature (param_types
, false);
823 jint p_len
= partial_sig
->length();
824 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
825 for (Class
*klass
= this; klass
; klass
= klass
->getSuperclass())
827 int i
= klass
->isPrimitive () ? 0 : klass
->method_count
;
830 if (_Jv_equalUtf8Consts (klass
->methods
[i
].name
, utf_name
)
831 && _Jv_equaln (klass
->methods
[i
].signature
, partial_sig
, p_len
))
834 using namespace java::lang::reflect
;
836 Method
*rmethod
= new Method ();
837 rmethod
->offset
= ((char *) (&klass
->methods
[i
])
838 - (char *) klass
->methods
);
839 rmethod
->declaringClass
= klass
;
844 throw new java::lang::NoSuchMethodException (name
);
847 // Private accessor method for Java code to retrieve the protection domain.
848 java::security::ProtectionDomain
*
849 java::lang::Class::getProtectionDomain0 ()
851 return protectionDomain
;
855 java::lang::Class::getSigners()
861 java::lang::Class::setSigners(JArray
<jobject
> *s
)
869 // Some class-related convenience functions.
872 // Find a method declared in the class. If it is not declared locally
873 // (or if it is inherited), return NULL.
875 _Jv_GetMethodLocal (jclass klass
, _Jv_Utf8Const
*name
,
876 _Jv_Utf8Const
*signature
)
878 for (int i
= 0; i
< klass
->method_count
; ++i
)
880 if (_Jv_equalUtf8Consts (name
, klass
->methods
[i
].name
)
881 && _Jv_equalUtf8Consts (signature
, klass
->methods
[i
].signature
))
882 return &klass
->methods
[i
];
888 _Jv_LookupDeclaredMethod (jclass klass
, _Jv_Utf8Const
*name
,
889 _Jv_Utf8Const
*signature
,
890 jclass
*declarer_result
)
892 for (; klass
; klass
= klass
->getSuperclass())
894 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
899 *declarer_result
= klass
;
907 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
908 #define MCACHE_SIZE 1023
916 static _Jv_mcache method_cache
[MCACHE_SIZE
+ 1];
919 _Jv_FindMethodInCache (jclass klass
,
921 _Jv_Utf8Const
*signature
)
923 int index
= name
->hash16 () & MCACHE_SIZE
;
924 _Jv_mcache
*mc
= method_cache
+ index
;
925 _Jv_Method
*m
= mc
->method
;
927 if (mc
->klass
== klass
928 && m
!= NULL
// thread safe check
929 && _Jv_equalUtf8Consts (m
->name
, name
)
930 && _Jv_equalUtf8Consts (m
->signature
, signature
))
931 return mc
->method
->ncode
;
936 _Jv_AddMethodToCache (jclass klass
,
939 _Jv_MonitorEnter (&java::lang::Class::class$
);
941 int index
= method
->name
->hash16 () & MCACHE_SIZE
;
943 method_cache
[index
].method
= method
;
944 method_cache
[index
].klass
= klass
;
946 _Jv_MonitorExit (&java::lang::Class::class$
);
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 target
, jclass source
)
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 (target
, source
);
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 iface
, jclass source
)
1063 for (int i
= 0; i
< source
->interface_count
; i
++)
1065 jclass interface
= source
->interfaces
[i
];
1066 if (iface
== interface
1067 || _Jv_InterfaceAssignableFrom (iface
, interface
))
1071 if (!source
->isInterface()
1072 && source
->superclass
1073 && _Jv_InterfaceAssignableFrom (iface
, source
->superclass
))
1080 _Jv_IsInstanceOf(jobject obj
, jclass cl
)
1082 if (__builtin_expect (!obj
, false))
1084 return (_Jv_IsAssignableFrom (cl
, JV_CLASS (obj
)));
1088 _Jv_CheckCast (jclass c
, jobject obj
)
1090 if (__builtin_expect
1091 (obj
!= NULL
&& ! _Jv_IsAssignableFrom(c
, JV_CLASS (obj
)), 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 (elt_class
, obj_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 target
, jclass source
)
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 (target
, source
->getInterface (i
)))
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
],