OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [natClassLoader.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
// natClassLoader.cc - Implementation of java.lang.ClassLoader native methods.
2
 
3
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  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
/* Author: Kresten Krab Thorup <krab@gnu.org>  */
12
 
13
#include <config.h>
14
 
15
#include <stdlib.h>
16
#include <stdio.h>
17
#include <string.h>
18
 
19
#include <gcj/cni.h>
20
#include <jvm.h>
21
#include <execution.h>
22
 
23
#include <java-threads.h>
24
#include <java-interp.h>
25
 
26
#include <java/lang/Character.h>
27
#include <java/lang/Thread.h>
28
#include <java/lang/ClassLoader.h>
29
#include <java/lang/InternalError.h>
30
#include <java/lang/IllegalAccessError.h>
31
#include <java/lang/LinkageError.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/ClassFormatError.h>
37
#include <java/lang/VirtualMachineError.h>
38
#include <java/lang/VMClassLoader.h>
39
#include <java/lang/reflect/Modifier.h>
40
#include <java/lang/Runtime.h>
41
#include <java/lang/StringBuffer.h>
42
#include <java/io/Serializable.h>
43
#include <java/lang/Cloneable.h>
44
#include <java/util/HashMap.h>
45
#include <gnu/gcj/runtime/BootClassLoader.h>
46
#include <gnu/gcj/runtime/SystemClassLoader.h>
47
 
48
// Size of local hash table.
49
#define HASH_LEN 1013
50
 
51
// Hash function for Utf8Consts.
52
#define HASH_UTF(Utf) ((Utf)->hash16() % HASH_LEN)
53
 
54
static jclass loaded_classes[HASH_LEN];
55
 
56
// This records classes which will be registered with the system class
57
// loader when it is initialized.
58
static jclass system_class_list;
59
 
60
// This is used as the value of system_class_list after we have
61
// initialized the system class loader; it lets us know that we should
62
// no longer pay attention to the system abi flag.
63
#define SYSTEM_LOADER_INITIALIZED ((jclass) -1)
64
 
65
// This is the root of a linked list of classes
66
static jclass stack_head;
67
 
68
// While bootstrapping we keep a list of classes we found, so that we
69
// can register their packages.  There aren't many of these so we
70
// just keep a small buffer here and abort if we overflow.
71
#define BOOTSTRAP_CLASS_LIST_SIZE 20
72
static jclass bootstrap_class_list[BOOTSTRAP_CLASS_LIST_SIZE];
73
static int bootstrap_index;
74
 
75
 
76
 
77
 
78
jclass
79
java::lang::ClassLoader::loadClassFromSig(jstring name)
80
{
81
  int len = _Jv_GetStringUTFLength (name);
82
  char sig[len + 1];
83
  _Jv_GetStringUTFRegion (name, 0, name->length(), sig);
84
  jclass result = _Jv_FindClassFromSignature(sig, this);
85
  if (result == NULL)
86
    throw new ClassNotFoundException(name);
87
  return result;
88
}
89
 
90
 
91
 
92
// This tries to find a class in our built-in cache.  This cache is
93
// used only for classes which are linked in to the executable or
94
// loaded via dlopen().
95
jclass
96
_Jv_FindClassInCache (_Jv_Utf8Const *name)
97
{
98
  JvSynchronize sync (&java::lang::Class::class$);
99
  jint hash = HASH_UTF (name);
100
 
101
  jclass klass;
102
  for (klass = loaded_classes[hash]; klass; klass = klass->next_or_version)
103
    {
104
      if (_Jv_equalUtf8Consts (name, klass->name))
105
        break;
106
    }
107
 
108
  return klass;
109
}
110
 
111
void
112
_Jv_UnregisterClass (jclass the_class)
113
{
114
  // This can happen if the class could not be defined properly.
115
  if (! the_class->name)
116
    return;
117
 
118
  JvSynchronize sync (&java::lang::Class::class$);
119
  jint hash = HASH_UTF(the_class->name);
120
 
121
  jclass *klass = &(loaded_classes[hash]);
122
  for ( ; *klass; klass = &((*klass)->next_or_version))
123
    {
124
      if (*klass == the_class)
125
        {
126
          *klass = (*klass)->next_or_version;
127
          break;
128
        }
129
    }
130
}
131
 
132
// Register an initiating class loader for a given class.
133
void
134
_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
135
{
136
  if (! loader)
137
    loader = java::lang::VMClassLoader::bootLoader;
138
  if (! loader)
139
    {
140
      // Very early in the bootstrap process, the Bootstrap classloader may 
141
      // not exist yet.
142
      // FIXME: We could maintain a list of these and come back and register
143
      // them later.
144
      return;
145
    }
146
  loader->loadedClasses->put(klass->name->toString(), klass);
147
}
148
 
149
// If we found an error while defining an interpreted class, we must
150
// go back and unregister it.
151
void
152
_Jv_UnregisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
153
{
154
  if (! loader)
155
    loader = java::lang::VMClassLoader::bootLoader;
156
  loader->loadedClasses->remove(klass->name->toString());
157
}
158
 
159
// This function is called many times during startup, before main() is
160
// run.  At that point in time we know for certain we are running 
161
// single-threaded, so we don't need to lock when adding classes to the 
162
// class chain.  At all other times, the caller should synchronize on
163
// Class::class$.
164
void
165
_Jv_RegisterClasses (const jclass *classes)
166
{
167
  for (; *classes; ++classes)
168
    {
169
      jclass klass = *classes;
170
 
171
      if (_Jv_CheckABIVersion ((unsigned long) klass->next_or_version))
172
        (*_Jv_RegisterClassHook) (klass);
173
    }
174
}
175
 
176
// This is a version of _Jv_RegisterClasses that takes a count.
177
void
178
_Jv_RegisterClasses_Counted (const jclass * classes, size_t count)
179
{
180
  size_t i;
181
  for (i = 0; i < count; i++)
182
    {
183
      jclass klass = classes[i];
184
 
185
      if (_Jv_CheckABIVersion ((unsigned long) klass->next_or_version))
186
        (*_Jv_RegisterClassHook) (klass);
187
    }
188
}
189
 
190
void
191
_Jv_RegisterClassHookDefault (jclass klass)
192
{
193
  // This is bogus, but there doesn't seem to be a better place to do
194
  // it.
195
  if (! klass->engine)
196
    klass->engine = &_Jv_soleCompiledEngine;
197
 
198
  if (system_class_list != SYSTEM_LOADER_INITIALIZED)
199
    {
200
      unsigned long abi = (unsigned long) klass->next_or_version;
201
      if (! _Jv_ClassForBootstrapLoader (abi))
202
        {
203
          klass->next_or_version = system_class_list;
204
          system_class_list = klass;
205
          return;
206
        }
207
    }
208
 
209
  jint hash = HASH_UTF (klass->name);
210
 
211
  // If the class is already registered, don't re-register it.
212
  for (jclass check_class = loaded_classes[hash];
213
       check_class != NULL;
214
       check_class = check_class->next_or_version)
215
    {
216
      if (check_class == klass)
217
        {
218
          // If you get this, it means you have the same class in two
219
          // different libraries.
220
#define TEXT "Duplicate class registration: "
221
          // We size-limit MESSAGE so that you can't trash the stack.
222
          char message[200];
223
          strcpy (message, TEXT);
224
          strncpy (message + sizeof (TEXT) - 1, klass->name->chars(),
225
                   sizeof (message) - sizeof (TEXT));
226
          message[sizeof (message) - 1] = '\0';
227
          if (! gcj::runtimeInitialized)
228
            JvFail (message);
229
          else
230
            {
231
              java::lang::String *str = JvNewStringLatin1 (message);
232
              throw new java::lang::VirtualMachineError (str);
233
            }
234
        }
235
    }
236
 
237
  klass->next_or_version = loaded_classes[hash];
238
  loaded_classes[hash] = klass;
239
}
240
 
241
// A pointer to a function that actually registers a class.
242
// Normally _Jv_RegisterClassHookDefault, but could be some other function
243
// that registers the class in e.g. a ClassLoader-local table.
244
// Should synchronize on Class:class$ while setting/restore this variable.
245
 
246
void (*_Jv_RegisterClassHook) (jclass cl) = _Jv_RegisterClassHookDefault;
247
 
248
void
249
_Jv_RegisterClass (jclass klass)
250
{
251
  jclass classes[2];
252
  classes[0] = klass;
253
  classes[1] = NULL;
254
  _Jv_RegisterClasses (classes);
255
}
256
 
257
// This is used during initialization to register all compiled-in
258
// classes that are not part of the core with the system class loader.
259
void
260
_Jv_CopyClassesToSystemLoader (gnu::gcj::runtime::SystemClassLoader *loader)
261
{
262
  for (jclass klass = system_class_list;
263
       klass;
264
       klass = klass->next_or_version)
265
    {
266
      klass->loader = loader;
267
      loader->addClass(klass);
268
    }
269
  system_class_list = SYSTEM_LOADER_INITIALIZED;
270
}
271
 
272
jclass
273
_Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
274
{
275
  // See if the class was already loaded by this loader.  This handles
276
  // initiating loader checks, as we register classes with their
277
  // initiating loaders.
278
 
279
  java::lang::ClassLoader *boot = java::lang::VMClassLoader::bootLoader;
280
  java::lang::ClassLoader *real = loader;
281
  if (! real)
282
    real = boot;
283
  jstring sname = name->toString();
284
  // We might still be bootstrapping the VM, in which case there
285
  // won't be a bootstrap class loader yet.
286
  jclass klass = real ? real->findLoadedClass (sname) : NULL;
287
 
288
  if (! klass)
289
    {
290
      if (loader)
291
        {
292
          // Load using a user-defined loader, jvmspec 5.3.2.
293
          // Note that we explicitly must call the single-argument form.
294
          klass = loader->loadClass(sname);
295
 
296
          // If "loader" delegated the loadClass operation to another
297
          // loader, explicitly register that it is also an initiating
298
          // loader of the given class.
299
          java::lang::ClassLoader *delegate = (loader == boot
300
                                               ? NULL
301
                                               : loader);
302
          if (klass && klass->getClassLoaderInternal () != delegate)
303
            _Jv_RegisterInitiatingLoader (klass, loader);
304
        }
305
      else if (boot)
306
        {
307
          // Load using the bootstrap loader jvmspec 5.3.1.
308
          klass = java::lang::VMClassLoader::loadClass (sname, false);
309
 
310
          // Register that we're an initiating loader.
311
          if (klass)
312
            _Jv_RegisterInitiatingLoader (klass, 0);
313
        }
314
      else
315
        {
316
          // Not even a bootstrap loader, try the built-in cache.
317
          klass = _Jv_FindClassInCache (name);
318
 
319
          if (klass)
320
            {
321
              bool found = false;
322
              for (int i = 0; i < bootstrap_index; ++i)
323
                {
324
                  if (bootstrap_class_list[i] == klass)
325
                    {
326
                      found = true;
327
                      break;
328
                    }
329
                }
330
              if (! found)
331
                {
332
                  if (bootstrap_index == BOOTSTRAP_CLASS_LIST_SIZE)
333
                    abort ();
334
                  bootstrap_class_list[bootstrap_index++] = klass;
335
                }
336
            }
337
        }
338
    }
339
 
340
  return klass;
341
}
342
 
343
void
344
_Jv_RegisterBootstrapPackages ()
345
{
346
  for (int i = 0; i < bootstrap_index; ++i)
347
    java::lang::VMClassLoader::definePackageForNative(bootstrap_class_list[i]->getName());
348
}
349
 
350
jclass
351
_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
352
              java::lang::ClassLoader *loader)
353
{
354
  jclass ret = (jclass) _Jv_AllocObject (&java::lang::Class::class$);
355
  ret->name = name;
356
  ret->superclass = superclass;
357
  ret->loader = loader;
358
 
359
  _Jv_RegisterInitiatingLoader (ret, loader);
360
 
361
  return ret;
362
}
363
 
364
static _Jv_IDispatchTable *array_idt = NULL;
365
static jshort array_depth = 0;
366
static jclass *array_ancestors = NULL;
367
 
368
// Create a class representing an array of ELEMENT and store a pointer to it
369
// in element->arrayclass. LOADER is the ClassLoader which _initiated_ the 
370
// instantiation of this array. ARRAY_VTABLE is the vtable to use for the new 
371
// array class. This parameter is optional.
372
void
373
_Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
374
                   _Jv_VTable *array_vtable)
375
{
376
  JvSynchronize sync (element);
377
 
378
  _Jv_Utf8Const *array_name;
379
  int len;
380
 
381
  if (element->arrayclass)
382
    return;
383
 
384
  if (element->isPrimitive())
385
    {
386
      if (element == JvPrimClass (void))
387
        throw new java::lang::ClassNotFoundException ();
388
      len = 3;
389
    }
390
  else
391
    len = element->name->len() + 5;
392
 
393
  {
394
    char signature[len];
395
    int index = 0;
396
    signature[index++] = '[';
397
    // Compute name of array class.
398
    if (element->isPrimitive())
399
      {
400
        signature[index++] = (char) element->method_count;
401
      }
402
    else
403
      {
404
        size_t length = element->name->len();
405
        const char *const name = element->name->chars();
406
        if (name[0] != '[')
407
          signature[index++] = 'L';
408
        memcpy (&signature[index], name, length);
409
        index += length;
410
        if (name[0] != '[')
411
          signature[index++] = ';';
412
      }
413
    array_name = _Jv_makeUtf8Const (signature, index);
414
  }
415
 
416
  // Create new array class.
417
  jclass array_class = _Jv_NewClass (array_name, &java::lang::Object::class$,
418
                                     element->loader);
419
 
420
  // Note that `vtable_method_count' doesn't include the initial
421
  // gc_descr slot.
422
  int dm_count = java::lang::Object::class$.vtable_method_count;
423
 
424
  // Create a new vtable by copying Object's vtable.
425
  _Jv_VTable *vtable;
426
  if (array_vtable)
427
    vtable = array_vtable;
428
  else
429
    vtable = _Jv_VTable::new_vtable (dm_count);
430
  vtable->clas = array_class;
431
  vtable->gc_descr = java::lang::Object::class$.vtable->gc_descr;
432
  for (int i = 0; i < dm_count; ++i)
433
    vtable->set_method (i, java::lang::Object::class$.vtable->get_method (i));
434
 
435
  array_class->vtable = vtable;
436
  array_class->vtable_method_count
437
    = java::lang::Object::class$.vtable_method_count;
438
 
439
  // Stash the pointer to the element type.
440
  array_class->methods = (_Jv_Method *) element;
441
 
442
  // Register our interfaces.
443
  static jclass interfaces[] =
444
    {
445
      &java::lang::Cloneable::class$,
446
      &java::io::Serializable::class$
447
    };
448
  array_class->interfaces = interfaces;
449
  array_class->interface_count = sizeof interfaces / sizeof interfaces[0];
450
 
451
  // Since all array classes have the same interface dispatch table, we can 
452
  // cache one and reuse it. It is not necessary to synchronize this.
453
  if (!array_idt)
454
    {
455
      _Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED);
456
      array_idt = array_class->idt;
457
      array_depth = array_class->depth;
458
      array_ancestors = array_class->ancestors;
459
    }
460
  else
461
    {
462
      array_class->idt = array_idt;
463
      array_class->depth = array_depth;
464
      array_class->ancestors = array_ancestors;
465
    }
466
 
467
  using namespace java::lang::reflect;
468
  {
469
    // Array classes are "abstract final" and inherit accessibility
470
    // from element type, per vmspec 5.3.3.2
471
    _Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT
472
                           | (element->accflags
473
                              & (Modifier::PUBLIC | Modifier::PROTECTED
474
                                 | Modifier::PRIVATE)));
475
    array_class->accflags = accflags;
476
  }
477
 
478
  // An array class has no visible instance fields. "length" is invisible to 
479
  // reflection.
480
 
481
  // Say this class is initialized and ready to go!
482
  array_class->state = JV_STATE_DONE;
483
 
484
  // vmspec, section 5.3.3 describes this
485
  if (element->loader != loader)
486
    _Jv_RegisterInitiatingLoader (array_class, loader);
487
 
488
  element->arrayclass = array_class;
489
}
490
 
491
// These two functions form a stack of classes.   When a class is loaded
492
// it is pushed onto the stack by the class loader; this is so that
493
// StackTrace can quickly determine which classes have been loaded.
494
 
495
jclass
496
_Jv_PopClass (void)
497
{
498
  JvSynchronize sync (&java::lang::Class::class$);
499
  if (stack_head)
500
    {
501
      jclass tmp = stack_head;
502
      stack_head = tmp->chain;
503
      return tmp;
504
    }
505
  return NULL;
506
}
507
 
508
void
509
_Jv_PushClass (jclass k)
510
{
511
  JvSynchronize sync (&java::lang::Class::class$);
512
  jclass tmp = stack_head;
513
  stack_head = k;
514
  k->chain = tmp;
515
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.