OSDN Git Service

* java/lang/ClassLoader.java (setSigners): Implemented.
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natClass.cc
1 // natClass.cc - Implementation of java.lang.Class native methods.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <limits.h>
14 #include <string.h>
15
16 #pragma implementation "Class.h"
17
18 #include <gcj/cni.h>
19 #include <jvm.h>
20 #include <java-threads.h>
21
22 #include <java/lang/Class.h>
23 #include <java/lang/ClassLoader.h>
24 #include <java/lang/String.h>
25 #include <java/lang/reflect/Modifier.h>
26 #include <java/lang/reflect/Member.h>
27 #include <java/lang/reflect/Method.h>
28 #include <java/lang/reflect/Field.h>
29 #include <java/lang/reflect/Constructor.h>
30 #include <java/lang/AbstractMethodError.h>
31 #include <java/lang/ArrayStoreException.h>
32 #include <java/lang/ClassCastException.h>
33 #include <java/lang/ClassNotFoundException.h>
34 #include <java/lang/ExceptionInInitializerError.h>
35 #include <java/lang/IllegalAccessException.h>
36 #include <java/lang/IllegalAccessError.h>
37 #include <java/lang/IllegalArgumentException.h>
38 #include <java/lang/IncompatibleClassChangeError.h>
39 #include <java/lang/NoSuchFieldError.h>
40 #include <java/lang/ArrayIndexOutOfBoundsException.h>
41 #include <java/lang/InstantiationException.h>
42 #include <java/lang/NoClassDefFoundError.h>
43 #include <java/lang/NoSuchFieldException.h>
44 #include <java/lang/NoSuchMethodError.h>
45 #include <java/lang/NoSuchMethodException.h>
46 #include <java/lang/Thread.h>
47 #include <java/lang/NullPointerException.h>
48 #include <java/lang/RuntimePermission.h>
49 #include <java/lang/System.h>
50 #include <java/lang/SecurityManager.h>
51 #include <java/lang/StringBuffer.h>
52 #include <java/lang/VMClassLoader.h>
53 #include <gnu/gcj/runtime/StackTrace.h>
54 #include <gcj/method.h>
55 #include <gnu/gcj/runtime/MethodRef.h>
56 #include <gnu/gcj/RawData.h>
57
58 #include <java-cpool.h>
59
60 \f
61
62 using namespace gcj;
63
64 jclass
65 java::lang::Class::forName (jstring className, jboolean initialize,
66                             java::lang::ClassLoader *loader)
67 {
68   if (! className)
69     throw new java::lang::NullPointerException;
70
71   jsize length = _Jv_GetStringUTFLength (className);
72   char buffer[length];
73   _Jv_GetStringUTFRegion (className, 0, length, buffer);
74
75   _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);
76
77   if (! _Jv_VerifyClassName (name))
78     throw new java::lang::ClassNotFoundException (className);
79
80   jclass klass = (buffer[0] == '[' 
81                   ? _Jv_FindClassFromSignature (name->data, loader)
82                   : _Jv_FindClass (name, loader));
83
84   if (klass == NULL)
85     throw new java::lang::ClassNotFoundException (className);
86
87   if (initialize)
88     _Jv_InitClass (klass);
89
90   return klass;
91 }
92
93 jclass
94 java::lang::Class::forName (jstring className)
95 {
96   java::lang::ClassLoader *loader = NULL;
97   gnu::gcj::runtime::StackTrace *t 
98     = new gnu::gcj::runtime::StackTrace(4);
99   java::lang::Class *klass = NULL;
100   try
101     {
102       for (int i = 1; !klass; i++)
103         {
104           klass = t->classAt (i);
105         }
106       loader = klass->getClassLoaderInternal();
107     }
108   catch (::java::lang::ArrayIndexOutOfBoundsException *e)
109     {
110     }
111
112   return forName (className, true, loader);
113 }
114
115 java::lang::ClassLoader *
116 java::lang::Class::getClassLoader (void)
117 {
118   java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
119   if (s != NULL)
120     {
121       gnu::gcj::runtime::StackTrace *t 
122         = new gnu::gcj::runtime::StackTrace(4);
123       Class *caller = NULL;
124       ClassLoader *caller_loader = NULL;
125       try
126         {
127           for (int i = 1; !caller; i++)
128             {
129               caller = t->classAt (i);
130             }
131           caller_loader = caller->getClassLoaderInternal();
132         }
133       catch (::java::lang::ArrayIndexOutOfBoundsException *e)
134         {
135         }
136
137       // If the caller has a non-null class loader, and that loader
138       // is not this class' loader or an ancestor thereof, then do a
139       // security check.
140       if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
141         s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
142     }
143
144   // The spec requires us to return `null' for primitive classes.  In
145   // other cases we have the option of returning `null' for classes
146   // loaded with the bootstrap loader.  All gcj-compiled classes which
147   // are linked into the application used to return `null' here, but
148   // that confuses some poorly-written applications.  It is a useful
149   // and apparently harmless compatibility hack to simply never return
150   // `null' instead.
151   if (isPrimitive ())
152     return NULL;
153   return loader ? loader : ClassLoader::getSystemClassLoader ();
154 }
155
156 java::lang::reflect::Constructor *
157 java::lang::Class::getConstructor (JArray<jclass> *param_types)
158 {
159   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
160
161   jstring partial_sig = getSignature (param_types, true);
162   jint hash = partial_sig->hashCode ();
163
164   int i = isPrimitive () ? 0 : method_count;
165   while (--i >= 0)
166     {
167       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
168           && _Jv_equal (methods[i].signature, partial_sig, hash))
169         {
170           // Found it.  For getConstructor, the constructor must be
171           // public.
172           using namespace java::lang::reflect;
173           if (! Modifier::isPublic(methods[i].accflags))
174             break;
175           Constructor *cons = new Constructor ();
176           cons->offset = (char *) (&methods[i]) - (char *) methods;
177           cons->declaringClass = this;
178           return cons;
179         }
180     }
181   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
182 }
183
184 JArray<java::lang::reflect::Constructor *> *
185 java::lang::Class::_getConstructors (jboolean declared)
186 {
187   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
188
189   int numConstructors = 0;
190   int max = isPrimitive () ? 0 : method_count;
191   int i;
192   for (i = max; --i >= 0; )
193     {
194       _Jv_Method *method = &methods[i];
195       if (method->name == NULL
196           || ! _Jv_equalUtf8Consts (method->name, init_name))
197         continue;
198       if (! declared
199           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
200         continue;
201       numConstructors++;
202     }
203   JArray<java::lang::reflect::Constructor *> *result
204     = (JArray<java::lang::reflect::Constructor *> *)
205     JvNewObjectArray (numConstructors,
206                       &java::lang::reflect::Constructor::class$,
207                       NULL);
208   java::lang::reflect::Constructor** cptr = elements (result);
209   for (i = 0;  i < max;  i++)
210     {
211       _Jv_Method *method = &methods[i];
212       if (method->name == NULL
213           || ! _Jv_equalUtf8Consts (method->name, init_name))
214         continue;
215       if (! declared
216           && ! java::lang::reflect::Modifier::isPublic(method->accflags))
217         continue;
218       java::lang::reflect::Constructor *cons
219         = new java::lang::reflect::Constructor ();
220       cons->offset = (char *) method - (char *) methods;
221       cons->declaringClass = this;
222       *cptr++ = cons;
223     }
224   return result;
225 }
226
227 java::lang::reflect::Constructor *
228 java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
229 {
230   memberAccessCheck(java::lang::reflect::Member::DECLARED);
231
232   jstring partial_sig = getSignature (param_types, true);
233   jint hash = partial_sig->hashCode ();
234
235   int i = isPrimitive () ? 0 : method_count;
236   while (--i >= 0)
237     {
238       if (_Jv_equalUtf8Consts (methods[i].name, init_name)
239           && _Jv_equal (methods[i].signature, partial_sig, hash))
240         {
241           // Found it.
242           using namespace java::lang::reflect;
243           Constructor *cons = new Constructor ();
244           cons->offset = (char *) (&methods[i]) - (char *) methods;
245           cons->declaringClass = this;
246           return cons;
247         }
248     }
249   throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
250 }
251
252 java::lang::reflect::Field *
253 java::lang::Class::getField (jstring name, jint hash)
254 {
255   java::lang::reflect::Field* rfield;
256   for (int i = 0;  i < field_count;  i++)
257     {
258       _Jv_Field *field = &fields[i];
259       if (! _Jv_equal (field->name, name, hash))
260         continue;
261       if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
262         continue;
263       rfield = new java::lang::reflect::Field ();
264       rfield->offset = (char*) field - (char*) fields;
265       rfield->declaringClass = this;
266       rfield->name = name;
267       return rfield;
268     }
269   jclass superclass = getSuperclass();
270   if (superclass == NULL)
271     return NULL;
272   rfield = superclass->getField(name, hash);
273   for (int i = 0; i < interface_count && rfield == NULL; ++i)
274     rfield = interfaces[i]->getField (name, hash);
275   return rfield;
276 }
277
278 java::lang::reflect::Field *
279 java::lang::Class::getDeclaredField (jstring name)
280 {
281   memberAccessCheck(java::lang::reflect::Member::DECLARED);
282   int hash = name->hashCode();
283   for (int i = 0;  i < field_count;  i++)
284     {
285       _Jv_Field *field = &fields[i];
286       if (! _Jv_equal (field->name, name, hash))
287         continue;
288       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
289       rfield->offset = (char*) field - (char*) fields;
290       rfield->declaringClass = this;
291       rfield->name = name;
292       return rfield;
293     }
294   throw new java::lang::NoSuchFieldException (name);
295 }
296
297 JArray<java::lang::reflect::Field *> *
298 java::lang::Class::getDeclaredFields (void)
299 {
300   memberAccessCheck(java::lang::reflect::Member::DECLARED);
301   JArray<java::lang::reflect::Field *> *result
302     = (JArray<java::lang::reflect::Field *> *)
303     JvNewObjectArray (field_count, &java::lang::reflect::Field::class$, NULL);
304   java::lang::reflect::Field** fptr = elements (result);
305   for (int i = 0;  i < field_count;  i++)
306     {
307       _Jv_Field *field = &fields[i];
308       java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
309       rfield->offset = (char*) field - (char*) fields;
310       rfield->declaringClass = this;
311       *fptr++ = rfield;
312     }
313   return result;
314 }
315
316 void
317 java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
318 {
319   if (isPrimitive())
320     buffer->append((jchar) method_count);
321   else
322     {
323       jstring name = getName();
324       if (name->charAt(0) != '[')
325         buffer->append((jchar) 'L');
326       buffer->append(name);
327       if (name->charAt(0) != '[')
328         buffer->append((jchar) ';');
329     }
330 }
331
332 // This doesn't have to be native.  It is an implementation detail
333 // only called from the C++ code, though, so maybe this is clearer.
334 jstring
335 java::lang::Class::getSignature (JArray<jclass> *param_types,
336                                  jboolean is_constructor)
337 {
338   java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
339   buf->append((jchar) '(');
340   // A NULL param_types means "no parameters".
341   if (param_types != NULL)
342     {
343       jclass *v = elements (param_types);
344       for (int i = 0; i < param_types->length; ++i)
345         v[i]->getSignature(buf);
346     }
347   buf->append((jchar) ')');
348   if (is_constructor)
349     buf->append((jchar) 'V');
350   return buf->toString();
351 }
352
353 java::lang::reflect::Method *
354 java::lang::Class::_getDeclaredMethod (jstring name,
355                                        JArray<jclass> *param_types)
356 {
357   jstring partial_sig = getSignature (param_types, false);
358   jint p_len = partial_sig->length();
359   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
360   int i = isPrimitive () ? 0 : method_count;
361   while (--i >= 0)
362     {
363       if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
364           && _Jv_equaln (methods[i].signature, partial_sig, p_len)
365           && (methods[i].accflags
366               & java::lang::reflect::Modifier::INVISIBLE) == 0)
367         {
368           // Found it.
369           using namespace java::lang::reflect;
370           Method *rmethod = new Method ();
371           rmethod->offset = (char*) (&methods[i]) - (char*) methods;
372           rmethod->declaringClass = this;
373           return rmethod;
374         }
375     }
376   return NULL;
377 }
378
379 JArray<java::lang::reflect::Method *> *
380 java::lang::Class::getDeclaredMethods (void)
381 {
382   memberAccessCheck(java::lang::reflect::Member::DECLARED);
383
384   int numMethods = 0;
385   int max = isPrimitive () ? 0 : method_count;
386   int i;
387   for (i = max; --i >= 0; )
388     {
389       _Jv_Method *method = &methods[i];
390       if (method->name == NULL
391           || _Jv_equalUtf8Consts (method->name, clinit_name)
392           || _Jv_equalUtf8Consts (method->name, init_name)
393           || _Jv_equalUtf8Consts (method->name, finit_name)
394           || (methods[i].accflags
395               & java::lang::reflect::Modifier::INVISIBLE) != 0)
396         continue;
397       numMethods++;
398     }
399   JArray<java::lang::reflect::Method *> *result
400     = (JArray<java::lang::reflect::Method *> *)
401     JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
402   java::lang::reflect::Method** mptr = elements (result);
403   for (i = 0;  i < max;  i++)
404     {
405       _Jv_Method *method = &methods[i];
406       if (method->name == NULL
407           || _Jv_equalUtf8Consts (method->name, clinit_name)
408           || _Jv_equalUtf8Consts (method->name, init_name)
409           || _Jv_equalUtf8Consts (method->name, finit_name)
410           || (methods[i].accflags
411               & java::lang::reflect::Modifier::INVISIBLE) != 0)
412         continue;
413       java::lang::reflect::Method* rmethod
414         = new java::lang::reflect::Method ();
415       rmethod->offset = (char*) method - (char*) methods;
416       rmethod->declaringClass = this;
417       *mptr++ = rmethod;
418     }
419   return result;
420 }
421
422 jstring
423 java::lang::Class::getName (void)
424 {
425   char buffer[name->length + 1];  
426   memcpy (buffer, name->data, name->length); 
427   buffer[name->length] = '\0';
428   return _Jv_NewStringUTF (buffer);
429 }
430
431 JArray<jclass> *
432 java::lang::Class::getClasses (void)
433 {
434   // FIXME: security checking.
435
436   // Until we have inner classes, it always makes sense to return an
437   // empty array.
438   JArray<jclass> *result
439     = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
440                                            NULL);
441   return result;
442 }
443
444 JArray<jclass> *
445 java::lang::Class::getDeclaredClasses (void)
446 {
447   memberAccessCheck (java::lang::reflect::Member::DECLARED);
448   // Until we have inner classes, it always makes sense to return an
449   // empty array.
450   JArray<jclass> *result
451     = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$,
452                                            NULL);
453   return result;
454 }
455
456 jclass
457 java::lang::Class::getDeclaringClass (void)
458 {
459   // Until we have inner classes, it makes sense to always return
460   // NULL.
461   return NULL;
462 }
463
464 jint
465 java::lang::Class::_getFields (JArray<java::lang::reflect::Field *> *result,
466                                jint offset)
467 {
468   int count = 0;
469   for (int i = 0;  i < field_count;  i++)
470     {
471       _Jv_Field *field = &fields[i];
472       if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
473         continue;
474       ++count;
475
476       if (result != NULL)
477         {
478           java::lang::reflect::Field *rfield
479             = new java::lang::reflect::Field ();
480           rfield->offset = (char *) field - (char *) fields;
481           rfield->declaringClass = this;
482           rfield->name = _Jv_NewStringUtf8Const (field->name);
483           (elements (result))[offset++] = rfield;
484         }
485     }
486   jclass superclass = getSuperclass();
487   if (superclass != NULL)
488     {
489       int s_count = superclass->_getFields (result, offset);
490       count += s_count;
491       offset += s_count;
492     }
493   for (int i = 0; i < interface_count; ++i)
494     {
495       int f_count = interfaces[i]->_getFields (result, offset);
496       count += f_count;
497       offset += f_count;
498     }
499   return count;
500 }
501
502 JArray<java::lang::reflect::Field *> *
503 java::lang::Class::getFields (void)
504 {
505   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
506
507   int count = _getFields (NULL, 0);
508
509   JArray<java::lang::reflect::Field *> *result
510     = ((JArray<java::lang::reflect::Field *> *)
511        JvNewObjectArray (count, &java::lang::reflect::Field::class$, NULL));
512
513   _getFields (result, 0);
514
515   return result;
516 }
517
518 JArray<jclass> *
519 java::lang::Class::getInterfaces (void)
520 {
521   jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
522   jobject *data = elements (r);
523   for (int i = 0; i < interface_count; ++i)
524     data[i] = interfaces[i];
525   return reinterpret_cast<JArray<jclass> *> (r);
526 }
527
528 java::lang::reflect::Method *
529 java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
530 {
531   jstring partial_sig = getSignature (param_types, false);
532   jint p_len = partial_sig->length();
533   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
534   for (Class *klass = this; klass; klass = klass->getSuperclass())
535     {
536       int i = klass->isPrimitive () ? 0 : klass->method_count;
537       while (--i >= 0)
538         {
539           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
540               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
541               && (klass->methods[i].accflags
542                   & java::lang::reflect::Modifier::INVISIBLE) == 0)
543             {
544               // Found it.
545               using namespace java::lang::reflect;
546
547               // Method must be public.
548               if (! Modifier::isPublic (klass->methods[i].accflags))
549                 break;
550
551               Method *rmethod = new Method ();
552               rmethod->offset = ((char *) (&klass->methods[i])
553                                  - (char *) klass->methods);
554               rmethod->declaringClass = klass;
555               return rmethod;
556             }
557         }
558     }
559
560   // If we haven't found a match, and this class is an interface, then
561   // check all the superinterfaces.
562   if (isInterface())
563     {
564       for (int i = 0; i < interface_count; ++i)
565         {
566           using namespace java::lang::reflect;
567           Method *rmethod = interfaces[i]->_getMethod (name, param_types);
568           if (rmethod != NULL)
569             return rmethod;
570         }
571     }
572
573   return NULL;
574 }
575
576 // This is a very slow implementation, since it re-scans all the
577 // methods we've already listed to make sure we haven't duplicated a
578 // method.  It also over-estimates the required size, so we have to
579 // shrink the result array later.
580 jint
581 java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
582                                 jint offset)
583 {
584   jint count = 0;
585
586   // First examine all local methods
587   for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
588     {
589       _Jv_Method *method = &methods[i];
590       if (method->name == NULL
591           || _Jv_equalUtf8Consts (method->name, clinit_name)
592           || _Jv_equalUtf8Consts (method->name, init_name)
593           || _Jv_equalUtf8Consts (method->name, finit_name)
594           || (method->accflags
595               & java::lang::reflect::Modifier::INVISIBLE) != 0)
596         continue;
597       // Only want public methods.
598       if (! java::lang::reflect::Modifier::isPublic (method->accflags))
599         continue;
600
601       // This is where we over-count the slots required if we aren't
602       // filling the result for real.
603       if (result != NULL)
604         {
605           jboolean add = true;
606           java::lang::reflect::Method **mp = elements (result);
607           // If we already have a method with this name and signature,
608           // then ignore this one.  This can happen with virtual
609           // methods.
610           for (int j = 0; j < offset; ++j)
611             {
612               _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
613               if (_Jv_equalUtf8Consts (method->name, meth_2->name)
614                   && _Jv_equalUtf8Consts (method->signature,
615                                           meth_2->signature))
616                 {
617                   add = false;
618                   break;
619                 }
620             }
621           if (! add)
622             continue;
623         }
624
625       if (result != NULL)
626         {
627           using namespace java::lang::reflect;
628           Method *rmethod = new Method ();
629           rmethod->offset = (char *) method - (char *) methods;
630           rmethod->declaringClass = this;
631           Method **mp = elements (result);
632           mp[offset + count] = rmethod;
633         }
634       ++count;
635     }
636   offset += count;
637
638   // Now examine superclasses.
639   if (getSuperclass () != NULL)
640     {
641       jint s_count = getSuperclass()->_getMethods (result, offset);
642       offset += s_count;
643       count += s_count;
644     }
645
646   // Finally, examine interfaces.
647   for (int i = 0; i < interface_count; ++i)
648     {
649       int f_count = interfaces[i]->_getMethods (result, offset);
650       count += f_count;
651       offset += f_count;
652     }
653
654   return count;
655 }
656
657 JArray<java::lang::reflect::Method *> *
658 java::lang::Class::getMethods (void)
659 {
660   using namespace java::lang::reflect;
661
662   memberAccessCheck(Member::PUBLIC);
663
664   // This will overestimate the size we need.
665   jint count = _getMethods (NULL, 0);
666
667   JArray<Method *> *result
668     = ((JArray<Method *> *) JvNewObjectArray (count,
669                                               &Method::class$,
670                                               NULL));
671
672   // When filling the array for real, we get the actual count.  Then
673   // we resize the array.
674   jint real_count = _getMethods (result, 0);
675
676   if (real_count != count)
677     {
678       JArray<Method *> *r2
679         = ((JArray<Method *> *) JvNewObjectArray (real_count,
680                                                   &Method::class$,
681                                                   NULL));
682       
683       Method **destp = elements (r2);
684       Method **srcp = elements (result);
685
686       for (int i = 0; i < real_count; ++i)
687         *destp++ = *srcp++;
688
689       result = r2;
690     }
691
692   return result;
693 }
694
695 jboolean
696 java::lang::Class::isAssignableFrom (jclass klass)
697 {
698   // Arguments may not have been initialized, given ".class" syntax.
699   _Jv_InitClass (this);
700   _Jv_InitClass (klass);
701   return _Jv_IsAssignableFrom (this, klass);
702 }
703
704 jboolean
705 java::lang::Class::isInstance (jobject obj)
706 {
707   if (! obj)
708     return false;
709   _Jv_InitClass (this);
710   return _Jv_IsAssignableFrom (this, JV_CLASS (obj));
711 }
712
713 jobject
714 java::lang::Class::newInstance (void)
715 {
716   memberAccessCheck(java::lang::reflect::Member::PUBLIC);
717
718   if (isPrimitive ()
719       || isInterface ()
720       || isArray ()
721       || java::lang::reflect::Modifier::isAbstract(accflags))
722     throw new java::lang::InstantiationException (getName ());
723
724   _Jv_InitClass (this);
725
726   _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
727   if (! meth)
728     throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
729
730   jobject r = JvAllocObject (this);
731   ((void (*) (jobject)) meth->ncode) (r);
732   return r;
733 }
734
735 void
736 java::lang::Class::finalize (void)
737 {
738 #ifdef INTERPRETER
739   JvAssert (_Jv_IsInterpretedClass (this));
740   _Jv_UnregisterClass (this);
741 #endif
742 }
743
744 // This implements the initialization process for a class.  From Spec
745 // section 12.4.2.
746 void
747 java::lang::Class::initializeClass (void)
748 {
749   // short-circuit to avoid needless locking.
750   if (state == JV_STATE_DONE)
751     return;
752
753   // Step 1.
754   _Jv_MonitorEnter (this);
755
756   if (state < JV_STATE_LINKED)
757     {    
758 #ifdef INTERPRETER
759       if (_Jv_IsInterpretedClass (this))
760         {
761           // this can throw exceptions, so exit the monitor as a precaution.
762           _Jv_MonitorExit (this);
763           java::lang::VMClassLoader::resolveClass (this);
764           _Jv_MonitorEnter (this);
765         }
766       else
767 #endif
768         {
769           _Jv_PrepareCompiledClass (this);
770         }
771     }
772
773   // Step 2.
774   java::lang::Thread *self = java::lang::Thread::currentThread();
775   // FIXME: `self' can be null at startup.  Hence this nasty trick.
776   self = (java::lang::Thread *) ((long) self | 1);
777   while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
778     wait ();
779
780   // Steps 3 &  4.
781   if (state == JV_STATE_DONE)
782     {
783       _Jv_MonitorExit (this);
784       return;
785     }
786   if (state == JV_STATE_IN_PROGRESS)
787     {
788       _Jv_MonitorExit (this);
789
790       /* Initialization in progress.  The class is linked now,
791          so ensure internal tables are built.  */
792       _Jv_PrepareConstantTimeTables (this);
793       _Jv_MakeVTable(this);
794       _Jv_LinkSymbolTable(this);
795
796       return;
797     }
798
799   // Step 5.
800   if (state == JV_STATE_ERROR)
801     {
802       _Jv_MonitorExit (this);
803       throw new java::lang::NoClassDefFoundError (getName());
804     }
805
806   // Step 6.
807   thread = self;
808   state = JV_STATE_IN_PROGRESS;
809   _Jv_MonitorExit (this);
810
811   // Step 7.
812   if (! isInterface () && superclass)
813     {
814       try
815         {
816           _Jv_InitClass (superclass);
817         }
818       catch (java::lang::Throwable *except)
819         {
820           // Caught an exception.
821           _Jv_MonitorEnter (this);
822           state = JV_STATE_ERROR;
823           notifyAll ();
824           _Jv_MonitorExit (this);
825           throw except;
826         }
827     }
828
829   _Jv_PrepareConstantTimeTables (this);
830
831   if (vtable == NULL)
832     _Jv_MakeVTable(this);
833
834   if (otable || atable)
835     _Jv_LinkSymbolTable(this);
836
837   // Steps 8, 9, 10, 11.
838   try
839     {
840       _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
841                                              void_signature);
842       if (meth)
843         ((void (*) (void)) meth->ncode) ();
844     }
845   catch (java::lang::Throwable *except)
846     {
847       if (! java::lang::Error::class$.isInstance(except))
848         {
849           try
850             {
851               except = new ExceptionInInitializerError (except);
852             }
853           catch (java::lang::Throwable *t)
854             {
855               except = t;
856             }
857         }
858       _Jv_MonitorEnter (this);
859       state = JV_STATE_ERROR;
860       notifyAll ();
861       _Jv_MonitorExit (this);
862       throw except;
863     }
864
865   _Jv_MonitorEnter (this);
866   state = JV_STATE_DONE;
867   notifyAll ();
868   _Jv_MonitorExit (this);
869 }
870
871 \f
872
873 //
874 // Some class-related convenience functions.
875 //
876
877 // Find a method declared in the class.  If it is not declared locally
878 // (or if it is inherited), return NULL.
879 _Jv_Method *
880 _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
881                     _Jv_Utf8Const *signature)
882 {
883   for (int i = 0; i < klass->method_count; ++i)
884     {
885       if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
886           && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
887         return &klass->methods[i];
888     }
889   return NULL;
890 }
891
892 _Jv_Method *
893 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
894                           _Jv_Utf8Const *signature)
895 {
896   for (; klass; klass = klass->getSuperclass())
897     {
898       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
899
900       if (meth)
901         return meth;
902     }
903
904   return NULL;
905 }
906
907 // NOTE: MCACHE_SIZE should be a power of 2 minus one.
908 #define MCACHE_SIZE 1023
909
910 struct _Jv_mcache
911 {
912   jclass klass;
913   _Jv_Method *method;
914 };
915
916 static _Jv_mcache method_cache[MCACHE_SIZE + 1];
917
918 static void *
919 _Jv_FindMethodInCache (jclass klass,
920                        _Jv_Utf8Const *name,
921                        _Jv_Utf8Const *signature)
922 {
923   int index = name->hash & MCACHE_SIZE;
924   _Jv_mcache *mc = method_cache + index;
925   _Jv_Method *m = mc->method;
926
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;
932   return NULL;
933 }
934
935 static void
936 _Jv_AddMethodToCache (jclass klass,
937                        _Jv_Method *method)
938 {
939   _Jv_MonitorEnter (&java::lang::Class::class$); 
940
941   int index = method->name->hash & MCACHE_SIZE;
942
943   method_cache[index].method = method;
944   method_cache[index].klass = klass;
945
946   _Jv_MonitorExit (&java::lang::Class::class$);
947 }
948
949 void *
950 _Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
951                            _Jv_Utf8Const *signature)
952 {
953   using namespace java::lang::reflect;
954
955   void *ncode = _Jv_FindMethodInCache (klass, name, signature);
956   if (ncode != 0)
957     return ncode;
958
959   for (; klass; klass = klass->getSuperclass())
960     {
961       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
962       if (! meth)
963         continue;
964
965       if (Modifier::isStatic(meth->accflags))
966         throw new java::lang::IncompatibleClassChangeError
967           (_Jv_GetMethodString (klass, meth->name));
968       if (Modifier::isAbstract(meth->accflags))
969         throw new java::lang::AbstractMethodError
970           (_Jv_GetMethodString (klass, meth->name));
971       if (! Modifier::isPublic(meth->accflags))
972         throw new java::lang::IllegalAccessError
973           (_Jv_GetMethodString (klass, meth->name));
974
975       _Jv_AddMethodToCache (klass, meth);
976
977       return meth->ncode;
978     }
979   throw new java::lang::IncompatibleClassChangeError;
980 }
981
982 // Fast interface method lookup by index.
983 void *
984 _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
985 {
986   _Jv_IDispatchTable *cldt = klass->idt;
987   int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx;
988   return cldt->cls.itable[idx];
989 }
990
991 jboolean
992 _Jv_IsAssignableFrom (jclass target, jclass source)
993 {
994   if (source == target)
995     return true;
996
997   // If target is array, so must source be.  
998   while (target->isArray ())
999     {
1000       if (! source->isArray())
1001         return false;
1002       target = target->getComponentType();
1003       source = source->getComponentType();
1004     }
1005
1006   if (target->isInterface())
1007     {
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);
1013
1014       _Jv_IDispatchTable *cl_idt = source->idt;
1015       _Jv_IDispatchTable *if_idt = target->idt;
1016
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])
1021         {
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)
1025             return true;
1026         }
1027       return false;
1028     }
1029
1030   // Primitive TYPE classes are only assignable to themselves.
1031   if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
1032     return false;
1033
1034   if (target == &java::lang::Object::class$)
1035     return true;
1036   else if (source->ancestors == NULL || target->ancestors == NULL)
1037     {
1038       // We need this case when either SOURCE or TARGET has not has
1039       // its constant-time tables prepared.
1040
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$)
1044         {
1045           if (source == target)
1046             return true;
1047           source = source->getSuperclass();
1048         }
1049     }
1050   else if (source->depth >= target->depth
1051            && source->ancestors[source->depth - target->depth] == target)
1052     return true;
1053
1054   return false;
1055 }
1056
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.
1060 jboolean
1061 _Jv_InterfaceAssignableFrom (jclass iface, jclass source)
1062 {
1063   for (int i = 0; i < source->interface_count; i++)
1064     {
1065       jclass interface = source->interfaces[i];
1066       if (iface == interface
1067           || _Jv_InterfaceAssignableFrom (iface, interface))
1068         return true;      
1069     }
1070     
1071   if (!source->isInterface()
1072       && source->superclass 
1073       && _Jv_InterfaceAssignableFrom (iface, source->superclass))
1074     return true;
1075         
1076   return false;
1077 }
1078
1079 jboolean
1080 _Jv_IsInstanceOf(jobject obj, jclass cl)
1081 {
1082   if (__builtin_expect (!obj, false))
1083     return false;
1084   return (_Jv_IsAssignableFrom (cl, JV_CLASS (obj)));
1085 }
1086
1087 void *
1088 _Jv_CheckCast (jclass c, jobject obj)
1089 {
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());
1097
1098   return obj;
1099 }
1100
1101 void
1102 _Jv_CheckArrayStore (jobject arr, jobject obj)
1103 {
1104   if (obj)
1105     {
1106       JvAssert (arr != NULL);
1107       jclass elt_class = (JV_CLASS (arr))->getComponentType();
1108       if (elt_class == &java::lang::Object::class$)
1109         return;
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());
1119     }
1120 }
1121
1122 #define INITIAL_IOFFSETS_LEN 4
1123 #define INITIAL_IFACES_LEN 4
1124
1125 static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
1126
1127 // Generate tables for constant-time assignment testing and interface
1128 // method lookup. This implements the technique described by Per Bothner
1129 // <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
1130 // http://gcc.gnu.org/ml/java/1999-q3/msg00377.html
1131 void 
1132 _Jv_PrepareConstantTimeTables (jclass klass)
1133 {  
1134   if (klass->isPrimitive () || klass->isInterface ())
1135     return;
1136   
1137   // Short-circuit in case we've been called already.
1138   if ((klass->idt != NULL) || klass->depth != 0)
1139     return;
1140
1141   // Calculate the class depth and ancestor table. The depth of a class 
1142   // is how many "extends" it is removed from Object. Thus the depth of 
1143   // java.lang.Object is 0, but the depth of java.io.FilterOutputStream 
1144   // is 2. Depth is defined for all regular and array classes, but not 
1145   // interfaces or primitive types.
1146    
1147   jclass klass0 = klass;
1148   jboolean has_interfaces = 0;
1149   while (klass0 != &java::lang::Object::class$)
1150     {
1151       has_interfaces += klass0->interface_count;
1152       klass0 = klass0->superclass;
1153       klass->depth++;
1154     }
1155
1156   // We do class member testing in constant time by using a small table 
1157   // of all the ancestor classes within each class. The first element is 
1158   // a pointer to the current class, and the rest are pointers to the 
1159   // classes ancestors, ordered from the current class down by decreasing 
1160   // depth. We do not include java.lang.Object in the table of ancestors, 
1161   // since it is redundant.
1162         
1163   klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass));
1164   klass0 = klass;
1165   for (int index = 0; index < klass->depth; index++)
1166     {
1167       klass->ancestors[index] = klass0;
1168       klass0 = klass0->superclass;
1169     }
1170     
1171   if (java::lang::reflect::Modifier::isAbstract (klass->accflags))
1172     return;
1173   
1174   // Optimization: If class implements no interfaces, use a common
1175   // predefined interface table.
1176   if (!has_interfaces)
1177     {
1178       klass->idt = &null_idt;
1179       return;
1180     }
1181
1182   klass->idt = 
1183     (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1184     
1185   _Jv_ifaces ifaces;
1186
1187   ifaces.count = 0;
1188   ifaces.len = INITIAL_IFACES_LEN;
1189   ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
1190
1191   int itable_size = _Jv_GetInterfaces (klass, &ifaces);
1192
1193   if (ifaces.count > 0)
1194     {
1195       klass->idt->cls.itable = 
1196         (void **) _Jv_Malloc (itable_size * sizeof (void *));
1197       klass->idt->cls.itable_length = itable_size;
1198           
1199       jshort *itable_offsets = 
1200         (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
1201
1202       _Jv_GenerateITable (klass, &ifaces, itable_offsets);
1203
1204       jshort cls_iindex = 
1205         _Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count);
1206
1207       for (int i=0; i < ifaces.count; i++)
1208         {
1209           ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
1210             itable_offsets[i];
1211         }
1212
1213       klass->idt->cls.iindex = cls_iindex;          
1214
1215       _Jv_Free (ifaces.list);
1216       _Jv_Free (itable_offsets);
1217     }
1218   else 
1219     {
1220       klass->idt->cls.iindex = SHRT_MAX;
1221     }
1222 }
1223
1224 // Return index of item in list, or -1 if item is not present.
1225 inline jshort
1226 _Jv_IndexOf (void *item, void **list, jshort list_len)
1227 {
1228   for (int i=0; i < list_len; i++)
1229     {
1230       if (list[i] == item)
1231         return i;
1232     }
1233   return -1;
1234 }
1235
1236 // Find all unique interfaces directly or indirectly implemented by klass.
1237 // Returns the size of the interface dispatch table (itable) for klass, which 
1238 // is the number of unique interfaces plus the total number of methods that 
1239 // those interfaces declare. May extend ifaces if required.
1240 jshort
1241 _Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces)
1242 {
1243   jshort result = 0;
1244   
1245   for (int i=0; i < klass->interface_count; i++)
1246     {
1247       jclass iface = klass->interfaces[i];
1248
1249       /* Make sure interface is linked.  */
1250       _Jv_WaitForState(iface, JV_STATE_LINKED);
1251
1252       if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1)
1253         {
1254           if (ifaces->count + 1 >= ifaces->len)
1255             {
1256               /* Resize ifaces list */
1257               ifaces->len = ifaces->len * 2;
1258               ifaces->list = (jclass *) _Jv_Realloc (ifaces->list, 
1259                              ifaces->len * sizeof(jclass));
1260             }
1261           ifaces->list[ifaces->count] = iface;
1262           ifaces->count++;
1263
1264           result += _Jv_GetInterfaces (klass->interfaces[i], ifaces);
1265         }
1266     }
1267     
1268   if (klass->isInterface())
1269     {
1270       result += klass->method_count + 1;
1271     }
1272   else
1273     {
1274       if (klass->superclass)
1275         {
1276           result += _Jv_GetInterfaces (klass->superclass, ifaces);
1277         }
1278     }
1279   return result;
1280 }
1281
1282 // Fill out itable in klass, resolving method declarations in each ifaces.
1283 // itable_offsets is filled out with the position of each iface in itable,
1284 // such that itable[itable_offsets[n]] == ifaces.list[n].
1285 void
1286 _Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets)
1287 {
1288   void **itable = klass->idt->cls.itable;
1289   jshort itable_pos = 0;
1290
1291   for (int i=0; i < ifaces->count; i++)
1292     { 
1293       jclass iface = ifaces->list[i];
1294       itable_offsets[i] = itable_pos;
1295       itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos);
1296       
1297       /* Create interface dispatch table for iface */
1298       if (iface->idt == NULL)
1299         {
1300           iface->idt = 
1301             (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
1302
1303           // The first element of ioffsets is its length (itself included).
1304           jshort *ioffsets = 
1305             (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN * sizeof (jshort));
1306           ioffsets[0] = INITIAL_IOFFSETS_LEN;
1307           for (int i=1; i < INITIAL_IOFFSETS_LEN; i++)
1308             ioffsets[i] = -1;
1309
1310           iface->idt->iface.ioffsets = ioffsets;            
1311         }
1312     }
1313 }
1314
1315 // Format method name for use in error messages.
1316 jstring
1317 _Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
1318 {
1319   jstring r = JvNewStringUTF (klass->name->data);
1320   r = r->concat (JvNewStringUTF ("."));
1321   r = r->concat (JvNewStringUTF (name->data));
1322   return r;
1323 }
1324
1325 void 
1326 _Jv_ThrowNoSuchMethodError ()
1327 {
1328   throw new java::lang::NoSuchMethodError;
1329 }
1330
1331 // Each superinterface of a class (i.e. each interface that the class
1332 // directly or indirectly implements) has a corresponding "Partial
1333 // Interface Dispatch Table" whose size is (number of methods + 1) words.
1334 // The first word is a pointer to the interface (i.e. the java.lang.Class
1335 // instance for that interface).  The remaining words are pointers to the
1336 // actual methods that implement the methods declared in the interface,
1337 // in order of declaration.
1338 //
1339 // Append partial interface dispatch table for "iface" to "itable", at
1340 // position itable_pos.
1341 // Returns the offset at which the next partial ITable should be appended.
1342 jshort
1343 _Jv_AppendPartialITable (jclass klass, jclass iface, void **itable, 
1344                          jshort pos)
1345 {
1346   using namespace java::lang::reflect;
1347
1348   itable[pos++] = (void *) iface;
1349   _Jv_Method *meth;
1350   
1351   for (int j=0; j < iface->method_count; j++)
1352     {
1353       meth = NULL;
1354       for (jclass cl = klass; cl; cl = cl->getSuperclass())
1355         {
1356           meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
1357                                      iface->methods[j].signature);
1358                  
1359           if (meth)
1360             break;
1361         }
1362
1363       if (meth && (meth->name->data[0] == '<'))
1364         {
1365           // leave a placeholder in the itable for hidden init methods.
1366           itable[pos] = NULL;   
1367         }
1368       else if (meth)
1369         {
1370           if (Modifier::isStatic(meth->accflags))
1371             throw new java::lang::IncompatibleClassChangeError
1372               (_Jv_GetMethodString (klass, meth->name));
1373           if (Modifier::isAbstract(meth->accflags))
1374             throw new java::lang::AbstractMethodError
1375               (_Jv_GetMethodString (klass, meth->name));
1376           if (! Modifier::isPublic(meth->accflags))
1377             throw new java::lang::IllegalAccessError
1378               (_Jv_GetMethodString (klass, meth->name));
1379
1380           itable[pos] = meth->ncode;
1381         }
1382       else
1383         {
1384           // The method doesn't exist in klass. Binary compatibility rules
1385           // permit this, so we delay the error until runtime using a pointer
1386           // to a method which throws an exception.
1387           itable[pos] = (void *) _Jv_ThrowNoSuchMethodError;
1388         }
1389       pos++;
1390     }
1391     
1392   return pos;
1393 }
1394
1395 static _Jv_Mutex_t iindex_mutex;
1396 static bool iindex_mutex_initialized = false;
1397
1398 // We need to find the correct offset in the Class Interface Dispatch 
1399 // Table for a given interface. Once we have that, invoking an interface 
1400 // method just requires combining the Method's index in the interface 
1401 // (known at compile time) to get the correct method.  Doing a type test 
1402 // (cast or instanceof) is the same problem: Once we have a possible Partial 
1403 // Interface Dispatch Table, we just compare the first element to see if it 
1404 // matches the desired interface. So how can we find the correct offset?  
1405 // Our solution is to keep a vector of candiate offsets in each interface 
1406 // (idt->iface.ioffsets), and in each class we have an index 
1407 // (idt->cls.iindex) used to select the correct offset from ioffsets.
1408 //
1409 // Calculate and return iindex for a new class. 
1410 // ifaces is a vector of num interfaces that the class implements.
1411 // offsets[j] is the offset in the interface dispatch table for the
1412 // interface corresponding to ifaces[j].
1413 // May extend the interface ioffsets if required.
1414 jshort
1415 _Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
1416 {
1417   int i;
1418   int j;
1419   
1420   // Acquire a global lock to prevent itable corruption in case of multiple 
1421   // classes that implement an intersecting set of interfaces being linked
1422   // simultaneously. We can assume that the mutex will be initialized
1423   // single-threaded.
1424   if (! iindex_mutex_initialized)
1425     {
1426       _Jv_MutexInit (&iindex_mutex);
1427       iindex_mutex_initialized = true;
1428     }
1429   
1430   _Jv_MutexLock (&iindex_mutex);
1431   
1432   for (i=1;; i++)  /* each potential position in ioffsets */
1433     {
1434       for (j=0;; j++)  /* each iface */
1435         {
1436           if (j >= num)
1437             goto found;
1438           if (i >= ifaces[j]->idt->iface.ioffsets[0])
1439             continue;
1440           int ioffset = ifaces[j]->idt->iface.ioffsets[i];
1441           /* We can potentially share this position with another class. */
1442           if (ioffset >= 0 && ioffset != offsets[j])
1443             break; /* Nope. Try next i. */        
1444         }
1445     }
1446   found:
1447   for (j = 0; j < num; j++)
1448     {
1449       int len = ifaces[j]->idt->iface.ioffsets[0];
1450       if (i >= len) 
1451         {
1452           /* Resize ioffsets. */
1453           int newlen = 2 * len;
1454           if (i >= newlen)
1455             newlen = i + 3;
1456           jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
1457           jshort *new_ioffsets = (jshort *) _Jv_Realloc (old_ioffsets, 
1458                                           newlen * sizeof(jshort));       
1459           new_ioffsets[0] = newlen;
1460
1461           while (len < newlen)
1462             new_ioffsets[len++] = -1;
1463           
1464           ifaces[j]->idt->iface.ioffsets = new_ioffsets;
1465         }
1466       ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
1467     }
1468
1469   _Jv_MutexUnlock (&iindex_mutex);
1470
1471   return i;
1472 }
1473
1474 // Only used by serialization
1475 java::lang::reflect::Field *
1476 java::lang::Class::getPrivateField (jstring name)
1477 {
1478   int hash = name->hashCode ();
1479
1480   java::lang::reflect::Field* rfield;
1481   for (int i = 0;  i < field_count;  i++)
1482     {
1483       _Jv_Field *field = &fields[i];
1484       if (! _Jv_equal (field->name, name, hash))
1485         continue;
1486       rfield = new java::lang::reflect::Field ();
1487       rfield->offset = (char*) field - (char*) fields;
1488       rfield->declaringClass = this;
1489       rfield->name = name;
1490       return rfield;
1491     }
1492   jclass superclass = getSuperclass();
1493   if (superclass == NULL)
1494     return NULL;
1495   rfield = superclass->getPrivateField(name);
1496   for (int i = 0; i < interface_count && rfield == NULL; ++i)
1497     rfield = interfaces[i]->getPrivateField (name);
1498   return rfield;
1499 }
1500
1501 // Only used by serialization
1502 java::lang::reflect::Method *
1503 java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
1504 {
1505   jstring partial_sig = getSignature (param_types, false);
1506   jint p_len = partial_sig->length();
1507   _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
1508   for (Class *klass = this; klass; klass = klass->getSuperclass())
1509     {
1510       int i = klass->isPrimitive () ? 0 : klass->method_count;
1511       while (--i >= 0)
1512         {
1513           if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
1514               && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
1515             {
1516               // Found it.
1517               using namespace java::lang::reflect;
1518
1519               Method *rmethod = new Method ();
1520               rmethod->offset = ((char *) (&klass->methods[i])
1521                                  - (char *) klass->methods);
1522               rmethod->declaringClass = klass;
1523               return rmethod;
1524             }
1525         }
1526     }
1527   throw new java::lang::NoSuchMethodException (name);
1528 }
1529
1530 // Private accessor method for Java code to retrieve the protection domain.
1531 java::security::ProtectionDomain *
1532 java::lang::Class::getProtectionDomain0 ()
1533 {
1534   return protectionDomain;
1535 }
1536
1537 JArray<jobject> *
1538 java::lang::Class::getSigners()
1539 {
1540   return signers;
1541 }
1542
1543 void
1544 java::lang::Class::setSigners(JArray<jobject> *s)
1545 {
1546   signers = s;
1547 }
1548
1549 // Functions for indirect dispatch (symbolic virtual binding) support.
1550
1551 // There are two tables, atable and otable.  atable is an array of
1552 // addresses, and otable is an array of offsets, and these are used
1553 // for static and virtual members respectively.
1554
1555 // {a,o}table_syms is an array of _Jv_MethodSymbols.  Each such symbol
1556 // is a tuple of {classname, member name, signature}.
1557 // _Jv_LinkSymbolTable() scans these two arrays and fills in the
1558 // corresponding atable and otable with the addresses of static
1559 // members and the offsets of virtual members.
1560
1561 // The offset (in bytes) for each resolved method or field is placed
1562 // at the corresponding position in the virtual method offset table
1563 // (klass->otable). 
1564
1565 // The same otable and atable may be shared by many classes.
1566
1567 void
1568 _Jv_LinkSymbolTable(jclass klass)
1569 {
1570   //// FIXME: Need to lock the tables ////
1571   
1572   int index = 0;
1573   _Jv_MethodSymbol sym;
1574   if (klass->otable == NULL
1575       || klass->otable->state != 0)
1576     goto atable;
1577    
1578   klass->otable->state = 1;
1579
1580   for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
1581     {
1582       jclass target_class = _Jv_FindClass (sym.class_name, NULL);
1583       _Jv_Method *meth = NULL;            
1584
1585       const _Jv_Utf8Const *signature = sym.signature;
1586
1587       // FIXME: This should be special index for ThrowNoSuchMethod().
1588       klass->otable->offsets[index] = -1;
1589       
1590       if (target_class == NULL)
1591         continue;
1592
1593       if (target_class->isInterface())
1594         {
1595           // FIXME: This does not yet fully conform to binary compatibility
1596           // rules. It will break if a declaration is moved into a 
1597           // superinterface.
1598           for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1599             {
1600               for (int i=0; i < cls->method_count; i++)
1601                 {
1602                   meth = &cls->methods[i];
1603                   if (_Jv_equalUtf8Consts (sym.name, meth->name)
1604                       && _Jv_equalUtf8Consts (signature, meth->signature))
1605                     {
1606                       klass->otable->offsets[index] = i + 1;
1607                       goto found;
1608                     }
1609                 }
1610             
1611             }
1612         found:
1613           continue;
1614         }
1615
1616       // We're looking for a field or a method, and we can tell
1617       // which is needed by looking at the signature.
1618       if (signature->length >= 2
1619           && signature->data[0] == '(')
1620         {
1621           // If the target class does not have a vtable_method_count yet, 
1622           // then we can't tell the offsets for its methods, so we must lay 
1623           // it out now.
1624           if (target_class->vtable_method_count == -1)
1625             {
1626               JvSynchronize sync (target_class);
1627               _Jv_LayoutVTableMethods (target_class);
1628             }
1629                 
1630           meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
1631                                           sym.signature);
1632                 
1633           if (meth != NULL)
1634             {
1635               klass->otable->offsets[index] = 
1636                 _Jv_VTable::idx_to_offset (meth->index);              
1637             }
1638
1639           continue;
1640         }
1641
1642       // try fields
1643       {
1644         _Jv_Field *the_field = NULL;
1645
1646         for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1647           {
1648             for (int i = 0; i < cls->field_count; i++)
1649               {
1650                 _Jv_Field *field = &cls->fields[i];
1651                 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1652                   continue;
1653
1654                 // FIXME: What access checks should we perform here?
1655 //              if (_Jv_CheckAccess (klass, cls, field->flags))
1656 //                {
1657
1658                 if (!field->isResolved ())
1659                   _Jv_ResolveField (field, cls->loader);
1660
1661 //              if (field_type != 0 && field->type != field_type)
1662 //                throw new java::lang::LinkageError
1663 //                  (JvNewStringLatin1 
1664 //                   ("field type mismatch with different loaders"));
1665
1666                 the_field = field;
1667                 goto end_of_field_search;
1668               }
1669           }
1670       end_of_field_search:
1671         if (the_field != NULL)
1672           {
1673             if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1674               {       
1675                 throw new java::lang::IncompatibleClassChangeError;
1676               }
1677             else
1678               {
1679                 klass->otable->offsets[index] = the_field->u.boffset;
1680               }
1681           }
1682         else
1683           {
1684             throw new java::lang::NoSuchFieldError
1685               (_Jv_NewStringUtf8Const (sym.name));
1686           }
1687       }
1688     }
1689
1690  atable:
1691   if (klass->atable == NULL
1692       || klass->atable->state != 0)
1693     return;
1694
1695   klass->atable->state = 1;
1696
1697   for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
1698     {
1699       jclass target_class = _Jv_FindClass (sym.class_name, NULL);
1700       _Jv_Method *meth = NULL;            
1701       const _Jv_Utf8Const *signature = sym.signature;
1702
1703       // ??? Setting this pointer to null will at least get us a
1704       // NullPointerException
1705       klass->atable->addresses[index] = NULL;
1706       
1707       if (target_class == NULL)
1708         continue;
1709       
1710       // We're looking for a static field or a static method, and we
1711       // can tell which is needed by looking at the signature.
1712       if (signature->length >= 2
1713           && signature->data[0] == '(')
1714         {
1715           // If the target class does not have a vtable_method_count yet, 
1716           // then we can't tell the offsets for its methods, so we must lay 
1717           // it out now.
1718           if (target_class->vtable_method_count == -1)
1719             {
1720               JvSynchronize sync (target_class);
1721               _Jv_LayoutVTableMethods (target_class);
1722             }
1723           
1724           meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
1725                                           sym.signature);
1726           
1727           if (meth != NULL)
1728             klass->atable->addresses[index] = meth->ncode;
1729           else
1730             klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
1731
1732           continue;
1733         }
1734
1735       // try fields
1736       {
1737         _Jv_Field *the_field = NULL;
1738
1739         for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
1740           {
1741             for (int i = 0; i < cls->field_count; i++)
1742               {
1743                 _Jv_Field *field = &cls->fields[i];
1744                 if (! _Jv_equalUtf8Consts (field->name, sym.name))
1745                   continue;
1746
1747                 // FIXME: What access checks should we perform here?
1748 //              if (_Jv_CheckAccess (klass, cls, field->flags))
1749 //                {
1750
1751                 if (!field->isResolved ())
1752                   _Jv_ResolveField (field, cls->loader);
1753                 
1754 //              if (field_type != 0 && field->type != field_type)
1755 //                throw new java::lang::LinkageError
1756 //                  (JvNewStringLatin1 
1757 //                   ("field type mismatch with different loaders"));
1758
1759                 the_field = field;
1760                 goto end_of_static_field_search;
1761               }
1762           }
1763       end_of_static_field_search:
1764         if (the_field != NULL)
1765           {
1766             if (the_field->flags & 0x0008 /* Modifier::STATIC */)
1767               {       
1768                 klass->atable->addresses[index] = the_field->u.addr;
1769               }
1770             else
1771               {
1772                 throw new java::lang::IncompatibleClassChangeError;
1773               }
1774           }
1775         else
1776           {
1777             throw new java::lang::NoSuchFieldError
1778               (_Jv_NewStringUtf8Const (sym.name));
1779           }
1780       }
1781     }
1782 }
1783
1784 // Returns true if METH should get an entry in a VTable.
1785 static jboolean
1786 isVirtualMethod (_Jv_Method *meth)
1787 {
1788   using namespace java::lang::reflect;
1789   return (((meth->accflags & (Modifier::STATIC | Modifier::PRIVATE)) == 0)
1790           && meth->name->data[0] != '<');
1791 }
1792
1793 // This is put in empty vtable slots.
1794 static void
1795 _Jv_abstractMethodError (void)
1796 {
1797   throw new java::lang::AbstractMethodError();
1798 }
1799
1800 // Prepare virtual method declarations in KLASS, and any superclasses as 
1801 // required, by determining their vtable index, setting method->index, and
1802 // finally setting the class's vtable_method_count. Must be called with the
1803 // lock for KLASS held.
1804 void
1805 _Jv_LayoutVTableMethods (jclass klass)
1806 {
1807   if (klass->vtable != NULL || klass->isInterface() 
1808       || klass->vtable_method_count != -1)
1809     return;
1810
1811   jclass superclass = klass->superclass;
1812
1813   if (superclass != NULL && superclass->vtable_method_count == -1)
1814     {
1815       JvSynchronize sync (superclass);
1816       _Jv_LayoutVTableMethods (superclass);
1817     }
1818
1819   int index = (superclass == NULL ? 0 : superclass->vtable_method_count);
1820
1821   for (int i = 0; i < klass->method_count; ++i)
1822     {
1823       _Jv_Method *meth = &klass->methods[i];
1824       _Jv_Method *super_meth = NULL;
1825
1826       if (! isVirtualMethod (meth))
1827         continue;
1828
1829       if (superclass != NULL)
1830         {
1831           super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, 
1832                                                  meth->signature);
1833         }
1834
1835       if (super_meth)
1836         meth->index = super_meth->index;
1837       else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL)
1838                && ! (klass->accflags & java::lang::reflect::Modifier::FINAL))
1839         meth->index = index++;
1840     }
1841
1842   klass->vtable_method_count = index;
1843 }
1844
1845 // Set entries in VTABLE for virtual methods declared in KLASS. If
1846 // KLASS has an immediate abstract parent, recursively do its methods
1847 // first.  FLAGS is used to determine which slots we've actually set.
1848 void
1849 _Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
1850 {
1851   using namespace java::lang::reflect;
1852
1853   jclass superclass = klass->getSuperclass();
1854
1855   if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT))
1856     _Jv_SetVTableEntries (superclass, vtable, flags);
1857
1858   for (int i = klass->method_count - 1; i >= 0; i--)
1859     {
1860       _Jv_Method *meth = &klass->methods[i];
1861       if (meth->index == (_Jv_ushort) -1)
1862         continue;
1863       if ((meth->accflags & Modifier::ABSTRACT))
1864         {
1865           vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
1866           flags[meth->index] = false;
1867         }
1868       else
1869         {
1870           vtable->set_method(meth->index, meth->ncode);
1871           flags[meth->index] = true;
1872         }
1873     }
1874 }
1875
1876 // Allocate and lay out the virtual method table for KLASS. This will also
1877 // cause vtables to be generated for any non-abstract superclasses, and
1878 // virtual method layout to occur for any abstract superclasses. Must be
1879 // called with monitor lock for KLASS held.
1880 void
1881 _Jv_MakeVTable (jclass klass)
1882 {
1883   using namespace java::lang::reflect;  
1884
1885   if (klass->vtable != NULL || klass->isInterface() 
1886       || (klass->accflags & Modifier::ABSTRACT))
1887     return;
1888
1889   //  out before we can create a vtable. 
1890   if (klass->vtable_method_count == -1)
1891     _Jv_LayoutVTableMethods (klass);
1892
1893   // Allocate the new vtable.
1894   _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count);
1895   klass->vtable = vtable;
1896
1897   jboolean flags[klass->vtable_method_count];
1898   for (int i = 0; i < klass->vtable_method_count; ++i)
1899     flags[i] = false;
1900
1901   // Copy the vtable of the closest non-abstract superclass.
1902   jclass superclass = klass->superclass;
1903   if (superclass != NULL)
1904     {
1905       while ((superclass->accflags & Modifier::ABSTRACT) != 0)
1906         superclass = superclass->superclass;
1907
1908       if (superclass->vtable == NULL)
1909         {
1910           JvSynchronize sync (superclass);
1911           _Jv_MakeVTable (superclass);
1912         }
1913
1914       for (int i = 0; i < superclass->vtable_method_count; ++i)
1915         {
1916           vtable->set_method (i, superclass->vtable->get_method (i));
1917           flags[i] = true;
1918         }
1919     }
1920
1921   // Set the class pointer and GC descriptor.
1922   vtable->clas = klass;
1923   vtable->gc_descr = _Jv_BuildGCDescr (klass);
1924
1925   // For each virtual declared in klass and any immediate abstract 
1926   // superclasses, set new vtable entry or override an old one.
1927   _Jv_SetVTableEntries (klass, vtable, flags);
1928
1929   // It is an error to have an abstract method in a concrete class.
1930   if (! (klass->accflags & Modifier::ABSTRACT))
1931     {
1932       for (int i = 0; i < klass->vtable_method_count; ++i)
1933         if (! flags[i])
1934           {
1935             using namespace java::lang;
1936             while (klass != NULL)
1937               {
1938                 for (int j = 0; j < klass->method_count; ++j)
1939                   {
1940                     if (klass->methods[i].index == i)
1941                       {
1942                         StringBuffer *buf = new StringBuffer ();
1943                         buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name));
1944                         buf->append ((jchar) ' ');
1945                         buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature));
1946                         throw new AbstractMethodError (buf->toString ());
1947                       }
1948                   }
1949                 klass = klass->getSuperclass ();
1950               }
1951             // Couldn't find the name, which is weird.
1952             // But we still must throw the error.
1953             throw new AbstractMethodError ();
1954           }
1955     }
1956 }