OSDN Git Service

4c0f411a87764bb5a6e3ba48ebcf3d1c80921baf
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natClassLoader.cc
1 // natClassLoader.cc - Implementation of java.lang.ClassLoader native methods.
2
3 /* Copyright (C) 1999  Cygnus Solutions
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 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
13 #include <config.h>
14
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include <cni.h>
19 #include <jvm.h>
20 #include <java/lang/Character.h>
21 #include <java/lang/Thread.h>
22 #include <java/lang/ClassLoader.h>
23 #include <gnu/gcj/runtime/VMClassLoader.h>
24 #include <java/lang/InternalError.h>
25 #include <java/lang/IllegalAccessError.h>
26 #include <java/lang/LinkageError.h>
27 #include <java/lang/ClassFormatError.h>
28 #include <java/lang/NoClassDefFoundError.h>
29 #include <java/lang/ClassNotFoundException.h>
30 #include <java/lang/ClassCircularityError.h>
31 #include <java/lang/IncompatibleClassChangeError.h>
32 #include <java/lang/reflect/Modifier.h>
33
34 #include <java-interp.h>
35
36 #define CloneableClass _CL_Q34java4lang9Cloneable
37 extern java::lang::Class CloneableClass;
38 #define ObjectClass _CL_Q34java4lang6Object
39 extern java::lang::Class ObjectClass;
40 #define ClassClass _CL_Q34java4lang5Class
41 extern java::lang::Class ClassClass;
42 #define VMClassLoaderClass _CL_Q34java4lang17VMClassLoader
43 extern java::lang::Class VMClassLoader;
44 #define ClassLoaderClass _CL_Q34java4lang11ClassLoader
45 extern java::lang::Class ClassLoaderClass;
46
47 /////////// java.lang.ClassLoader native methods ////////////
48
49 #ifdef INTERPRETER
50 gnu::gcj::runtime::VMClassLoader *redirect = 0;
51 #endif
52
53 java::lang::ClassLoader*
54 java::lang::ClassLoader::getVMClassLoader0 ()
55 {
56 #ifdef INTERPRETER
57     if (redirect == 0)
58         redirect = new gnu::gcj::runtime::VMClassLoader;
59     return redirect;
60 #else
61     return 0;
62 #endif
63 }
64
65 void
66 java::lang::ClassLoader::defineClass2 (jclass klass, jbyteArray data,
67                                        jint offset, jint length)
68 {
69 #ifdef INTERPRETER
70   _Jv_DefineClass (klass, data, offset, length);
71 #endif
72 }
73
74 java::lang::Class *
75 java::lang::ClassLoader::defineClass0 (jstring name,
76                                        jbyteArray data, 
77                                        jint offset,
78                                        jint length)
79 {
80 #ifdef INTERPRETER
81   jclass klass;
82   klass = (jclass) JvAllocObject (&ClassClass, sizeof (_Jv_InterpClass));
83
84   // synchronize on the class, so that it is not
85   // attempted initialized until we're done loading.
86   _Jv_MonitorEnter (klass);
87
88   // record which is the defining loader
89   klass->loader = this;
90
91   // register that we are the initiating loader...
92   if (name != 0)
93     {
94       _Jv_Utf8Const *   name2 = _Jv_makeUtf8Const (name);
95
96       _Jv_VerifyClassName (name2);
97
98       klass->name = name2;
99     }
100
101   // this will do the magic.  loadInto also operates
102   // as an exception trampoline for now...
103   Throwable *ex = defineClass1 (klass, data, offset, length);
104     
105   if (ex)  // we failed to load it
106     {
107       klass->state = JV_STATE_ERROR;
108       klass->notifyAll ();
109
110       _Jv_UnregisterClass (klass);
111
112       _Jv_MonitorExit (klass);
113           
114       // FIXME: Here we may want to test that EX does
115       // indeed represent a valid exception.  That is,
116       // anything but ClassNotFoundException, 
117       // or some kind of Error.
118           
119       JvThrow (ex);
120     }
121     
122   // if everything proceeded sucessfully, we're loaded.
123   JvAssert (klass->state == JV_STATE_LOADED);
124
125   // if an exception is generated, this is initially missed.
126   // however, we come back here in handleException0 below...
127   _Jv_MonitorExit (klass);
128
129   return klass;
130
131 #else // INTERPRETER
132
133   return 0;
134 #endif
135 }
136
137 void
138 _Jv_WaitForState (jclass klass, int state)
139 {
140   if (klass->state >= state)
141     return;
142   
143   _Jv_MonitorEnter (klass) ;
144
145   if (state == JV_STATE_LINKED)
146     {
147       _Jv_MonitorExit (klass);
148       _Jv_PrepareCompiledClass (klass);
149       return;
150     }
151         
152   java::lang::Thread *self = java::lang::Thread::currentThread();
153
154   // this is similar to the strategy for class initialization.
155   // if we already hold the lock, just leave.
156   while (klass->state <= state
157          && klass->thread 
158          && klass->thread != self)
159     klass->wait ();
160
161   _Jv_MonitorExit (klass);
162
163   if (klass->state == JV_STATE_ERROR)
164     {
165       _Jv_Throw (new java::lang::LinkageError ());
166     }
167 }
168
169 // Finish linking a class.  Only called from ClassLoader::resolveClass.
170 void
171 java::lang::ClassLoader::linkClass0 (java::lang::Class *klass)
172 {
173   if (klass->state >= JV_STATE_LINKED)
174     return;
175
176 #ifdef INTERPRETER
177   if (_Jv_IsInterpretedClass (klass))
178     {
179       _Jv_PrepareClass (klass);
180     }
181 #endif
182
183   _Jv_PrepareCompiledClass (klass);
184 }
185
186 void
187 java::lang::ClassLoader::markClassErrorState0 (java::lang::Class *klass)
188 {
189   klass->state = JV_STATE_ERROR;
190   klass->notifyAll ();
191 }
192
193
194 /** this is the only native method in VMClassLoader, so 
195     we define it here. */
196 jclass
197 gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
198 {
199   return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), 0);
200 }
201
202 jclass
203 java::lang::ClassLoader::findLoadedClass (jstring name)
204 {
205   return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), this);
206 }
207
208 static const int PUBLIC       = 0x001;
209 static const int PRIVATE      = 0x002;
210 static const int PROTECTED    = 0x004;
211 static const int STATIC       = 0x008;
212 static const int FINAL        = 0x010;
213 static const int SYNCHRONIZED = 0x020;
214 static const int VOLATILE     = 0x040;
215 static const int TRANSIENT    = 0x080;
216 static const int NATIVE       = 0x100;
217 static const int INTERFACE    = 0x200;
218 static const int ABSTRACT     = 0x400;
219 static const int ALL_FLAGS    = 0x7FF; 
220
221
222 /** This function does class-preparation for compiled classes.  
223     NOTE: It contains replicated functionality from
224     _Jv_ResolvePoolEntry, and this is intentional, since that function
225     lives in resolve.cc which is entirely conditionally compiled.
226  */
227 void
228 _Jv_PrepareCompiledClass(jclass klass)
229 {
230   if (klass->state >= JV_STATE_LINKED)
231     return;
232
233   // short-circuit, so that mutually dependent classes are ok
234   klass->state = JV_STATE_LINKED;
235
236   _Jv_Constants *pool = &klass->constants;
237   for (int index = 1; index < pool->size; ++index)
238     {
239       if (pool->tags[index] == JV_CONSTANT_Class)
240         {
241           _Jv_Utf8Const *name = pool->data[index].utf8;
242           
243           jclass found;
244           if (name->data[0] == '[')
245             found = _Jv_FindClassFromSignature (&name->data[0],
246                                                 klass->loader);
247           else
248             found = _Jv_FindClass (name, klass->loader);
249                 
250           if (! found)
251             {
252               jstring str = _Jv_NewStringUTF (name->data);
253               JvThrow (new java::lang::ClassNotFoundException (str));
254             }
255
256           pool->data[index].clazz = found;
257           pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
258         }
259             
260       else if (pool->tags[index] == JV_CONSTANT_String)
261         {
262           jstring str;
263           str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
264           pool->data[index].o = str;
265           pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
266         }
267     }
268
269   klass->notifyAll ();
270 }
271
272
273 //
274 //  A single class can have many "initiating" class loaders,
275 //  and a single "defining" class loader.  The Defining
276 //  class loader is what is returned from Class.getClassLoader()
277 //  and is used when loading dependent classes during resolution.
278 //  The set of initiating class loaders are used to ensure
279 //  safety of linking, and is maintained in the hash table
280 //  "initiated_classes".  A defining classloader is by definition also
281 //  initiating, so we only store classes in this table, if they have more
282 //  than one class loader associated.
283 //
284
285
286 // Size of local hash table.
287 #define HASH_LEN 1013
288
289 // Hash function for Utf8Consts.
290 #define HASH_UTF(Utf) (((Utf)->hash) % HASH_LEN)
291
292 struct _Jv_LoaderInfo {
293     _Jv_LoaderInfo          *next;
294     java::lang::Class       *klass;
295     java::lang::ClassLoader *loader;
296 };
297
298 _Jv_LoaderInfo *initiated_classes[HASH_LEN];
299 jclass loaded_classes[HASH_LEN];
300
301 jclass
302 _Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
303 {
304   _Jv_MonitorEnter (&ClassClass);
305   jint hash = HASH_UTF (name);
306
307   // first, if LOADER is a defining loader, then it is also initiating
308   jclass klass;
309   for (klass = loaded_classes[hash]; klass; klass = klass->next)
310     {
311       if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
312         break;
313     }
314
315   // otherwise, it may be that the class in question was defined
316   // by some other loader, but that the loading was initiated by 
317   // the loader in question.
318   if (!klass)
319     {
320       _Jv_LoaderInfo *info;
321       for (info = initiated_classes[hash]; info; info = info->next)
322         {
323           if (loader == info->loader
324               && _Jv_equalUtf8Consts (name, info->klass->name))
325             {
326               klass = info->klass;
327               break;
328             }
329         }
330     }
331
332   _Jv_MonitorExit (&ClassClass);
333
334   return klass;
335 }
336
337 void
338 _Jv_UnregisterClass (jclass the_class)
339 {
340   _Jv_MonitorEnter (&ClassClass);
341   jint hash = HASH_UTF(the_class->name);
342
343   jclass *klass = &(loaded_classes[hash]);
344   for ( ; *klass; klass = &((*klass)->next))
345     {
346       if (*klass == the_class)
347         {
348           *klass = (*klass)->next;
349           break;
350         }
351     }
352
353   _Jv_LoaderInfo **info = &(initiated_classes[hash]);
354   for ( ; *info; info = &((*info)->next))
355     {
356       while ((*info)->klass == the_class)
357         {
358           *info = (*info)->next;
359         }
360     }
361
362   _Jv_MonitorExit (&ClassClass);
363 }
364
365 void
366 _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
367 {
368   _Jv_LoaderInfo *info = new _Jv_LoaderInfo; // non-gc alloc!
369   jint hash = HASH_UTF(klass->name);
370
371   _Jv_MonitorEnter (&ClassClass);
372   info->loader = loader;
373   info->klass  = klass;
374   info->next   = initiated_classes[hash];
375   initiated_classes[hash] = info;
376   _Jv_MonitorExit (&ClassClass);
377   
378 }
379
380 // This function is called many times during startup, before main() is
381 // run.  We do our runtime initialization here the very first time we
382 // are called.  At that point in time we know for certain we are
383 // running single-threaded, so we don't need to lock when modifying
384 // `init'.  CLASSES is NULL-terminated.
385 void
386 _Jv_RegisterClasses (jclass *classes)
387 {
388   static bool init = false;
389
390   if (! init)
391     {
392       init = true;
393       _Jv_InitThreads ();
394       _Jv_InitGC ();
395       _Jv_InitializeSyncMutex ();
396     }
397
398   JvSynchronize sync (&ClassClass);
399   for (; *classes; ++classes)
400     {
401       jclass klass = *classes;
402       jint hash = HASH_UTF (klass->name);
403       klass->next = loaded_classes[hash];
404       loaded_classes[hash] = klass;
405
406       // registering a compiled class causes
407       // it to be immediately "prepared".  
408       if (klass->state == JV_STATE_NOTHING)
409         klass->state = JV_STATE_COMPILED;
410     }
411 }
412
413 void
414 _Jv_RegisterClass (jclass klass)
415 {
416   jclass classes[2];
417   classes[0] = klass;
418   classes[1] = NULL;
419   _Jv_RegisterClasses (classes);
420 }
421
422 #if 0
423 // NOTE: this one is out of date with the new loader stuff...
424 jclass
425 _Jv_FindClassInCache (jstring name, java::lang::ClassLoader *loader)
426 {
427   JvSynchronize sync (&ClassClass);
428   jint hash = name->hashCode();
429   jclass klass = loaded_classes[(_Jv_ushort) hash % HASH_LEN];
430   for ( ; klass; klass = klass->next)
431     {
432       if (loader == klass->loader
433           && _Jv_equal (klass->name, name, hash))
434         break;
435     }
436   _Jv_MonitorExit (&ClassClass);
437   return klass;
438 }
439 #endif
440
441 jclass _Jv_FindClass (_Jv_Utf8Const *name,
442                       java::lang::ClassLoader *loader)
443 {
444   jclass klass = _Jv_FindClassInCache (name, loader);
445
446 #ifdef INTERPRETER
447   if (! klass)
448     {
449       jstring sname = _Jv_NewStringUTF (name->data);
450
451       if (loader)
452         {
453           // Load using a user-defined loader, jvmspec 5.3.2
454           klass = loader->loadClass(sname, false);
455
456           // if "loader" delegateted the loadClass operation
457           // to another loader, register explicitly
458           // that he is also an initiating loader of the
459           // given class.         
460
461           if (klass && (klass->getClassLoader () != loader))
462             _Jv_RegisterInitiatingLoader (klass, 0);
463         }
464       else 
465         {
466           if (redirect == NULL)
467             {
468               _Jv_InitClass (&ClassLoaderClass);
469               java::lang::ClassLoader::getSystemClassLoader ();
470             }
471
472           // Load using the bootstrap loader jmspec 5.3.1
473           klass = redirect -> loadClass (sname, false); 
474
475           // register that we're an initiating loader
476           if (klass)
477             {
478               _Jv_RegisterInitiatingLoader (klass, 0);
479             }
480         }
481     }
482   else
483     {
484       // we need classes to be in the hash while
485       // we're loading, so that they can refer to themselves. 
486       _Jv_WaitForState (klass, JV_STATE_LOADED);
487     }
488 #endif
489
490   return klass;
491 }
492
493 #if 0
494 // NOTE: this one is out of date with the new class loader stuff...
495 jclass
496 _Jv_FindClass (jstring name, java::lang::ClassLoader *loader)
497 {
498   jclass klass = _Jv_FindClassInCache (name, loader);
499   if (! klass)
500     {
501       if (loader)
502         {
503           klass = loader->loadClass(name);
504         }
505       else
506         {
507           // jmspec 5.3.1.2
508           
509           // delegate to the system loader
510           klass = java::lang::ClassLoader::system.loadClass (sname);
511           
512           // register that we're an initiating loader
513           if (klass)
514             _Jv_RegisterInitiatingLoader (klass, 0);
515         }
516     }
517   else
518     {
519       _Jv_WaitForState (klass, JV_STATE_LOADED);
520     }
521   
522   return klass;
523 }
524 #endif
525
526 jclass
527 _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
528               java::lang::ClassLoader *loader)
529 {
530   jclass ret = (jclass) JvAllocObject (&ClassClass);
531
532   ret->next = NULL;
533   ret->name = name;
534   ret->accflags = 0;
535   ret->superclass = superclass;
536   ret->constants.size = 0;
537   ret->constants.tags = NULL;
538   ret->constants.data = NULL;
539   ret->methods = NULL;
540   ret->method_count = 0;
541   ret->vtable_method_count = 0;
542   ret->fields = NULL;
543   ret->size_in_bytes = 0;
544   ret->field_count = 0;
545   ret->static_field_count = 0;
546   ret->vtable = NULL;
547   ret->interfaces = NULL;
548   ret->loader = loader;
549   ret->interface_count = 0;
550   ret->state = JV_STATE_NOTHING;
551   ret->thread = NULL;
552
553   _Jv_RegisterClass (ret);
554
555   return ret;
556 }
557
558 jclass
559 _Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader)
560 {
561   _Jv_Utf8Const *array_name;
562   int len;
563   if (element->isPrimitive())
564     {
565       // For primitive types the array is cached in the class.
566       jclass ret = (jclass) element->methods;
567       if (ret)
568         return ret;
569       len = 3;
570     }
571   else
572     len = element->name->length + 5;
573
574   {
575     char signature[len];
576     int index = 0;
577     signature[index++] = '[';
578     // Compute name of array class to see if we've already cached it.
579     if (element->isPrimitive())
580       {
581         signature[index++] = (char) element->method_count;
582       }
583     else
584       {
585         size_t length = element->name->length;
586         const char *const name = element->name->data;
587         if (name[0] != '[')
588           signature[index++] = 'L';
589         memcpy (&signature[index], name, length);
590         index += length;
591         if (name[0] != '[')
592           signature[index++] = ';';
593       }      
594     array_name = _Jv_makeUtf8Const (signature, index);
595   }
596
597   jclass array_class = _Jv_FindClassInCache (array_name, element->loader);
598
599   if (! array_class)
600     {
601       // Create new array class.
602       array_class = _Jv_NewClass (array_name, &ObjectClass, element->loader);
603
604       // Note that `vtable_method_count' doesn't include the initial
605       // NULL slot.
606       int dm_count = ObjectClass.vtable_method_count + 1;
607
608       // Create a new vtable by copying Object's vtable (except the
609       // class pointer, of course).  Note that we allocate this as
610       // unscanned memory -- the vtables are handled specially by the
611       // GC.
612       int size = (sizeof (_Jv_VTable) +
613                   ((dm_count - 1) * sizeof (void *)));
614       _Jv_VTable *vtable = (_Jv_VTable *) _Jv_AllocBytes (size);
615       vtable->clas = array_class;
616       memcpy (vtable->method, ObjectClass.vtable->method,
617               dm_count * sizeof (void *));
618       array_class->vtable = vtable;
619       array_class->vtable_method_count = ObjectClass.vtable_method_count;
620
621       // Stash the pointer to the element type.
622       array_class->methods = (_Jv_Method *) element;
623
624       // Register our interfaces.
625       // FIXME: for JDK 1.2 we need Serializable.
626       static jclass interfaces[] = { &CloneableClass };
627       array_class->interfaces = interfaces;
628       array_class->interface_count = 1;
629
630       // as per vmspec 5.3.3.2
631       array_class->accflags = element->accflags;
632
633       // FIXME: initialize other Class instance variables,
634       // e.g. `fields'.
635
636       // say this class is initialized and ready to go!
637       array_class->state = JV_STATE_DONE;
638
639       // vmspec, section 5.3.3 describes this
640       if (element->loader != loader)
641         _Jv_RegisterInitiatingLoader (array_class, loader);
642     }
643
644   // For primitive types, point back at this array.
645   if (element->isPrimitive())
646     element->methods = (_Jv_Method *) array_class;
647
648   return array_class;
649 }
650
651