📄 natclassloader.cc
字号:
while (*info && (*info)->klass == the_class) { _Jv_LoaderInfo *old = *info; *info = (*info)->next; _Jv_Free (old); } if (*info == NULL) break; }}void_Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader){ if (loader && loader == java::lang::ClassLoader::getSystemClassLoader()) loader = NULL; // This information can't be visible to the GC. _Jv_LoaderInfo *info = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo)); jint hash = HASH_UTF(klass->name); JvSynchronize sync (&java::lang::Class::class$); info->loader = loader; info->klass = klass; info->next = initiated_classes[hash]; initiated_classes[hash] = info;}// This function is called many times during startup, before main() is// run. At that point in time we know for certain we are running // single-threaded, so we don't need to lock when adding classes to the // class chain. At all other times, the caller should synchronize on// Class::class$.void_Jv_RegisterClasses (jclass *classes){ for (; *classes; ++classes) { jclass klass = *classes; (*_Jv_RegisterClassHook) (klass); // registering a compiled class causes // it to be immediately "prepared". if (klass->state == JV_STATE_NOTHING) klass->state = JV_STATE_COMPILED; }}void_Jv_RegisterClassHookDefault (jclass klass){ jint hash = HASH_UTF (klass->name); jclass check_class = loaded_classes[hash]; // If the class is already registered, don't re-register it. while (check_class != NULL) { if (check_class == klass) { // If you get this, it means you have the same class in two // different libraries.#define TEXT "Duplicate class registration: " // We size-limit MESSAGE so that you can't trash the stack. char message[200]; strcpy (message, TEXT); strncpy (message + sizeof (TEXT) - 1, klass->name->data, sizeof (message) - sizeof (TEXT)); message[sizeof (message) - 1] = '\0'; if (! gcj::runtimeInitialized) JvFail (message); else { java::lang::String *str = JvNewStringLatin1 (message); throw new java::lang::VirtualMachineError (str); } } check_class = check_class->next; } klass->next = loaded_classes[hash]; loaded_classes[hash] = klass;}// A pointer to a function that actually registers a class.// Normally _Jv_RegisterClassHookDefault, but could be some other function// that registers the class in e.g. a ClassLoader-local table.// Should synchronize on Class:class$ while setting/restore this variable.void (*_Jv_RegisterClassHook) (jclass cl) = _Jv_RegisterClassHookDefault;void_Jv_RegisterClass (jclass klass){ jclass classes[2]; classes[0] = klass; classes[1] = NULL; _Jv_RegisterClasses (classes);}jclass_Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader){ jclass klass = _Jv_FindClassInCache (name, loader); if (! klass) { jstring sname = _Jv_NewStringUTF (name->data); java::lang::ClassLoader *sys = java::lang::ClassLoader::getSystemClassLoader (); if (loader) { // Load using a user-defined loader, jvmspec 5.3.2 klass = loader->loadClass(sname, false); // If "loader" delegated the loadClass operation to another // loader, explicitly register that it is also an initiating // loader of the given class. java::lang::ClassLoader *delegate = (loader == sys ? NULL : loader); if (klass && klass->getClassLoaderInternal () != delegate) _Jv_RegisterInitiatingLoader (klass, loader); } else { // Load using the bootstrap loader jvmspec 5.3.1. klass = sys->loadClass (sname, false); // Register that we're an initiating loader. if (klass) _Jv_RegisterInitiatingLoader (klass, 0); } } else { // we need classes to be in the hash while // we're loading, so that they can refer to themselves. _Jv_WaitForState (klass, JV_STATE_LOADED); } return klass;}void_Jv_InitNewClassFields (jclass ret){ ret->next = NULL; ret->name = NULL; ret->accflags = 0; ret->superclass = NULL; ret->constants.size = 0; ret->constants.tags = NULL; ret->constants.data = NULL; ret->methods = NULL; ret->method_count = 0; ret->vtable_method_count = 0; ret->fields = NULL; ret->size_in_bytes = 0; ret->field_count = 0; ret->static_field_count = 0; ret->vtable = NULL; ret->interfaces = NULL; ret->loader = NULL; ret->interface_count = 0; ret->state = JV_STATE_NOTHING; ret->thread = NULL; ret->depth = 0; ret->ancestors = NULL; ret->idt = NULL; ret->arrayclass = NULL; ret->protectionDomain = NULL; ret->chain = NULL;}jclass_Jv_NewClass (_Jv_Utf8Const *name, jclass superclass, java::lang::ClassLoader *loader){ jclass ret = (jclass) JvAllocObject (&java::lang::Class::class$); _Jv_InitNewClassFields (ret); ret->name = name; ret->superclass = superclass; ret->loader = loader; _Jv_RegisterClass (ret); return ret;}static _Jv_IDispatchTable *array_idt = NULL;static jshort array_depth = 0;static jclass *array_ancestors = NULL;// Create a class representing an array of ELEMENT and store a pointer to it// in element->arrayclass. LOADER is the ClassLoader which _initiated_ the // instantiation of this array. ARRAY_VTABLE is the vtable to use for the new // array class. This parameter is optional.void_Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader, _Jv_VTable *array_vtable){ JvSynchronize sync (element); _Jv_Utf8Const *array_name; int len; if (element->arrayclass) return; if (element->isPrimitive()) { if (element == JvPrimClass (void)) throw new java::lang::ClassNotFoundException (); len = 3; } else len = element->name->length + 5; { char signature[len]; int index = 0; signature[index++] = '['; // Compute name of array class. if (element->isPrimitive()) { signature[index++] = (char) element->method_count; } else { size_t length = element->name->length; const char *const name = element->name->data; if (name[0] != '[') signature[index++] = 'L'; memcpy (&signature[index], name, length); index += length; if (name[0] != '[') signature[index++] = ';'; } array_name = _Jv_makeUtf8Const (signature, index); } // Create new array class. jclass array_class = _Jv_NewClass (array_name, &java::lang::Object::class$, element->loader); // Note that `vtable_method_count' doesn't include the initial // gc_descr slot. JvAssert (java::lang::Object::class$.vtable_method_count == NUM_OBJECT_METHODS); int dm_count = java::lang::Object::class$.vtable_method_count; // Create a new vtable by copying Object's vtable. _Jv_VTable *vtable; if (array_vtable) vtable = array_vtable; else vtable = _Jv_VTable::new_vtable (dm_count); vtable->clas = array_class; vtable->gc_descr = java::lang::Object::class$.vtable->gc_descr; for (int i = 0; i < dm_count; ++i) vtable->set_method (i, java::lang::Object::class$.vtable->get_method (i)); array_class->vtable = vtable; array_class->vtable_method_count = java::lang::Object::class$.vtable_method_count; // Stash the pointer to the element type. array_class->methods = (_Jv_Method *) element; // Register our interfaces. static jclass interfaces[] = { &java::lang::Cloneable::class$, &java::io::Serializable::class$ }; array_class->interfaces = interfaces; array_class->interface_count = sizeof interfaces / sizeof interfaces[0]; // Since all array classes have the same interface dispatch table, we can // cache one and reuse it. It is not necessary to synchronize this. if (!array_idt) { _Jv_PrepareConstantTimeTables (array_class); array_idt = array_class->idt; array_depth = array_class->depth; array_ancestors = array_class->ancestors; } else { array_class->idt = array_idt; array_class->depth = array_depth; array_class->ancestors = array_ancestors; } using namespace java::lang::reflect; { // Array classes are "abstract final"... _Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT; // ... and inherit accessibility from element type, per vmspec 5.3.3.2 accflags |= (element->accflags & Modifier::PUBLIC); accflags |= (element->accflags & Modifier::PROTECTED); accflags |= (element->accflags & Modifier::PRIVATE); array_class->accflags = accflags; } // An array class has no visible instance fields. "length" is invisible to // reflection. // say this class is initialized and ready to go! array_class->state = JV_STATE_DONE; // vmspec, section 5.3.3 describes this if (element->loader != loader) _Jv_RegisterInitiatingLoader (array_class, loader); element->arrayclass = array_class;}static jclass stack_head;// These two functions form a stack of classes. When a class is loaded// it is pushed onto the stack by the class loader; this is so that// StackTrace can quickly determine which classes have been loaded.jclass_Jv_PopClass (void){ JvSynchronize sync (&java::lang::Class::class$); if (stack_head) { jclass tmp = stack_head; stack_head = tmp->chain; return tmp; } return NULL;}void_Jv_PushClass (jclass k){ JvSynchronize sync (&java::lang::Class::class$); jclass tmp = stack_head; stack_head = k; k->chain = tmp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -