1 // natClass.cc - Implementation of java.lang.Class native methods.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
17 #pragma implementation "Class.h"
21 #include <java-threads.h>
23 #include <java/lang/Class.h>
24 #include <java/lang/ClassLoader.h>
25 #include <java/lang/String.h>
26 #include <java/lang/reflect/Modifier.h>
27 #include <java/lang/reflect/Member.h>
28 #include <java/lang/reflect/Method.h>
29 #include <java/lang/reflect/Field.h>
30 #include <java/lang/reflect/Constructor.h>
31 #include <java/lang/AbstractMethodError.h>
32 #include <java/lang/ArrayStoreException.h>
33 #include <java/lang/ClassCastException.h>
34 #include <java/lang/ClassNotFoundException.h>
35 #include <java/lang/ExceptionInInitializerError.h>
36 #include <java/lang/IllegalAccessException.h>
37 #include <java/lang/IllegalAccessError.h>
38 #include <java/lang/IllegalArgumentException.h>
39 #include <java/lang/IncompatibleClassChangeError.h>
40 #include <java/lang/NoSuchFieldError.h>
41 #include <java/lang/ArrayIndexOutOfBoundsException.h>
42 #include <java/lang/InstantiationException.h>
43 #include <java/lang/NoClassDefFoundError.h>
44 #include <java/lang/NoSuchFieldException.h>
45 #include <java/lang/NoSuchMethodError.h>
46 #include <java/lang/NoSuchMethodException.h>
47 #include <java/lang/Thread.h>
48 #include <java/lang/NullPointerException.h>
49 #include <java/lang/RuntimePermission.h>
50 #include <java/lang/System.h>
51 #include <java/lang/SecurityManager.h>
52 #include <java/lang/StringBuffer.h>
53 #include <java/lang/VMClassLoader.h>
54 #include <gnu/gcj/runtime/StackTrace.h>
55 #include <gcj/method.h>
56 #include <gnu/gcj/runtime/MethodRef.h>
57 #include <gnu/gcj/RawData.h>
59 #include <java-cpool.h>
60 #include <java-interp.h>
66 java::lang::Class::forName (jstring className
, jboolean initialize
,
67 java::lang::ClassLoader
*loader
)
70 throw new java::lang::NullPointerException
;
72 jsize length
= _Jv_GetStringUTFLength (className
);
74 _Jv_GetStringUTFRegion (className
, 0, className
->length(), buffer
);
76 _Jv_Utf8Const
*name
= _Jv_makeUtf8Const (buffer
, length
);
78 if (! _Jv_VerifyClassName (name
))
79 throw new java::lang::ClassNotFoundException (className
);
81 jclass klass
= (buffer
[0] == '['
82 ? _Jv_FindClassFromSignature (name
->data
, loader
)
83 : _Jv_FindClass (name
, loader
));
86 throw new java::lang::ClassNotFoundException (className
);
89 _Jv_InitClass (klass
);
95 java::lang::Class::forName (jstring className
)
97 java::lang::ClassLoader
*loader
= NULL
;
98 gnu::gcj::runtime::StackTrace
*t
99 = new gnu::gcj::runtime::StackTrace(4);
100 java::lang::Class
*klass
= NULL
;
103 for (int i
= 1; !klass
; i
++)
105 klass
= t
->classAt (i
);
107 loader
= klass
->getClassLoaderInternal();
109 catch (::java::lang::ArrayIndexOutOfBoundsException
*e
)
113 return forName (className
, true, loader
);
116 java::lang::ClassLoader
*
117 java::lang::Class::getClassLoader (void)
119 java::lang::SecurityManager
*s
= java::lang::System::getSecurityManager();
122 gnu::gcj::runtime::StackTrace
*t
123 = new gnu::gcj::runtime::StackTrace(4);
124 Class
*caller
= NULL
;
125 ClassLoader
*caller_loader
= NULL
;
128 for (int i
= 1; !caller
; i
++)
130 caller
= t
->classAt (i
);
132 caller_loader
= caller
->getClassLoaderInternal();
134 catch (::java::lang::ArrayIndexOutOfBoundsException
*e
)
138 // If the caller has a non-null class loader, and that loader
139 // is not this class' loader or an ancestor thereof, then do a
141 if (caller_loader
!= NULL
&& ! caller_loader
->isAncestorOf(loader
))
142 s
->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
145 // The spec requires us to return `null' for primitive classes. In
146 // other cases we have the option of returning `null' for classes
147 // loaded with the bootstrap loader. All gcj-compiled classes which
148 // are linked into the application used to return `null' here, but
149 // that confuses some poorly-written applications. It is a useful
150 // and apparently harmless compatibility hack to simply never return
154 return loader
? loader
: ClassLoader::getSystemClassLoader ();
157 java::lang::reflect::Constructor
*
158 java::lang::Class::getConstructor (JArray
<jclass
> *param_types
)
160 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
162 jstring partial_sig
= getSignature (param_types
, true);
163 jint hash
= partial_sig
->hashCode ();
165 int i
= isPrimitive () ? 0 : method_count
;
168 if (_Jv_equalUtf8Consts (methods
[i
].name
, init_name
)
169 && _Jv_equal (methods
[i
].signature
, partial_sig
, hash
))
171 // Found it. For getConstructor, the constructor must be
173 using namespace java::lang::reflect
;
174 if (! Modifier::isPublic(methods
[i
].accflags
))
176 Constructor
*cons
= new Constructor ();
177 cons
->offset
= (char *) (&methods
[i
]) - (char *) methods
;
178 cons
->declaringClass
= this;
182 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name
));
185 JArray
<java::lang::reflect::Constructor
*> *
186 java::lang::Class::_getConstructors (jboolean declared
)
188 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
190 int numConstructors
= 0;
191 int max
= isPrimitive () ? 0 : method_count
;
193 for (i
= max
; --i
>= 0; )
195 _Jv_Method
*method
= &methods
[i
];
196 if (method
->name
== NULL
197 || ! _Jv_equalUtf8Consts (method
->name
, init_name
))
200 && ! java::lang::reflect::Modifier::isPublic(method
->accflags
))
204 JArray
<java::lang::reflect::Constructor
*> *result
205 = (JArray
<java::lang::reflect::Constructor
*> *)
206 JvNewObjectArray (numConstructors
,
207 &java::lang::reflect::Constructor::class$
,
209 java::lang::reflect::Constructor
** cptr
= elements (result
);
210 for (i
= 0; i
< max
; i
++)
212 _Jv_Method
*method
= &methods
[i
];
213 if (method
->name
== NULL
214 || ! _Jv_equalUtf8Consts (method
->name
, init_name
))
217 && ! java::lang::reflect::Modifier::isPublic(method
->accflags
))
219 java::lang::reflect::Constructor
*cons
220 = new java::lang::reflect::Constructor ();
221 cons
->offset
= (char *) method
- (char *) methods
;
222 cons
->declaringClass
= this;
228 java::lang::reflect::Constructor
*
229 java::lang::Class::getDeclaredConstructor (JArray
<jclass
> *param_types
)
231 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
233 jstring partial_sig
= getSignature (param_types
, true);
234 jint hash
= partial_sig
->hashCode ();
236 int i
= isPrimitive () ? 0 : method_count
;
239 if (_Jv_equalUtf8Consts (methods
[i
].name
, init_name
)
240 && _Jv_equal (methods
[i
].signature
, partial_sig
, hash
))
243 using namespace java::lang::reflect
;
244 Constructor
*cons
= new Constructor ();
245 cons
->offset
= (char *) (&methods
[i
]) - (char *) methods
;
246 cons
->declaringClass
= this;
250 throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name
));
253 java::lang::reflect::Field
*
254 java::lang::Class::getField (jstring name
, jint hash
)
256 java::lang::reflect::Field
* rfield
;
257 for (int i
= 0; i
< field_count
; i
++)
259 _Jv_Field
*field
= &fields
[i
];
260 if (! _Jv_equal (field
->name
, name
, hash
))
262 if (! (field
->getModifiers() & java::lang::reflect::Modifier::PUBLIC
))
264 rfield
= new java::lang::reflect::Field ();
265 rfield
->offset
= (char*) field
- (char*) fields
;
266 rfield
->declaringClass
= this;
270 jclass superclass
= getSuperclass();
271 if (superclass
== NULL
)
273 rfield
= superclass
->getField(name
, hash
);
274 for (int i
= 0; i
< interface_count
&& rfield
== NULL
; ++i
)
275 rfield
= interfaces
[i
]->getField (name
, hash
);
279 java::lang::reflect::Field
*
280 java::lang::Class::getDeclaredField (jstring name
)
282 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
283 int hash
= name
->hashCode();
284 for (int i
= 0; i
< field_count
; i
++)
286 _Jv_Field
*field
= &fields
[i
];
287 if (! _Jv_equal (field
->name
, name
, hash
))
289 java::lang::reflect::Field
* rfield
= new java::lang::reflect::Field ();
290 rfield
->offset
= (char*) field
- (char*) fields
;
291 rfield
->declaringClass
= this;
295 throw new java::lang::NoSuchFieldException (name
);
298 JArray
<java::lang::reflect::Field
*> *
299 java::lang::Class::getDeclaredFields (jboolean public_only
)
305 for (int i
= 0; i
< field_count
; ++i
)
307 _Jv_Field
*field
= &fields
[i
];
308 if ((field
->flags
& java::lang::reflect::Modifier::PUBLIC
))
315 JArray
<java::lang::reflect::Field
*> *result
316 = (JArray
<java::lang::reflect::Field
*> *)
317 JvNewObjectArray (size
, &java::lang::reflect::Field::class$
, NULL
);
318 java::lang::reflect::Field
** fptr
= elements (result
);
319 for (int i
= 0; i
< field_count
; i
++)
321 _Jv_Field
*field
= &fields
[i
];
323 && ! (field
->flags
& java::lang::reflect::Modifier::PUBLIC
))
325 java::lang::reflect::Field
* rfield
= new java::lang::reflect::Field ();
326 rfield
->offset
= (char*) field
- (char*) fields
;
327 rfield
->declaringClass
= this;
334 java::lang::Class::getSignature (java::lang::StringBuffer
*buffer
)
337 buffer
->append((jchar
) method_count
);
340 jstring name
= getName();
341 if (name
->charAt(0) != '[')
342 buffer
->append((jchar
) 'L');
343 buffer
->append(name
);
344 if (name
->charAt(0) != '[')
345 buffer
->append((jchar
) ';');
349 // This doesn't have to be native. It is an implementation detail
350 // only called from the C++ code, though, so maybe this is clearer.
352 java::lang::Class::getSignature (JArray
<jclass
> *param_types
,
353 jboolean is_constructor
)
355 java::lang::StringBuffer
*buf
= new java::lang::StringBuffer ();
356 buf
->append((jchar
) '(');
357 // A NULL param_types means "no parameters".
358 if (param_types
!= NULL
)
360 jclass
*v
= elements (param_types
);
361 for (int i
= 0; i
< param_types
->length
; ++i
)
362 v
[i
]->getSignature(buf
);
364 buf
->append((jchar
) ')');
366 buf
->append((jchar
) 'V');
367 return buf
->toString();
370 java::lang::reflect::Method
*
371 java::lang::Class::_getDeclaredMethod (jstring name
,
372 JArray
<jclass
> *param_types
)
374 jstring partial_sig
= getSignature (param_types
, false);
375 jint p_len
= partial_sig
->length();
376 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
377 int i
= isPrimitive () ? 0 : method_count
;
380 if (_Jv_equalUtf8Consts (methods
[i
].name
, utf_name
)
381 && _Jv_equaln (methods
[i
].signature
, partial_sig
, p_len
)
382 && (methods
[i
].accflags
383 & java::lang::reflect::Modifier::INVISIBLE
) == 0)
386 using namespace java::lang::reflect
;
387 Method
*rmethod
= new Method ();
388 rmethod
->offset
= (char*) (&methods
[i
]) - (char*) methods
;
389 rmethod
->declaringClass
= this;
396 JArray
<java::lang::reflect::Method
*> *
397 java::lang::Class::getDeclaredMethods (void)
399 memberAccessCheck(java::lang::reflect::Member::DECLARED
);
402 int max
= isPrimitive () ? 0 : method_count
;
404 for (i
= max
; --i
>= 0; )
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)
416 JArray
<java::lang::reflect::Method
*> *result
417 = (JArray
<java::lang::reflect::Method
*> *)
418 JvNewObjectArray (numMethods
, &java::lang::reflect::Method::class$
, NULL
);
419 java::lang::reflect::Method
** mptr
= elements (result
);
420 for (i
= 0; i
< max
; i
++)
422 _Jv_Method
*method
= &methods
[i
];
423 if (method
->name
== NULL
424 || _Jv_equalUtf8Consts (method
->name
, clinit_name
)
425 || _Jv_equalUtf8Consts (method
->name
, init_name
)
426 || _Jv_equalUtf8Consts (method
->name
, finit_name
)
427 || (methods
[i
].accflags
428 & java::lang::reflect::Modifier::INVISIBLE
) != 0)
430 java::lang::reflect::Method
* rmethod
431 = new java::lang::reflect::Method ();
432 rmethod
->offset
= (char*) method
- (char*) methods
;
433 rmethod
->declaringClass
= this;
440 java::lang::Class::getName (void)
442 char buffer
[name
->length
+ 1];
443 memcpy (buffer
, name
->data
, name
->length
);
444 buffer
[name
->length
] = '\0';
445 return _Jv_NewStringUTF (buffer
);
449 java::lang::Class::getClasses (void)
451 // FIXME: security checking.
453 // Until we have inner classes, it always makes sense to return an
455 JArray
<jclass
> *result
456 = (JArray
<jclass
> *) JvNewObjectArray (0, &java::lang::Class::class$
,
462 java::lang::Class::getDeclaredClasses (void)
464 memberAccessCheck (java::lang::reflect::Member::DECLARED
);
465 // Until we have inner classes, it always makes sense to return an
467 JArray
<jclass
> *result
468 = (JArray
<jclass
> *) JvNewObjectArray (0, &java::lang::Class::class$
,
474 java::lang::Class::getDeclaringClass (void)
476 // Until we have inner classes, it makes sense to always return
482 java::lang::Class::getInterfaces (void)
484 jobjectArray r
= JvNewObjectArray (interface_count
, getClass (), NULL
);
485 jobject
*data
= elements (r
);
486 for (int i
= 0; i
< interface_count
; ++i
)
487 data
[i
] = interfaces
[i
];
488 return reinterpret_cast<JArray
<jclass
> *> (r
);
491 java::lang::reflect::Method
*
492 java::lang::Class::_getMethod (jstring name
, JArray
<jclass
> *param_types
)
494 jstring partial_sig
= getSignature (param_types
, false);
495 jint p_len
= partial_sig
->length();
496 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
497 for (Class
*klass
= this; klass
; klass
= klass
->getSuperclass())
499 int i
= klass
->isPrimitive () ? 0 : klass
->method_count
;
502 if (_Jv_equalUtf8Consts (klass
->methods
[i
].name
, utf_name
)
503 && _Jv_equaln (klass
->methods
[i
].signature
, partial_sig
, p_len
)
504 && (klass
->methods
[i
].accflags
505 & java::lang::reflect::Modifier::INVISIBLE
) == 0)
508 using namespace java::lang::reflect
;
510 // Method must be public.
511 if (! Modifier::isPublic (klass
->methods
[i
].accflags
))
514 Method
*rmethod
= new Method ();
515 rmethod
->offset
= ((char *) (&klass
->methods
[i
])
516 - (char *) klass
->methods
);
517 rmethod
->declaringClass
= klass
;
523 // If we haven't found a match, and this class is an interface, then
524 // check all the superinterfaces.
527 for (int i
= 0; i
< interface_count
; ++i
)
529 using namespace java::lang::reflect
;
530 Method
*rmethod
= interfaces
[i
]->_getMethod (name
, param_types
);
539 // This is a very slow implementation, since it re-scans all the
540 // methods we've already listed to make sure we haven't duplicated a
541 // method. It also over-estimates the required size, so we have to
542 // shrink the result array later.
544 java::lang::Class::_getMethods (JArray
<java::lang::reflect::Method
*> *result
,
549 // First examine all local methods
550 for (int i
= isPrimitive () ? 0 : method_count
; --i
>= 0; )
552 _Jv_Method
*method
= &methods
[i
];
553 if (method
->name
== NULL
554 || _Jv_equalUtf8Consts (method
->name
, clinit_name
)
555 || _Jv_equalUtf8Consts (method
->name
, init_name
)
556 || _Jv_equalUtf8Consts (method
->name
, finit_name
)
558 & java::lang::reflect::Modifier::INVISIBLE
) != 0)
560 // Only want public methods.
561 if (! java::lang::reflect::Modifier::isPublic (method
->accflags
))
564 // This is where we over-count the slots required if we aren't
565 // filling the result for real.
569 java::lang::reflect::Method
**mp
= elements (result
);
570 // If we already have a method with this name and signature,
571 // then ignore this one. This can happen with virtual
573 for (int j
= 0; j
< offset
; ++j
)
575 _Jv_Method
*meth_2
= _Jv_FromReflectedMethod (mp
[j
]);
576 if (_Jv_equalUtf8Consts (method
->name
, meth_2
->name
)
577 && _Jv_equalUtf8Consts (method
->signature
,
590 using namespace java::lang::reflect
;
591 Method
*rmethod
= new Method ();
592 rmethod
->offset
= (char *) method
- (char *) methods
;
593 rmethod
->declaringClass
= this;
594 Method
**mp
= elements (result
);
595 mp
[offset
+ count
] = rmethod
;
601 // Now examine superclasses.
602 if (getSuperclass () != NULL
)
604 jint s_count
= getSuperclass()->_getMethods (result
, offset
);
609 // Finally, examine interfaces.
610 for (int i
= 0; i
< interface_count
; ++i
)
612 int f_count
= interfaces
[i
]->_getMethods (result
, offset
);
620 JArray
<java::lang::reflect::Method
*> *
621 java::lang::Class::getMethods (void)
623 using namespace java::lang::reflect
;
625 memberAccessCheck(Member::PUBLIC
);
627 // This will overestimate the size we need.
628 jint count
= _getMethods (NULL
, 0);
630 JArray
<Method
*> *result
631 = ((JArray
<Method
*> *) JvNewObjectArray (count
,
635 // When filling the array for real, we get the actual count. Then
636 // we resize the array.
637 jint real_count
= _getMethods (result
, 0);
639 if (real_count
!= count
)
642 = ((JArray
<Method
*> *) JvNewObjectArray (real_count
,
646 Method
**destp
= elements (r2
);
647 Method
**srcp
= elements (result
);
649 for (int i
= 0; i
< real_count
; ++i
)
659 java::lang::Class::isAssignableFrom (jclass klass
)
661 // Arguments may not have been initialized, given ".class" syntax.
662 _Jv_InitClass (this);
663 _Jv_InitClass (klass
);
664 return _Jv_IsAssignableFrom (this, klass
);
668 java::lang::Class::isInstance (jobject obj
)
672 _Jv_InitClass (this);
673 return _Jv_IsAssignableFrom (this, JV_CLASS (obj
));
677 java::lang::Class::newInstance (void)
679 memberAccessCheck(java::lang::reflect::Member::PUBLIC
);
684 || java::lang::reflect::Modifier::isAbstract(accflags
))
685 throw new java::lang::InstantiationException (getName ());
687 _Jv_InitClass (this);
689 _Jv_Method
*meth
= _Jv_GetMethodLocal (this, init_name
, void_signature
);
691 throw new java::lang::InstantiationException (getName());
693 jobject r
= JvAllocObject (this);
694 ((void (*) (jobject
)) meth
->ncode
) (r
);
699 java::lang::Class::finalize (void)
702 JvAssert (_Jv_IsInterpretedClass (this));
703 _Jv_UnregisterClass (this);
707 // This implements the initialization process for a class. From Spec
710 java::lang::Class::initializeClass (void)
712 // short-circuit to avoid needless locking.
713 if (state
== JV_STATE_DONE
)
717 _Jv_MonitorEnter (this);
719 if (state
< JV_STATE_LINKED
)
722 if (_Jv_IsInterpretedClass (this))
724 // this can throw exceptions, so exit the monitor as a precaution.
725 _Jv_MonitorExit (this);
726 java::lang::VMClassLoader::resolveClass (this);
727 _Jv_MonitorEnter (this);
732 _Jv_PrepareCompiledClass (this);
737 java::lang::Thread
*self
= java::lang::Thread::currentThread();
738 // FIXME: `self' can be null at startup. Hence this nasty trick.
739 self
= (java::lang::Thread
*) ((long) self
| 1);
740 while (state
== JV_STATE_IN_PROGRESS
&& thread
&& thread
!= self
)
744 if (state
== JV_STATE_DONE
)
746 _Jv_MonitorExit (this);
749 if (state
== JV_STATE_IN_PROGRESS
)
751 _Jv_MonitorExit (this);
753 /* Initialization in progress. The class is linked now,
754 so ensure internal tables are built. */
755 _Jv_PrepareConstantTimeTables (this);
756 _Jv_MakeVTable(this);
757 _Jv_LinkSymbolTable(this);
763 if (state
== JV_STATE_ERROR
)
765 _Jv_MonitorExit (this);
766 throw new java::lang::NoClassDefFoundError (getName());
771 state
= JV_STATE_IN_PROGRESS
;
772 _Jv_MonitorExit (this);
775 if (! isInterface () && superclass
)
779 _Jv_InitClass (superclass
);
781 catch (java::lang::Throwable
*except
)
783 // Caught an exception.
784 _Jv_MonitorEnter (this);
785 state
= JV_STATE_ERROR
;
787 _Jv_MonitorExit (this);
792 _Jv_PrepareConstantTimeTables (this);
795 _Jv_MakeVTable(this);
797 if (otable
|| atable
)
798 _Jv_LinkSymbolTable(this);
800 _Jv_linkExceptionClassTable (this);
802 // Steps 8, 9, 10, 11.
805 _Jv_Method
*meth
= _Jv_GetMethodLocal (this, clinit_name
,
808 ((void (*) (void)) meth
->ncode
) ();
810 catch (java::lang::Throwable
*except
)
812 if (! java::lang::Error::class$
.isInstance(except
))
816 except
= new ExceptionInInitializerError (except
);
818 catch (java::lang::Throwable
*t
)
823 _Jv_MonitorEnter (this);
824 state
= JV_STATE_ERROR
;
826 _Jv_MonitorExit (this);
830 _Jv_MonitorEnter (this);
831 state
= JV_STATE_DONE
;
833 _Jv_MonitorExit (this);
839 // Some class-related convenience functions.
842 // Find a method declared in the class. If it is not declared locally
843 // (or if it is inherited), return NULL.
845 _Jv_GetMethodLocal (jclass klass
, _Jv_Utf8Const
*name
,
846 _Jv_Utf8Const
*signature
)
848 for (int i
= 0; i
< klass
->method_count
; ++i
)
850 if (_Jv_equalUtf8Consts (name
, klass
->methods
[i
].name
)
851 && _Jv_equalUtf8Consts (signature
, klass
->methods
[i
].signature
))
852 return &klass
->methods
[i
];
858 _Jv_LookupDeclaredMethod (jclass klass
, _Jv_Utf8Const
*name
,
859 _Jv_Utf8Const
*signature
)
861 for (; klass
; klass
= klass
->getSuperclass())
863 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
872 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
873 #define MCACHE_SIZE 1023
881 static _Jv_mcache method_cache
[MCACHE_SIZE
+ 1];
884 _Jv_FindMethodInCache (jclass klass
,
886 _Jv_Utf8Const
*signature
)
888 int index
= name
->hash
& MCACHE_SIZE
;
889 _Jv_mcache
*mc
= method_cache
+ index
;
890 _Jv_Method
*m
= mc
->method
;
892 if (mc
->klass
== klass
893 && m
!= NULL
// thread safe check
894 && _Jv_equalUtf8Consts (m
->name
, name
)
895 && _Jv_equalUtf8Consts (m
->signature
, signature
))
896 return mc
->method
->ncode
;
901 _Jv_AddMethodToCache (jclass klass
,
904 _Jv_MonitorEnter (&java::lang::Class::class$
);
906 int index
= method
->name
->hash
& MCACHE_SIZE
;
908 method_cache
[index
].method
= method
;
909 method_cache
[index
].klass
= klass
;
911 _Jv_MonitorExit (&java::lang::Class::class$
);
915 _Jv_LookupInterfaceMethod (jclass klass
, _Jv_Utf8Const
*name
,
916 _Jv_Utf8Const
*signature
)
918 using namespace java::lang::reflect
;
920 void *ncode
= _Jv_FindMethodInCache (klass
, name
, signature
);
924 for (; klass
; klass
= klass
->getSuperclass())
926 _Jv_Method
*meth
= _Jv_GetMethodLocal (klass
, name
, signature
);
930 if (Modifier::isStatic(meth
->accflags
))
931 throw new java::lang::IncompatibleClassChangeError
932 (_Jv_GetMethodString (klass
, meth
->name
));
933 if (Modifier::isAbstract(meth
->accflags
))
934 throw new java::lang::AbstractMethodError
935 (_Jv_GetMethodString (klass
, meth
->name
));
936 if (! Modifier::isPublic(meth
->accflags
))
937 throw new java::lang::IllegalAccessError
938 (_Jv_GetMethodString (klass
, meth
->name
));
940 _Jv_AddMethodToCache (klass
, meth
);
944 throw new java::lang::IncompatibleClassChangeError
;
947 // Fast interface method lookup by index.
949 _Jv_LookupInterfaceMethodIdx (jclass klass
, jclass iface
, int method_idx
)
951 _Jv_IDispatchTable
*cldt
= klass
->idt
;
952 int idx
= iface
->idt
->iface
.ioffsets
[cldt
->cls
.iindex
] + method_idx
;
953 return cldt
->cls
.itable
[idx
];
957 _Jv_IsAssignableFrom (jclass target
, jclass source
)
959 if (source
== target
)
962 // If target is array, so must source be.
963 while (target
->isArray ())
965 if (! source
->isArray())
967 target
= target
->getComponentType();
968 source
= source
->getComponentType();
971 if (target
->isInterface())
973 // Abstract classes have no IDT, and IDTs provide no way to check
974 // two interfaces for assignability.
976 (source
->idt
== NULL
|| source
->isInterface(), false))
977 return _Jv_InterfaceAssignableFrom (target
, source
);
979 _Jv_IDispatchTable
*cl_idt
= source
->idt
;
980 _Jv_IDispatchTable
*if_idt
= target
->idt
;
982 if (__builtin_expect ((if_idt
== NULL
), false))
983 return false; // No class implementing TARGET has been loaded.
984 jshort cl_iindex
= cl_idt
->cls
.iindex
;
985 if (cl_iindex
< if_idt
->iface
.ioffsets
[0])
987 jshort offset
= if_idt
->iface
.ioffsets
[cl_iindex
];
988 if (offset
!= -1 && offset
< cl_idt
->cls
.itable_length
989 && cl_idt
->cls
.itable
[offset
] == target
)
995 // Primitive TYPE classes are only assignable to themselves.
996 if (__builtin_expect (target
->isPrimitive() || source
->isPrimitive(), false))
999 if (target
== &java::lang::Object::class$
)
1001 else if (source
->ancestors
== NULL
|| target
->ancestors
== NULL
)
1003 // We need this case when either SOURCE or TARGET has not has
1004 // its constant-time tables prepared.
1006 // At this point we know that TARGET can't be Object, so it is
1007 // safe to use that as the termination point.
1008 while (source
&& source
!= &java::lang::Object::class$
)
1010 if (source
== target
)
1012 source
= source
->getSuperclass();
1015 else if (source
->depth
>= target
->depth
1016 && source
->ancestors
[source
->depth
- target
->depth
] == target
)
1022 // Interface type checking, the slow way. Returns TRUE if IFACE is a
1023 // superinterface of SOURCE. This is used when SOURCE is also an interface,
1024 // or a class with no interface dispatch table.
1026 _Jv_InterfaceAssignableFrom (jclass iface
, jclass source
)
1028 for (int i
= 0; i
< source
->interface_count
; i
++)
1030 jclass interface
= source
->interfaces
[i
];
1031 if (iface
== interface
1032 || _Jv_InterfaceAssignableFrom (iface
, interface
))
1036 if (!source
->isInterface()
1037 && source
->superclass
1038 && _Jv_InterfaceAssignableFrom (iface
, source
->superclass
))
1045 _Jv_IsInstanceOf(jobject obj
, jclass cl
)
1047 if (__builtin_expect (!obj
, false))
1049 return (_Jv_IsAssignableFrom (cl
, JV_CLASS (obj
)));
1053 _Jv_CheckCast (jclass c
, jobject obj
)
1055 if (__builtin_expect
1056 (obj
!= NULL
&& ! _Jv_IsAssignableFrom(c
, JV_CLASS (obj
)), false))
1057 throw new java::lang::ClassCastException
1058 ((new java::lang::StringBuffer
1059 (obj
->getClass()->getName()))->append
1060 (JvNewStringUTF(" cannot be cast to "))->append
1061 (c
->getName())->toString());
1067 _Jv_CheckArrayStore (jobject arr
, jobject obj
)
1071 JvAssert (arr
!= NULL
);
1072 jclass elt_class
= (JV_CLASS (arr
))->getComponentType();
1073 if (elt_class
== &java::lang::Object::class$
)
1075 jclass obj_class
= JV_CLASS (obj
);
1076 if (__builtin_expect
1077 (! _Jv_IsAssignableFrom (elt_class
, obj_class
), false))
1078 throw new java::lang::ArrayStoreException
1079 ((new java::lang::StringBuffer
1080 (JvNewStringUTF("Cannot store ")))->append
1081 (obj_class
->getName())->append
1082 (JvNewStringUTF(" in array of type "))->append
1083 (elt_class
->getName())->toString());
1087 #define INITIAL_IOFFSETS_LEN 4
1088 #define INITIAL_IFACES_LEN 4
1090 static _Jv_IDispatchTable null_idt
= { {SHRT_MAX
, 0, NULL
} };
1092 // Generate tables for constant-time assignment testing and interface
1093 // method lookup. This implements the technique described by Per Bothner
1094 // <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
1095 // http://gcc.gnu.org/ml/java/1999-q3/msg00377.html
1097 _Jv_PrepareConstantTimeTables (jclass klass
)
1099 if (klass
->isPrimitive () || klass
->isInterface ())
1102 // Short-circuit in case we've been called already.
1103 if ((klass
->idt
!= NULL
) || klass
->depth
!= 0)
1106 // Calculate the class depth and ancestor table. The depth of a class
1107 // is how many "extends" it is removed from Object. Thus the depth of
1108 // java.lang.Object is 0, but the depth of java.io.FilterOutputStream
1109 // is 2. Depth is defined for all regular and array classes, but not
1110 // interfaces or primitive types.
1112 jclass klass0
= klass
;
1113 jboolean has_interfaces
= 0;
1114 while (klass0
!= &java::lang::Object::class$
)
1116 has_interfaces
+= klass0
->interface_count
;
1117 klass0
= klass0
->superclass
;
1121 // We do class member testing in constant time by using a small table
1122 // of all the ancestor classes within each class. The first element is
1123 // a pointer to the current class, and the rest are pointers to the
1124 // classes ancestors, ordered from the current class down by decreasing
1125 // depth. We do not include java.lang.Object in the table of ancestors,
1126 // since it is redundant.
1128 klass
->ancestors
= (jclass
*) _Jv_Malloc (klass
->depth
* sizeof (jclass
));
1130 for (int index
= 0; index
< klass
->depth
; index
++)
1132 klass
->ancestors
[index
] = klass0
;
1133 klass0
= klass0
->superclass
;
1136 if (java::lang::reflect::Modifier::isAbstract (klass
->accflags
))
1139 // Optimization: If class implements no interfaces, use a common
1140 // predefined interface table.
1141 if (!has_interfaces
)
1143 klass
->idt
= &null_idt
;
1148 (_Jv_IDispatchTable
*) _Jv_Malloc (sizeof (_Jv_IDispatchTable
));
1153 ifaces
.len
= INITIAL_IFACES_LEN
;
1154 ifaces
.list
= (jclass
*) _Jv_Malloc (ifaces
.len
* sizeof (jclass
*));
1156 int itable_size
= _Jv_GetInterfaces (klass
, &ifaces
);
1158 if (ifaces
.count
> 0)
1160 klass
->idt
->cls
.itable
=
1161 (void **) _Jv_Malloc (itable_size
* sizeof (void *));
1162 klass
->idt
->cls
.itable_length
= itable_size
;
1164 jshort
*itable_offsets
=
1165 (jshort
*) _Jv_Malloc (ifaces
.count
* sizeof (jshort
));
1167 _Jv_GenerateITable (klass
, &ifaces
, itable_offsets
);
1170 _Jv_FindIIndex (ifaces
.list
, itable_offsets
, ifaces
.count
);
1172 for (int i
=0; i
< ifaces
.count
; i
++)
1174 ifaces
.list
[i
]->idt
->iface
.ioffsets
[cls_iindex
] =
1178 klass
->idt
->cls
.iindex
= cls_iindex
;
1180 _Jv_Free (ifaces
.list
);
1181 _Jv_Free (itable_offsets
);
1185 klass
->idt
->cls
.iindex
= SHRT_MAX
;
1189 // Return index of item in list, or -1 if item is not present.
1191 _Jv_IndexOf (void *item
, void **list
, jshort list_len
)
1193 for (int i
=0; i
< list_len
; i
++)
1195 if (list
[i
] == item
)
1201 // Find all unique interfaces directly or indirectly implemented by klass.
1202 // Returns the size of the interface dispatch table (itable) for klass, which
1203 // is the number of unique interfaces plus the total number of methods that
1204 // those interfaces declare. May extend ifaces if required.
1206 _Jv_GetInterfaces (jclass klass
, _Jv_ifaces
*ifaces
)
1210 for (int i
=0; i
< klass
->interface_count
; i
++)
1212 jclass iface
= klass
->interfaces
[i
];
1214 /* Make sure interface is linked. */
1215 _Jv_WaitForState(iface
, JV_STATE_LINKED
);
1217 if (_Jv_IndexOf (iface
, (void **) ifaces
->list
, ifaces
->count
) == -1)
1219 if (ifaces
->count
+ 1 >= ifaces
->len
)
1221 /* Resize ifaces list */
1222 ifaces
->len
= ifaces
->len
* 2;
1223 ifaces
->list
= (jclass
*) _Jv_Realloc (ifaces
->list
,
1224 ifaces
->len
* sizeof(jclass
));
1226 ifaces
->list
[ifaces
->count
] = iface
;
1229 result
+= _Jv_GetInterfaces (klass
->interfaces
[i
], ifaces
);
1233 if (klass
->isInterface())
1235 result
+= klass
->method_count
+ 1;
1239 if (klass
->superclass
)
1241 result
+= _Jv_GetInterfaces (klass
->superclass
, ifaces
);
1247 // Fill out itable in klass, resolving method declarations in each ifaces.
1248 // itable_offsets is filled out with the position of each iface in itable,
1249 // such that itable[itable_offsets[n]] == ifaces.list[n].
1251 _Jv_GenerateITable (jclass klass
, _Jv_ifaces
*ifaces
, jshort
*itable_offsets
)
1253 void **itable
= klass
->idt
->cls
.itable
;
1254 jshort itable_pos
= 0;
1256 for (int i
=0; i
< ifaces
->count
; i
++)
1258 jclass iface
= ifaces
->list
[i
];
1259 itable_offsets
[i
] = itable_pos
;
1260 itable_pos
= _Jv_AppendPartialITable (klass
, iface
, itable
, itable_pos
);
1262 /* Create interface dispatch table for iface */
1263 if (iface
->idt
== NULL
)
1266 (_Jv_IDispatchTable
*) _Jv_Malloc (sizeof (_Jv_IDispatchTable
));
1268 // The first element of ioffsets is its length (itself included).
1270 (jshort
*) _Jv_Malloc (INITIAL_IOFFSETS_LEN
* sizeof (jshort
));
1271 ioffsets
[0] = INITIAL_IOFFSETS_LEN
;
1272 for (int i
=1; i
< INITIAL_IOFFSETS_LEN
; i
++)
1275 iface
->idt
->iface
.ioffsets
= ioffsets
;
1280 // Format method name for use in error messages.
1282 _Jv_GetMethodString (jclass klass
, _Jv_Utf8Const
*name
)
1284 jstring r
= JvNewStringUTF (klass
->name
->data
);
1285 r
= r
->concat (JvNewStringUTF ("."));
1286 r
= r
->concat (JvNewStringUTF (name
->data
));
1291 _Jv_ThrowNoSuchMethodError ()
1293 throw new java::lang::NoSuchMethodError
;
1296 // Each superinterface of a class (i.e. each interface that the class
1297 // directly or indirectly implements) has a corresponding "Partial
1298 // Interface Dispatch Table" whose size is (number of methods + 1) words.
1299 // The first word is a pointer to the interface (i.e. the java.lang.Class
1300 // instance for that interface). The remaining words are pointers to the
1301 // actual methods that implement the methods declared in the interface,
1302 // in order of declaration.
1304 // Append partial interface dispatch table for "iface" to "itable", at
1305 // position itable_pos.
1306 // Returns the offset at which the next partial ITable should be appended.
1308 _Jv_AppendPartialITable (jclass klass
, jclass iface
, void **itable
,
1311 using namespace java::lang::reflect
;
1313 itable
[pos
++] = (void *) iface
;
1316 for (int j
=0; j
< iface
->method_count
; j
++)
1319 for (jclass cl
= klass
; cl
; cl
= cl
->getSuperclass())
1321 meth
= _Jv_GetMethodLocal (cl
, iface
->methods
[j
].name
,
1322 iface
->methods
[j
].signature
);
1328 if (meth
&& (meth
->name
->data
[0] == '<'))
1330 // leave a placeholder in the itable for hidden init methods.
1335 if (Modifier::isStatic(meth
->accflags
))
1336 throw new java::lang::IncompatibleClassChangeError
1337 (_Jv_GetMethodString (klass
, meth
->name
));
1338 if (Modifier::isAbstract(meth
->accflags
))
1339 throw new java::lang::AbstractMethodError
1340 (_Jv_GetMethodString (klass
, meth
->name
));
1341 if (! Modifier::isPublic(meth
->accflags
))
1342 throw new java::lang::IllegalAccessError
1343 (_Jv_GetMethodString (klass
, meth
->name
));
1345 itable
[pos
] = meth
->ncode
;
1349 // The method doesn't exist in klass. Binary compatibility rules
1350 // permit this, so we delay the error until runtime using a pointer
1351 // to a method which throws an exception.
1352 itable
[pos
] = (void *) _Jv_ThrowNoSuchMethodError
;
1360 static _Jv_Mutex_t iindex_mutex
;
1361 static bool iindex_mutex_initialized
= false;
1363 // We need to find the correct offset in the Class Interface Dispatch
1364 // Table for a given interface. Once we have that, invoking an interface
1365 // method just requires combining the Method's index in the interface
1366 // (known at compile time) to get the correct method. Doing a type test
1367 // (cast or instanceof) is the same problem: Once we have a possible Partial
1368 // Interface Dispatch Table, we just compare the first element to see if it
1369 // matches the desired interface. So how can we find the correct offset?
1370 // Our solution is to keep a vector of candiate offsets in each interface
1371 // (idt->iface.ioffsets), and in each class we have an index
1372 // (idt->cls.iindex) used to select the correct offset from ioffsets.
1374 // Calculate and return iindex for a new class.
1375 // ifaces is a vector of num interfaces that the class implements.
1376 // offsets[j] is the offset in the interface dispatch table for the
1377 // interface corresponding to ifaces[j].
1378 // May extend the interface ioffsets if required.
1380 _Jv_FindIIndex (jclass
*ifaces
, jshort
*offsets
, jshort num
)
1385 // Acquire a global lock to prevent itable corruption in case of multiple
1386 // classes that implement an intersecting set of interfaces being linked
1387 // simultaneously. We can assume that the mutex will be initialized
1389 if (! iindex_mutex_initialized
)
1391 _Jv_MutexInit (&iindex_mutex
);
1392 iindex_mutex_initialized
= true;
1395 _Jv_MutexLock (&iindex_mutex
);
1397 for (i
=1;; i
++) /* each potential position in ioffsets */
1399 for (j
=0;; j
++) /* each iface */
1403 if (i
>= ifaces
[j
]->idt
->iface
.ioffsets
[0])
1405 int ioffset
= ifaces
[j
]->idt
->iface
.ioffsets
[i
];
1406 /* We can potentially share this position with another class. */
1407 if (ioffset
>= 0 && ioffset
!= offsets
[j
])
1408 break; /* Nope. Try next i. */
1412 for (j
= 0; j
< num
; j
++)
1414 int len
= ifaces
[j
]->idt
->iface
.ioffsets
[0];
1417 /* Resize ioffsets. */
1418 int newlen
= 2 * len
;
1421 jshort
*old_ioffsets
= ifaces
[j
]->idt
->iface
.ioffsets
;
1422 jshort
*new_ioffsets
= (jshort
*) _Jv_Realloc (old_ioffsets
,
1423 newlen
* sizeof(jshort
));
1424 new_ioffsets
[0] = newlen
;
1426 while (len
< newlen
)
1427 new_ioffsets
[len
++] = -1;
1429 ifaces
[j
]->idt
->iface
.ioffsets
= new_ioffsets
;
1431 ifaces
[j
]->idt
->iface
.ioffsets
[i
] = offsets
[j
];
1434 _Jv_MutexUnlock (&iindex_mutex
);
1439 // Only used by serialization
1440 java::lang::reflect::Field
*
1441 java::lang::Class::getPrivateField (jstring name
)
1443 int hash
= name
->hashCode ();
1445 java::lang::reflect::Field
* rfield
;
1446 for (int i
= 0; i
< field_count
; i
++)
1448 _Jv_Field
*field
= &fields
[i
];
1449 if (! _Jv_equal (field
->name
, name
, hash
))
1451 rfield
= new java::lang::reflect::Field ();
1452 rfield
->offset
= (char*) field
- (char*) fields
;
1453 rfield
->declaringClass
= this;
1454 rfield
->name
= name
;
1457 jclass superclass
= getSuperclass();
1458 if (superclass
== NULL
)
1460 rfield
= superclass
->getPrivateField(name
);
1461 for (int i
= 0; i
< interface_count
&& rfield
== NULL
; ++i
)
1462 rfield
= interfaces
[i
]->getPrivateField (name
);
1466 // Only used by serialization
1467 java::lang::reflect::Method
*
1468 java::lang::Class::getPrivateMethod (jstring name
, JArray
<jclass
> *param_types
)
1470 jstring partial_sig
= getSignature (param_types
, false);
1471 jint p_len
= partial_sig
->length();
1472 _Jv_Utf8Const
*utf_name
= _Jv_makeUtf8Const (name
);
1473 for (Class
*klass
= this; klass
; klass
= klass
->getSuperclass())
1475 int i
= klass
->isPrimitive () ? 0 : klass
->method_count
;
1478 if (_Jv_equalUtf8Consts (klass
->methods
[i
].name
, utf_name
)
1479 && _Jv_equaln (klass
->methods
[i
].signature
, partial_sig
, p_len
))
1482 using namespace java::lang::reflect
;
1484 Method
*rmethod
= new Method ();
1485 rmethod
->offset
= ((char *) (&klass
->methods
[i
])
1486 - (char *) klass
->methods
);
1487 rmethod
->declaringClass
= klass
;
1492 throw new java::lang::NoSuchMethodException (name
);
1495 // Private accessor method for Java code to retrieve the protection domain.
1496 java::security::ProtectionDomain
*
1497 java::lang::Class::getProtectionDomain0 ()
1499 return protectionDomain
;
1503 java::lang::Class::getSigners()
1505 return hack_signers
;
1509 java::lang::Class::setSigners(JArray
<jobject
> *s
)
1514 // Functions for indirect dispatch (symbolic virtual binding) support.
1516 // There are two tables, atable and otable. atable is an array of
1517 // addresses, and otable is an array of offsets, and these are used
1518 // for static and virtual members respectively.
1520 // {a,o}table_syms is an array of _Jv_MethodSymbols. Each such symbol
1521 // is a tuple of {classname, member name, signature}.
1522 // _Jv_LinkSymbolTable() scans these two arrays and fills in the
1523 // corresponding atable and otable with the addresses of static
1524 // members and the offsets of virtual members.
1526 // The offset (in bytes) for each resolved method or field is placed
1527 // at the corresponding position in the virtual method offset table
1530 // The same otable and atable may be shared by many classes.
1533 _Jv_LinkSymbolTable(jclass klass
)
1535 //// FIXME: Need to lock the tables ////
1538 _Jv_MethodSymbol sym
;
1539 if (klass
->otable
== NULL
1540 || klass
->otable
->state
!= 0)
1543 klass
->otable
->state
= 1;
1545 for (index
= 0; sym
= klass
->otable_syms
[index
], sym
.name
!= NULL
; index
++)
1547 // FIXME: Why are we passing NULL as the class loader?
1548 jclass target_class
= _Jv_FindClass (sym
.class_name
, NULL
);
1549 _Jv_Method
*meth
= NULL
;
1551 const _Jv_Utf8Const
*signature
= sym
.signature
;
1554 static char *bounce
= (char *)_Jv_ThrowNoSuchMethodError
;
1555 ptrdiff_t offset
= (char *)(klass
->vtable
) - bounce
;
1556 klass
->otable
->offsets
[index
] = offset
;
1559 if (target_class
== NULL
)
1562 if (target_class
->isInterface())
1564 // FIXME: This does not yet fully conform to binary compatibility
1565 // rules. It will break if a declaration is moved into a
1567 for (jclass cls
= target_class
; cls
!= 0; cls
= cls
->getSuperclass ())
1569 for (int i
=0; i
< cls
->method_count
; i
++)
1571 meth
= &cls
->methods
[i
];
1572 if (_Jv_equalUtf8Consts (sym
.name
, meth
->name
)
1573 && _Jv_equalUtf8Consts (signature
, meth
->signature
))
1575 klass
->otable
->offsets
[index
] = i
+ 1;
1585 // We're looking for a field or a method, and we can tell
1586 // which is needed by looking at the signature.
1587 if (signature
->length
>= 2
1588 && signature
->data
[0] == '(')
1590 // If the target class does not have a vtable_method_count yet,
1591 // then we can't tell the offsets for its methods, so we must lay
1593 if (target_class
->vtable_method_count
== -1)
1595 JvSynchronize
sync (target_class
);
1596 _Jv_LayoutVTableMethods (target_class
);
1599 meth
= _Jv_LookupDeclaredMethod(target_class
, sym
.name
,
1604 klass
->otable
->offsets
[index
] =
1605 _Jv_VTable::idx_to_offset (meth
->index
);
1613 _Jv_Field
*the_field
= NULL
;
1615 for (jclass cls
= target_class
; cls
!= 0; cls
= cls
->getSuperclass ())
1617 for (int i
= 0; i
< cls
->field_count
; i
++)
1619 _Jv_Field
*field
= &cls
->fields
[i
];
1620 if (! _Jv_equalUtf8Consts (field
->name
, sym
.name
))
1623 // FIXME: What access checks should we perform here?
1624 // if (_Jv_CheckAccess (klass, cls, field->flags))
1627 if (!field
->isResolved ())
1628 _Jv_ResolveField (field
, cls
->loader
);
1630 // if (field_type != 0 && field->type != field_type)
1631 // throw new java::lang::LinkageError
1632 // (JvNewStringLatin1
1633 // ("field type mismatch with different loaders"));
1636 goto end_of_field_search
;
1639 end_of_field_search
:
1640 if (the_field
!= NULL
)
1642 if (the_field
->flags
& 0x0008 /* Modifier::STATIC */)
1644 throw new java::lang::IncompatibleClassChangeError
;
1648 klass
->otable
->offsets
[index
] = the_field
->u
.boffset
;
1653 throw new java::lang::NoSuchFieldError
1654 (_Jv_NewStringUtf8Const (sym
.name
));
1660 if (klass
->atable
== NULL
1661 || klass
->atable
->state
!= 0)
1664 klass
->atable
->state
= 1;
1666 for (index
= 0; sym
= klass
->atable_syms
[index
], sym
.name
!= NULL
; index
++)
1668 // FIXME: Why are we passing NULL as the class loader?
1669 jclass target_class
= _Jv_FindClass (sym
.class_name
, NULL
);
1670 _Jv_Method
*meth
= NULL
;
1671 const _Jv_Utf8Const
*signature
= sym
.signature
;
1673 // ??? Setting this pointer to null will at least get us a
1674 // NullPointerException
1675 klass
->atable
->addresses
[index
] = NULL
;
1677 if (target_class
== NULL
)
1680 // We're looking for a static field or a static method, and we
1681 // can tell which is needed by looking at the signature.
1682 if (signature
->length
>= 2
1683 && signature
->data
[0] == '(')
1685 // If the target class does not have a vtable_method_count yet,
1686 // then we can't tell the offsets for its methods, so we must lay
1688 if (target_class
->vtable_method_count
== -1)
1690 JvSynchronize
sync (target_class
);
1691 _Jv_LayoutVTableMethods (target_class
);
1694 meth
= _Jv_LookupDeclaredMethod(target_class
, sym
.name
,
1699 if (meth
->ncode
) // Maybe abstract?
1700 klass
->atable
->addresses
[index
] = meth
->ncode
;
1702 else if (_Jv_IsInterpretedClass (target_class
))
1703 _Jv_Defer_Resolution (target_class
, meth
,
1704 &klass
->atable
->addresses
[index
]);
1708 klass
->atable
->addresses
[index
] = (void *)_Jv_ThrowNoSuchMethodError
;
1715 _Jv_Field
*the_field
= NULL
;
1717 for (jclass cls
= target_class
; cls
!= 0; cls
= cls
->getSuperclass ())
1719 for (int i
= 0; i
< cls
->field_count
; i
++)
1721 _Jv_Field
*field
= &cls
->fields
[i
];
1722 if (! _Jv_equalUtf8Consts (field
->name
, sym
.name
))
1725 // FIXME: What access checks should we perform here?
1726 // if (_Jv_CheckAccess (klass, cls, field->flags))
1729 if (!field
->isResolved ())
1730 _Jv_ResolveField (field
, cls
->loader
);
1732 // if (field_type != 0 && field->type != field_type)
1733 // throw new java::lang::LinkageError
1734 // (JvNewStringLatin1
1735 // ("field type mismatch with different loaders"));
1738 goto end_of_static_field_search
;
1741 end_of_static_field_search
:
1742 if (the_field
!= NULL
)
1744 if (the_field
->flags
& 0x0008 /* Modifier::STATIC */)
1746 klass
->atable
->addresses
[index
] = the_field
->u
.addr
;
1750 throw new java::lang::IncompatibleClassChangeError
;
1755 throw new java::lang::NoSuchFieldError
1756 (_Jv_NewStringUtf8Const (sym
.name
));
1763 // For each catch_record in the list of caught classes, fill in the
1766 _Jv_linkExceptionClassTable (jclass self
)
1768 struct _Jv_CatchClass
*catch_record
= self
->catch_classes
;
1769 if (!catch_record
|| catch_record
->classname
)
1772 while (catch_record
->classname
)
1774 jclass target_class
= _Jv_FindClass (catch_record
->classname
,
1775 self
->getClassLoaderInternal ());
1776 *catch_record
->address
= target_class
;
1779 self
->catch_classes
->classname
= (_Jv_Utf8Const
*)-1;
1782 // This is put in empty vtable slots.
1784 _Jv_abstractMethodError (void)
1786 throw new java::lang::AbstractMethodError();
1789 // Prepare virtual method declarations in KLASS, and any superclasses as
1790 // required, by determining their vtable index, setting method->index, and
1791 // finally setting the class's vtable_method_count. Must be called with the
1792 // lock for KLASS held.
1794 _Jv_LayoutVTableMethods (jclass klass
)
1796 if (klass
->vtable
!= NULL
|| klass
->isInterface()
1797 || klass
->vtable_method_count
!= -1)
1800 jclass superclass
= klass
->superclass
;
1802 typedef unsigned int uaddr
__attribute__ ((mode (pointer
)));
1804 // If superclass looks like a constant pool entry,
1806 if ((uaddr
)superclass
< (uaddr
)klass
->constants
.size
)
1808 if (klass
->state
< JV_STATE_LINKED
)
1810 _Jv_Utf8Const
*name
= klass
->constants
.data
[(int)superclass
].utf8
;
1811 superclass
= _Jv_FindClass (name
, klass
->loader
);
1814 jstring str
= _Jv_NewStringUTF (name
->data
);
1815 throw new java::lang::NoClassDefFoundError (str
);
1819 superclass
= klass
->constants
.data
[(int)superclass
].clazz
;
1822 if (superclass
!= NULL
&& superclass
->vtable_method_count
== -1)
1824 JvSynchronize
sync (superclass
);
1825 _Jv_LayoutVTableMethods (superclass
);
1828 int index
= (superclass
== NULL
? 0 : superclass
->vtable_method_count
);
1830 for (int i
= 0; i
< klass
->method_count
; ++i
)
1832 _Jv_Method
*meth
= &klass
->methods
[i
];
1833 _Jv_Method
*super_meth
= NULL
;
1835 if (! _Jv_isVirtualMethod (meth
))
1838 // FIXME: Must check that we don't override:
1839 // - Package-private method where superclass is in different package.
1840 // - Final or less-accessible declaration in superclass (check binary
1841 // spec, do we allocate new vtable entry or put throw node in vtable?)
1842 // - Static or private method in superclass.
1844 if (superclass
!= NULL
)
1846 super_meth
= _Jv_LookupDeclaredMethod (superclass
, meth
->name
,
1851 meth
->index
= super_meth
->index
;
1853 meth
->index
= index
++;
1856 klass
->vtable_method_count
= index
;
1859 // Set entries in VTABLE for virtual methods declared in KLASS. If
1860 // KLASS has an immediate abstract parent, recursively do its methods
1861 // first. FLAGS is used to determine which slots we've actually set.
1863 _Jv_SetVTableEntries (jclass klass
, _Jv_VTable
*vtable
, jboolean
*flags
)
1865 using namespace java::lang::reflect
;
1867 jclass superclass
= klass
->getSuperclass();
1869 if (superclass
!= NULL
&& (superclass
->getModifiers() & Modifier::ABSTRACT
))
1870 _Jv_SetVTableEntries (superclass
, vtable
, flags
);
1872 for (int i
= klass
->method_count
- 1; i
>= 0; i
--)
1874 _Jv_Method
*meth
= &klass
->methods
[i
];
1875 if (meth
->index
== (_Jv_ushort
) -1)
1877 if ((meth
->accflags
& Modifier::ABSTRACT
))
1879 vtable
->set_method(meth
->index
, (void *) &_Jv_abstractMethodError
);
1880 flags
[meth
->index
] = false;
1884 vtable
->set_method(meth
->index
, meth
->ncode
);
1885 flags
[meth
->index
] = true;
1890 // Allocate and lay out the virtual method table for KLASS. This will also
1891 // cause vtables to be generated for any non-abstract superclasses, and
1892 // virtual method layout to occur for any abstract superclasses. Must be
1893 // called with monitor lock for KLASS held.
1895 _Jv_MakeVTable (jclass klass
)
1897 using namespace java::lang::reflect
;
1899 if (klass
->vtable
!= NULL
|| klass
->isInterface()
1900 || (klass
->accflags
& Modifier::ABSTRACT
))
1903 // out before we can create a vtable.
1904 if (klass
->vtable_method_count
== -1)
1905 _Jv_LayoutVTableMethods (klass
);
1907 // Allocate the new vtable.
1908 _Jv_VTable
*vtable
= _Jv_VTable::new_vtable (klass
->vtable_method_count
);
1909 klass
->vtable
= vtable
;
1911 jboolean flags
[klass
->vtable_method_count
];
1912 for (int i
= 0; i
< klass
->vtable_method_count
; ++i
)
1915 // Copy the vtable of the closest non-abstract superclass.
1916 jclass superclass
= klass
->superclass
;
1917 if (superclass
!= NULL
)
1919 while ((superclass
->accflags
& Modifier::ABSTRACT
) != 0)
1920 superclass
= superclass
->superclass
;
1922 if (superclass
->vtable
== NULL
)
1924 JvSynchronize
sync (superclass
);
1925 _Jv_MakeVTable (superclass
);
1928 for (int i
= 0; i
< superclass
->vtable_method_count
; ++i
)
1930 vtable
->set_method (i
, superclass
->vtable
->get_method (i
));
1935 // Set the class pointer and GC descriptor.
1936 vtable
->clas
= klass
;
1937 vtable
->gc_descr
= _Jv_BuildGCDescr (klass
);
1939 // For each virtual declared in klass and any immediate abstract
1940 // superclasses, set new vtable entry or override an old one.
1941 _Jv_SetVTableEntries (klass
, vtable
, flags
);
1943 // It is an error to have an abstract method in a concrete class.
1944 if (! (klass
->accflags
& Modifier::ABSTRACT
))
1946 for (int i
= 0; i
< klass
->vtable_method_count
; ++i
)
1949 using namespace java::lang
;
1950 while (klass
!= NULL
)
1952 for (int j
= 0; j
< klass
->method_count
; ++j
)
1954 if (klass
->methods
[i
].index
== i
)
1956 StringBuffer
*buf
= new StringBuffer ();
1957 buf
->append (_Jv_NewStringUtf8Const (klass
->methods
[i
].name
));
1958 buf
->append ((jchar
) ' ');
1959 buf
->append (_Jv_NewStringUtf8Const (klass
->methods
[i
].signature
));
1960 throw new AbstractMethodError (buf
->toString ());
1963 klass
= klass
->getSuperclass ();
1965 // Couldn't find the name, which is weird.
1966 // But we still must throw the error.
1967 throw new AbstractMethodError ();