Skip to main content

java classloader相关内容

· 5 min read

背景

学习java的类加载内容,了解java类加载是加载什么内容? 是加载*.class文件,还是加载*.java.或者其实文件格式不重要,classjava都可以

demo of classloader

demo地址

the same type

相关阅读

4.3.4 When Reference Types Are the Same
Two reference types are the same compile-time type if they have the same binary
name (§13.1) and their type arguments, if any, are the same, applying this definition
recursively.
When two reference types are the same, they are sometimes said to be the same
class or the same interface.
At run time, several reference types with the same binary name may be loaded
simultaneously by different class loaders. These types may or may not represent
the same type declaration. Even if two such types do represent the same type
declaration, they are considered distinct.
Two reference types are the same run-time type if:
• They are both class or both interface types, are defined by the same class loader,
and have the same binary name (§13.1), in which case they are sometimes said
to be the same run-time class or the same run-time interface.
• They are both array types, and their component types are the same run-time type
(§10 (Arrays)).
Thread 2 "java" hit Breakpoint 5, SystemDictionary::resolve_class_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:865
865 HandleMark hm(THREAD);
(gdb) p class_name->print()
Symbol: 'A' count 65535$27 = void
(gdb) bt
#0 SystemDictionary::resolve_class_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:865
#1 0x00007ffff69b9c32 in SystemDictionary::resolve_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:929
#2 0x00007ffff62f1cd8 in jvm_define_class_common (name=0x7ffff531f030 "A", loader=0x7ffff531f5a0, buf=0x7ffff04b1b40 "\312\376\272\276", len=176, pd=0x7ffff531f578,
source=0x7ffff71430ee "__JVM_DefineClass__", __the_thread__=0x7ffff002a690) at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:912
#3 0x00007ffff62f29b1 in JVM_DefineClassWithSource (env=0x7ffff002aa90, name=0x7ffff531f030 "A", loader=0x7ffff531f5a0, buf=0x7ffff04b1b40 "\312\376\272\276", len=176, pd=0x7ffff531f578, source=0x0)
at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:1079
#4 0x00007ffff51e14f7 in Java_java_lang_ClassLoader_defineClass1 (env=0x7ffff002aa90, cls=0x7ffff531f560, loader=0x7ffff531f5a0, name=0x7ffff531f598, data=0x7ffff531f590, offset=0, length=176,
pd=0x7ffff531f578, source=0x0) at /home/dai/jdk/src/java.base/share/native/libjava/ClassLoader.c:139
#5 0x00007fffe854588e in ?? ()
#6 0xffffffff000000b0 in ?? ()
#7 0x00007ffff531f578 in ?? ()
#8 0x0000000000000000 in ?? ()

查找加载的内容

JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
ResourceMark rm(THREAD);

Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
char* str = java_lang_String::as_utf8_string(h_name());

// Sanity check, don't expect null
if (str == nullptr) return nullptr;

// Internalize the string, converting '.' to '/' in string.
char* p = (char*)str;
while (*p != '\0') {
if (*p == '.') {
*p = '/';
}
p++;
}

const int str_len = (int)(p - str);
if (str_len > Symbol::max_length()) {
// It's impossible to create this class; the name cannot fit
// into the constant pool.
return nullptr;
}
TempNewSymbol klass_name = SymbolTable::new_symbol(str, str_len);

// Security Note:
// The Java level wrapper will perform the necessary security check allowing
// us to pass the null as the initiating class loader.
Handle h_loader(THREAD, JNIHandles::resolve(loader));
Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name,
h_loader,
Handle());
#if INCLUDE_CDS
if (k == nullptr) {
// If the class is not already loaded, try to see if it's in the shared
// archive for the current classloader (h_loader).
k = SystemDictionaryShared::find_or_load_shared_class(klass_name, h_loader, CHECK_NULL);
}
#endif
return (k == nullptr) ? nullptr :
(jclass) JNIHandles::make_local(THREAD, k->java_mirror());
JVM_END
// Update class loader data dictionary - done after check_constraint and add_to_hierarchy
// have been called.
void SystemDictionary::update_dictionary(JavaThread* current,
InstanceKlass* k,
ClassLoaderData* loader_data) {
MonitorLocker mu1(SystemDictionary_lock);

// Make a new dictionary entry.
Symbol* name = k->name();
Dictionary* dictionary = loader_data->dictionary();
InstanceKlass* sd_check = dictionary->find_class(current, name);
if (sd_check == nullptr) {
dictionary->add_klass(current, name, k);
}
mu1.notify_all();
}

查找过程:

InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
Symbol* class_name,
Handle class_loader,
Handle protection_domain) {

// The result of this call should be consistent with the result
// of the call to resolve_instance_class_or_null().
// See evaluation 6790209 and 4474172 for more details.
oop class_loader_oop = java_lang_ClassLoader::non_reflection_class_loader(class_loader());
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader_oop);

if (loader_data == NULL) {
// If the ClassLoaderData has not been setup,
// then the class loader has no entries in the dictionary.
return NULL;
}

Dictionary* dictionary = loader_data->dictionary();
return dictionary->find(current, class_name, protection_domain);
}

查询的堆栈:

Thread 2 "java" hit Breakpoint 4, Dictionary::find (this=0x7ffff0556dd0, current=0x7ffff002a690, name=0x7ffff02c6728, protection_domain=...) at /home/dai/jdk/src/hotspot/share/classfile/dictionary.cpp:298
298 NoSafepointVerifier nsv;
Symbol: 'A' count 65535$89 = void
(gdb) bt
#0 Dictionary::find (this=0x7ffff0556dd0, current=0x7ffff002a690, name=0x7ffff02c6728, protection_domain=...) at /home/dai/jdk/src/hotspot/share/classfile/dictionary.cpp:298
#1 0x00007ffff69b9384 in SystemDictionary::find_instance_klass (current=0x7ffff002a690, class_name=0x7ffff02c6728, class_loader=..., protection_domain=...)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:765
#2 0x00007ffff69b94dc in SystemDictionary::find_instance_or_array_klass (current=0x7ffff002a690, class_name=0x7ffff02c6728, class_loader=..., protection_domain=...)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:793
#3 0x00007ffff62f2bba in JVM_FindLoadedClass (env=0x7ffff002aa90, loader=0x7ffff531f410, name=0x7ffff531f408) at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:1112
#4 0x00007ffff51e1c7c in Java_java_lang_ClassLoader_findLoadedClass0 (env=0x7ffff002aa90, loader=0x7ffff531f410, name=0x7ffff531f408) at /home/dai/jdk/src/java.base/share/native/libjava/ClassLoader.c:327
#5 0x00007fffe854588e in ?? ()
#6 0x0000000000000000 in ?? ()
(gdb) c

dict 维护

inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
if (loader == NULL) {
return ClassLoaderData::the_null_class_loader_data();
}
return java_lang_ClassLoader::loader_data_acquire(loader);
}

oop 转对象:

ClassLoaderData* java_lang_ClassLoader::loader_data_acquire(oop loader) {
assert(loader != NULL, "loader must not be NULL");
assert(oopDesc::is_oop(loader), "loader must be oop");
return Atomic::load_acquire(loader->field_addr<ClassLoaderData*>(_loader_data_offset));
}

相关阅读