OSDN Git Service

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