赞
踩
这一章的内容主要是对初始后的 Java Class 的需要使用(主要体现在反射)的字段计算偏移(偏移是指相对于类本身的 存储位置的起始位置)
函数调用链:
init.cpp->init_globals
javaClasses.cpp->javaClasses_init()
void javaClasses_init() {
// 计算偏移
JavaClasses::compute_offsets();
// 计算完后,要验证偏移
JavaClasses::check_offsets();
FilteredFieldsMap::initialize(); // must be done after computing offsets.
}
计算字段偏移
void JavaClasses::compute_offsets() { // 计算偏移每个操作都差不多,这里抽前面 java_lang_ClassLoader 和 java_lang_Thread 两个类来讲,其他照葫芦画瓢 java_lang_ClassLoader::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableInvokeDynamic) { java_lang_invoke_MethodHandle::compute_offsets(); java_lang_invoke_DirectMethodHandle::compute_offsets(); java_lang_invoke_MemberName::compute_offsets(); java_lang_invoke_LambdaForm::compute_offsets(); java_lang_invoke_MethodType::compute_offsets(); java_lang_invoke_CallSite::compute_offsets(); } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes // changed with the new reflection implementation in JDK 1.4, and // since the Universe doesn't know what JDK version it is until this // point we defer computation of these offsets until now. java_lang_reflect_AccessibleObject::compute_offsets(); java_lang_reflect_Method::compute_offsets(); java_lang_reflect_Constructor::compute_offsets(); java_lang_reflect_Field::compute_offsets(); if (JDK_Version::is_gte_jdk14x_version()) { java_nio_Buffer::compute_offsets(); } if (JDK_Version::is_gte_jdk15x_version()) { sun_reflect_ConstantPool::compute_offsets(); sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets(); } if (JDK_Version::is_jdk18x_version()) java_lang_reflect_Parameter::compute_offsets(); java_lang_ref_ReferenceQueue::compute_offsets(); // generated interpreter code wants to know about the offsets we just computed: AbstractAssembler::update_delayed_values(); }
java_lang_ClassLoader::compute_offsets()
void java_lang_ClassLoader::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
// 直接看这一行,计算 ClassLoader 类的 parallelCapable 字段的偏移
Klass* k1 = SystemDictionary::ClassLoader_klass();
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
java_lang_Thread::compute_offsets()
void java_lang_Thread::compute_offsets() { assert(_group_offset == 0, "offsets should be initialized only once"); Klass* k = SystemDictionary::Thread_klass(); // 计算 name/group/priority...等偏移 compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature()); compute_offset(_priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature()); compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); compute_offset(_eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature()); compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature()); // The stackSize field is only present starting in 1.4, so don't go fatal. compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature()); // The tid and thread_status fields are only present starting in 1.5, so don't go fatal. compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature()); compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature()); // The parkBlocker field is only present starting in 1.6, so don't go fatal. compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature()); compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(), vmSymbols::long_signature()); }
校验偏移
void JavaClasses::check_offsets() { bool valid = true; HandleMark hm; #define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig) #define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig) #define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig) #define CHECK_CONSTANT(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_constant(klass_name, cpp_klass_name :: field_name, #field_name, field_sig) // java.lang.String CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C"); if (java_lang_String::has_offset_field()) { CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I"); CHECK_OFFSET("java/lang/String", java_lang_String, count, "I"); } if (java_lang_String::has_hash_field()) { CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I"); } // java.lang.Class // Fake fields // CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked // CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked // java.lang.Throwable CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, backtrace, "Ljava/lang/Object;"); CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, detailMessage, "Ljava/lang/String;"); CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, cause, "Ljava/lang/Throwable;"); CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, stackTrace, "[Ljava/lang/StackTraceElement;"); // Boxed primitive objects (java_lang_boxing_object) CHECK_OFFSET("java/lang/Boolean", java_lang_boxing_object, value, "Z"); CHECK_OFFSET("java/lang/Character", java_lang_boxing_object, value, "C"); CHECK_OFFSET("java/lang/Float", java_lang_boxing_object, value, "F"); CHECK_LONG_OFFSET("java/lang/Double", java_lang_boxing_object, value, "D"); CHECK_OFFSET("java/lang/Byte", java_lang_boxing_object, value, "B"); CHECK_OFFSET("java/lang/Short", java_lang_boxing_object, value, "S"); CHECK_OFFSET("java/lang/Integer", java_lang_boxing_object, value, "I"); CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J"); // java.lang.ClassLoader CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent, "Ljava/lang/ClassLoader;"); // java.lang.System CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, in, "Ljava/io/InputStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, out, "Ljava/io/PrintStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, err, "Ljava/io/PrintStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, security, "Ljava/lang/SecurityManager;"); // java.lang.StackTraceElement CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;"); CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;"); CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName, "Ljava/lang/String;"); CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I"); // java.lang.ref.Reference CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, referent, "Ljava/lang/Object;"); CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, queue, "Ljava/lang/ref/ReferenceQueue;"); CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, next, "Ljava/lang/ref/Reference;"); // Fake field //CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;"); CHECK_STATIC_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, lock, "Ljava/lang/ref/Reference$Lock;"); CHECK_STATIC_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, pending, "Ljava/lang/ref/Reference;"); // java.lang.ref.SoftReference CHECK_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, timestamp, "J"); CHECK_STATIC_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, clock, "J"); // java.lang.AssertionStatusDirectives // // The CheckAssertionStatusDirectives boolean can be removed from here and // globals.hpp after the AssertionStatusDirectives class has been integrated // into merlin "for some time." Without it, the vm will fail with early // merlin builds. if (CheckAssertionStatusDirectives && JDK_Version::is_gte_jdk14x_version()) { const char* nm = "java/lang/AssertionStatusDirectives"; const char* sig = "[Ljava/lang/String;"; CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classes, sig); CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classEnabled, "[Z"); CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packages, sig); CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packageEnabled, "[Z"); CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, deflt, "Z"); } if (!valid) vm_exit_during_initialization("Hard-coded field offset verification failed"); }
check_offset 检验实体字段偏移
bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) { EXCEPTION_MARK; fieldDescriptor fd; // 先给 klass name 创建一个符合 TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); // 通过 klass name 符合解析出真实的 klass 对象 Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); // 增加句柄 instanceKlassHandle h_klass (THREAD, k); // 再分别给 字段名 和 字段签名 创建对应的符号 TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); // 从 klass 对象查找该字段是否存在,不存在,直接返回 false 退出 if (!h_klass->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Nonstatic field %s.%s not found", klass_name, field_name); return false; } // 找到了 字段,但是是静态的,也返回 false 退出 if (fd.is_static()) { tty->print_cr("Nonstatic field %s.%s appears to be static", klass_name, field_name); return false; } // 字段偏移与上面计算的偏移一致,返回 true 成功退出 if (fd.offset() == hardcoded_offset ) { return true; } else { tty->print_cr("Offset of nonstatic field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset()); return false; } }
check_static_offset 检验静态字段偏移
bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) { EXCEPTION_MARK; fieldDescriptor fd; TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); instanceKlassHandle h_klass (THREAD, k); TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); if (!h_klass->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Static field %s.%s not found", klass_name, field_name); return false; } // 上面的代码跟 check_offset 完全一样,主要看这一行,如果不是 static,就 false 退出了 if (!fd.is_static()) { tty->print_cr("Static field %s.%s appears to be nonstatic", klass_name, field_name); return false; } if (fd.offset() == hardcoded_offset + InstanceMirrorKlass::offset_of_static_fields()) { return true; } else { tty->print_cr("Offset of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset() - InstanceMirrorKlass::offset_of_static_fields()); return false; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。