openjdk17在java方法中创建对象 类加载在C++源码实现步骤

java的testYYM方法中OtherClass类是如何被加载的

##有请志愿者java实验类 ByteCodeTest、OtherClass

import java.lang.reflect.Method;public class ByteCodeTest {private int insert=678;public static void main(String[] args) throws Exception {ByteCodeTest byteCodeTest = new ByteCodeTest();Method method = ByteCodeTest.class.getDeclaredMethod("testYYM", int.class, int.class);Object result = method.invoke(byteCodeTest, 1,2);System.out.println(result);System.in.read();}public int testYYM(int a, int b) {OtherClass otherClass = new OtherClass();otherClass.dddd();int c = 0;while(a>b) {c = a-b;}c=c+1+this.insert;return c;}}
public class OtherClass {public void dddd() {System.out.println("dddd");}}

##javap -v ByteCodeTest查看 字节码指令new OtherClass对象

public int testYYM(int, int);descriptor: (II)Iflags: ACC_PUBLICCode:stack=2, locals=5, args_size=30: new           #16                 // class com/newland/mi/OtherClass3: dup4: invokespecial #17                 // Method com/newland/mi/OtherClass."<init>":()V7: astore_38: aload_39: invokevirtual #18                 // Method com/newland/mi/OtherClass.dddd:()V12: iconst_013: istore        415: iload_116: iload_217: if_icmple     2820: iload_121: iload_222: isub23: istore        425: goto          1528: iload         430: iconst_131: iadd32: aload_033: getfield      #2                  // Field insert:I36: iadd37: istore        439: iload         441: ireturnLineNumberTable:line 19: 0line 20: 8line 21: 12line 22: 15line 23: 20line 25: 28line 26: 39LocalVariableTable:Start  Length  Slot  Name   Signature0      42     0  this   Lcom/newland/mi/ByteCodeTest;0      42     1     a   I0      42     2     b   I8      34     3 otherClass   Lcom/newland/mi/OtherClass;15      27     4     c   IStackMapTable: number_of_entries = 2frame_type = 253 /* append */offset_delta = 15locals = [ class com/newland/mi/OtherClass, int ]frame_type = 12 /* same */

##C++ new 指令源码

JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* current, ConstantPool* pool, int index))Klass* k = pool->klass_at(index, CHECK);InstanceKlass* klass = InstanceKlass::cast(k);// Make sure we are not instantiating an abstract klassklass->check_valid_for_instantiation(true, CHECK);// Make sure klass is initializedklass->initialize(CHECK);// At this point the class may not be fully initialized// because of recursive initialization. If it is fully// initialized & has_finalized is not set, we rewrite// it into its fast version (Note: no locking is needed// here since this is an atomic byte write and can be// done more than once).//// Note: In case of classes with has_finalized we don't//       rewrite since that saves us an extra check in//       the fast version which then would call the//       slow version anyway (and do a call back into//       Java).//       If we have a breakpoint, then we don't rewrite//       because the _breakpoint bytecode would be lost.oop obj = klass->allocate_instance(CHECK);// std::cout << "@@@@yym%%%%obj address " << klass->name()->as_C_string() << obj << "----begin" << std::endl;current->set_vm_result(obj);
JRT_END

##Klass* k = pool->klass_at(index, CHECK); 池中查找是否有缓存的klass

池中缓存没有命中,SystemDictionary::load_instance_class_impl方法调用jdk/internal/loader/ClassLoaders$AppClassLoader  loadClass 方法加载

调用java loadClass 方法

JavaCalls::call_virtual(&result,
                            class_loader,
                            spec_klass,
                            vmSymbols::loadClass_name(),
                            vmSymbols::string_class_signature(),
                            string,
                            CHECK_NULL);

##源码

InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Handle class_loader, TRAPS) {if (class_loader.is_null()) {ResourceMark rm(THREAD);PackageEntry* pkg_entry = NULL;bool search_only_bootloader_append = false;ClassLoaderData *loader_data = class_loader_data(class_loader);// Find the package in the boot loader's package entry table.TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);if (pkg_name != NULL) {pkg_entry = loader_data->packages()->lookup_only(pkg_name);}// Prior to attempting to load the class, enforce the boot loader's// visibility boundaries.if (!Universe::is_module_initialized()) {// During bootstrapping, prior to module initialization, any// class attempting to be loaded must be checked against the// java.base packages in the boot loader's PackageEntryTable.// No class outside of java.base is allowed to be loaded during// this bootstrapping window.if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {// Class is either in the unnamed package or in// a named package within the unnamed module.  Either// case is outside of java.base, do not attempt to// load the class post java.base definition.  If// java.base has not been defined, let the class load// and its package will be checked later by// ModuleEntryTable::verify_javabase_packages.if (ModuleEntryTable::javabase_defined()) {return NULL;}} else {// Check that the class' package is defined within java.base.ModuleEntry* mod_entry = pkg_entry->module();Symbol* mod_entry_name = mod_entry->name();if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {return NULL;}}} else {// After the module system has been initialized, check if the class'// package is in a module defined to the boot loader.if (pkg_name == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {// Class is either in the unnamed package, in a named package// within a module not defined to the boot loader or in a// a named package within the unnamed module.  In all cases,// limit visibility to search for the class only in the boot// loader's append path.if (!ClassLoader::has_bootclasspath_append()) {// If there is no bootclasspath append entry, no need to continue// searching.return NULL;}search_only_bootloader_append = true;}}// Prior to bootstrapping's module initialization, never load a class outside// of the boot loader's module pathassert(Universe::is_module_initialized() ||!search_only_bootloader_append,"Attempt to load a class outside of boot loader's module path");// Search for classes in the CDS archive.InstanceKlass* k = NULL;#if INCLUDE_CDSif (UseSharedSpaces){PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name);if (ik != NULL && ik->is_shared_boot_class() && !ik->shared_loading_failed()) {SharedClassLoadingMark slm(THREAD, ik);k = load_shared_class(ik, class_loader, Handle(), NULL,  pkg_entry, CHECK_NULL);}}
#endifif (k == NULL) {// Use VM class loaderPerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_NULL);}// find_or_define_instance_class may return a different InstanceKlassif (k != NULL) {CDS_ONLY(SharedClassLoadingMark slm(THREAD, k);)k = find_or_define_instance_class(class_name, class_loader, k, CHECK_NULL);}return k;} else {// Use user specified class loader to load class. Call loadClass operation on class_loader.ResourceMark rm(THREAD);JavaThread* jt = THREAD;PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(),ClassLoader::perf_app_classload_selftime(),ClassLoader::perf_app_classload_count(),jt->get_thread_stat()->perf_recursion_counts_addr(),jt->get_thread_stat()->perf_timers_addr(),PerfClassTraceTime::CLASS_LOAD);Handle s = java_lang_String::create_from_symbol(class_name, CHECK_NULL);// Translate to external class name format, i.e., convert '/' chars to '.'Handle string = java_lang_String::externalize_classname(s, CHECK_NULL);JavaValue result(T_OBJECT);InstanceKlass* spec_klass = vmClasses::ClassLoader_klass();// Call public unsynchronized loadClass(String) directly for all class loaders.// For parallelCapable class loaders, JDK >=7, loadClass(String, boolean) will// acquire a class-name based lock rather than the class loader object lock.// JDK < 7 already acquire the class loader lock in loadClass(String, boolean).JavaCalls::call_virtual(&result,class_loader,spec_klass,vmSymbols::loadClass_name(),vmSymbols::string_class_signature(),string,CHECK_NULL);assert(result.get_type() == T_OBJECT, "just checking");oop obj = result.get_oop();// Primitive classes return null since forName() can not be// used to obtain any of the Class objects representing primitives or voidif ((obj != NULL) && !(java_lang_Class::is_primitive(obj))) {InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(obj));// For user defined Java class loaders, check that the name returned is// the same as that requested.  This check is done for the bootstrap// loader when parsing the class file.if (class_name == k->name()) {return k;}}// Class is not found or has the wrong name, return NULLreturn NULL;}
}

##C++调用java ClassLoader loadClass方法

##C++源码

void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {JavaCallArguments args(receiver);args.push_oop(arg1);call_virtual(result, spec_klass, name, signature, &args, CHECK);
}// ============ Virtual calls ============void JavaCalls::call_virtual(JavaValue* result, Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {CallInfo callinfo;Handle receiver = args->receiver();Klass* recvrKlass = receiver.is_null() ? (Klass*)NULL : receiver->klass();LinkInfo link_info(spec_klass, name, signature);LinkResolver::resolve_virtual_call(callinfo, receiver, recvrKlass, link_info, true, CHECK);methodHandle method(THREAD, callinfo.selected_method());assert(method.not_null(), "should have thrown exception");// Invoke the method// method->print_on(tty);JavaCalls::call(result, method, args, CHECK);// char * yym_method_str = method->name()->as_C_string();// std::cout << "@@@@yym%%%%" << yym_method_str << "----begin" << std::endl;
}// Implementation of JavaCalls (low level)void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) {// Check if we need to wrap a potential OS exception handler around thread.// This is used for e.g. Win32 structured exception handlers.// Need to wrap each and every time, since there might be native code down the// stack that has installed its own exception handlers.// method->print_on(tty);os::os_exception_wrapper(call_helper, result, method, args, THREAD);
}void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) {JavaThread* thread = THREAD;assert(method.not_null(), "must have a method to call");assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation");assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here");// Verify the argumentsif (JVMCI_ONLY(args->alternative_target().is_null() &&) (DEBUG_ONLY(true ||) CheckJNICalls)) {args->verify(method, result->get_type());}// Ignore call if method is emptyif (JVMCI_ONLY(args->alternative_target().is_null() &&) method->is_empty_method()) {assert(result->get_type() == T_VOID, "an empty method must return a void value");return;}#ifdef ASSERT{ InstanceKlass* holder = method->method_holder();// A klass might not be initialized since JavaCall's might be used during the executing of// the <clinit>. For example, a Thread.start might start executing on an object that is// not fully initialized! (bad Java programming style)assert(holder->is_linked(), "rewriting must have taken place");}
#endifCompilationPolicy::compile_if_required(method, CHECK);// Since the call stub sets up like the interpreter we call the from_interpreted_entry// so we can go compiled via a i2c. Otherwise initial entry method will always// run interpreted.address entry_point = method->from_interpreted_entry();if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) {entry_point = method->interpreter_entry();}// Figure out if the result value is an oop or not (Note: This is a different value// than result_type. result_type will be T_INT of oops. (it is about size)BasicType result_type = runtime_type_from(result);bool oop_result_flag = is_reference_type(result->get_type());// Find receiverHandle receiver = (!method->is_static()) ? args->receiver() : Handle();// When we reenter Java, we need to reenable the reserved/yellow zone which// might already be disabled when we are in VM.thread->stack_overflow_state()->reguard_stack_if_needed();// Check that there are shadow pages available before changing thread state// to Java. Calculate current_stack_pointer here to make sure// stack_shadow_pages_available() and bang_stack_shadow_pages() use the same sp.address sp = os::current_stack_pointer();if (!os::stack_shadow_pages_available(THREAD, method, sp)) {// Throw stack overflow exception with preinitialized exception.Exceptions::throw_stack_overflow_exception(THREAD, __FILE__, __LINE__, method);return;} else {// Touch pages checked if the OS needs them to be touched to be mapped.os::map_stack_shadow_pages(sp);}// do call{ JavaCallWrapper link(method, receiver, result, CHECK);{ HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner// NOTE: if we move the computation of the result_val_address inside// the call to call_stub, the optimizer produces wrong code.intptr_t* result_val_address = (intptr_t*)(result->get_value_addr());intptr_t* parameter_address = args->parameters();
#if INCLUDE_JVMCI// Gets the alternative target (if any) that should be calledHandle alternative_target = args->alternative_target();if (!alternative_target.is_null()) {// Must extract verified entry point from HotSpotNmethod after VM to Java// transition in JavaCallWrapper constructor so that it is safe with// respect to nmethod sweeping.address verified_entry_point = (address) HotSpotJVMCI::InstalledCode::entryPoint(NULL, alternative_target());if (verified_entry_point != NULL) {thread->set_jvmci_alternate_call_target(verified_entry_point);entry_point = method->adapter()->get_i2c_entry();}}
#endif// std::cout << "@@@@yym%%%%" << thread->get_thread_name() << "----begin" << std::endl;// std::cout << "@@@@yym%%%%" << method->name_and_sig_as_C_string() << "----begin" << std::endl;// method->print_on(tty);StubRoutines::call_stub()((address)&link,// (intptr_t*)&(result->_value), // see NOTE above (compiler problem)result_val_address,          // see NOTE above (compiler problem)result_type,method(),entry_point,parameter_address,args->size_of_parameters(),CHECK);result = link.result();  // circumvent MS C++ 5.0 compiler bug (result is clobbered across call)// Preserve oop return value across possible gc pointsif (oop_result_flag) {thread->set_vm_result(result->get_oop());}}} // Exit JavaCallWrapper (can block - potential return oop must be preserved)// Check if a thread stop or suspend should be executed// The following assert was not realistic.  Thread.stop can set that bit at any moment.//assert(!thread->has_special_runtime_exit_condition(), "no async. exceptions should be installed");// Restore possible oop returnif (oop_result_flag) {result->set_oop(thread->vm_result());thread->set_vm_result(NULL);}
}

##从class字节码文件流生成klass

k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);

##源码

// Add a klass to the system from a stream (called by jni_DefineClass and
// JVM_DefineClass).
// Note: class_name can be NULL. In that case we do not know the name of
// the class until we have parsed the stream.
// This function either returns an InstanceKlass or throws an exception.  It does
// not return NULL without a pending exception.
InstanceKlass* SystemDictionary::resolve_class_from_stream(ClassFileStream* st,Symbol* class_name,Handle class_loader,const ClassLoadInfo& cl_info,TRAPS) {HandleMark hm(THREAD);ClassLoaderData* loader_data = register_loader(class_loader);// Classloaders that support parallelism, e.g. bootstrap classloader,// do not acquire lock hereHandle lockObject = get_loader_lock_or_null(class_loader);ObjectLocker ol(lockObject, THREAD);// Parse the stream and create a klass.// Note that we do this even though this klass might// already be present in the SystemDictionary, otherwise we would not// throw potential ClassFormatErrors.InstanceKlass* k = NULL;#if INCLUDE_CDSif (!DumpSharedSpaces) {k = SystemDictionaryShared::lookup_from_stream(class_name,class_loader,cl_info.protection_domain(),st,CHECK_NULL);}
#endifif (k == NULL) {k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);}assert(k != NULL, "no klass created");Symbol* h_name = k->name();assert(class_name == NULL || class_name == h_name, "name mismatch");// Add class just loaded// If a class loader supports parallel classloading, handle parallel define requests.// find_or_define_instance_class may return a different InstanceKlass,// in which case the old k would be deallocatedif (is_parallelCapable(class_loader)) {k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);} else {define_instance_class(k, class_loader, THREAD);// If defining the class throws an exception register 'k' for cleanup.if (HAS_PENDING_EXCEPTION) {assert(k != NULL, "Must have an instance klass here!");loader_data->add_to_deallocate_list(k);return NULL;}}// Make sure we have an entry in the SystemDictionary on successDEBUG_ONLY(verify_dictionary_entry(h_name, k));return k;
}

##全文重点来了,java class对象生成

InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
                                                Symbol* name,
                                                ClassLoaderData* loader_data,
                                                const ClassLoadInfo& cl_info,
                                                TRAPS)

InstanceKlass* result = parser.create_instance_klass(old_stream != stream, *cl_inst_info, CHECK_NULL);InstanceKlass* result = parser.create_instance_klass(old_stream != stream, *cl_inst_info, CHECK_NULL);

java_lang_Class::create_mirror(ik,
                                 Handle(THREAD, _loader_data->class_loader()),
                                 module_handle,
                                 _protection_domain,
                                 cl_inst_info.class_data(),
                                 CHECK);

java_lang_Class::create_mirror

//创建klass实例
InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook,const ClassInstanceInfo& cl_inst_info,TRAPS) {if (_klass != NULL) {return _klass;}InstanceKlass* const ik =InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);if (is_hidden()) {mangle_hidden_class_name(ik);}fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL);assert(_klass == ik, "invariant");return ik;
}
//填充klass内存
void ClassFileParser::fill_instance_klass(InstanceKlass* ik,bool changed_by_loadhook,const ClassInstanceInfo& cl_inst_info,TRAPS) {assert(ik != NULL, "invariant");// Set name and CLD before adding to CLDik->set_class_loader_data(_loader_data);ik->set_name(_class_name);// Add all classes to our internal class loader list here,// including classes in the bootstrap (NULL) class loader.const bool publicize = !is_internal();_loader_data->add_class(ik, publicize);set_klass_to_deallocate(ik);assert(_field_info != NULL, "invariant");assert(ik->static_field_size() == _field_info->_static_field_size, "sanity");assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count,"sanity");assert(ik->is_instance_klass(), "sanity");assert(ik->size_helper() == _field_info->_instance_size, "sanity");// Fill in information already parsedik->set_should_verify_class(_need_verify);// Not yet: supers are done below to support the new subtype-checking fieldsik->set_nonstatic_field_size(_field_info->_nonstatic_field_size);ik->set_has_nonstatic_fields(_field_info->_has_nonstatic_fields);assert(_fac != NULL, "invariant");ik->set_static_oop_field_count(_fac->count[STATIC_OOP]);// this transfers ownership of a lot of arrays from// the parser onto the InstanceKlass*apply_parsed_class_metadata(ik, _java_fields_count);// can only set dynamic nest-host after static nest information is setif (cl_inst_info.dynamic_nest_host() != NULL) {ik->set_nest_host(cl_inst_info.dynamic_nest_host());}// note that is not safe to use the fields in the parser from this point onassert(NULL == _cp, "invariant");assert(NULL == _fields, "invariant");assert(NULL == _methods, "invariant");assert(NULL == _inner_classes, "invariant");assert(NULL == _nest_members, "invariant");assert(NULL == _combined_annotations, "invariant");assert(NULL == _record_components, "invariant");assert(NULL == _permitted_subclasses, "invariant");if (_has_final_method) {ik->set_has_final_method();}ik->copy_method_ordering(_method_ordering, CHECK);// The InstanceKlass::_methods_jmethod_ids cache// is managed on the assumption that the initial cache// size is equal to the number of methods in the class. If// that changes, then InstanceKlass::idnum_can_increment()// has to be changed accordingly.ik->set_initial_method_idnum(ik->methods()->length());ik->set_this_class_index(_this_class_index);if (_is_hidden) {// _this_class_index is a CONSTANT_Class entry that refers to this// hidden class itself. If this class needs to refer to its own methods// or fields, it would use a CONSTANT_MethodRef, etc, which would reference// _this_class_index. However, because this class is hidden (it's// not stored in SystemDictionary), _this_class_index cannot be resolved// with ConstantPool::klass_at_impl, which does a SystemDictionary lookup.// Therefore, we must eagerly resolve _this_class_index now.ik->constants()->klass_at_put(_this_class_index, ik);}ik->set_minor_version(_minor_version);ik->set_major_version(_major_version);ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods);if (_is_hidden) {ik->set_is_hidden();}// Set PackageEntry for this_klassoop cl = ik->class_loader();Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl));ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh());ik->set_package(cld, NULL, CHECK);const Array<Method*>* const methods = ik->methods();assert(methods != NULL, "invariant");const int methods_len = methods->length();check_methods_for_intrinsics(ik, methods);// Fill in field values obtained by parse_classfile_attributesif (_parsed_annotations->has_any_annotations()) {_parsed_annotations->apply_to(ik);}apply_parsed_class_attributes(ik);// Miranda methodsif ((_num_miranda_methods > 0) ||// if this class introduced new miranda methods or(_super_klass != NULL && _super_klass->has_miranda_methods())// super class exists and this class inherited miranda methods) {ik->set_has_miranda_methods(); // then set a flag}// Fill in information needed to compute superclasses.ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass), _transitive_interfaces, CHECK);ik->set_transitive_interfaces(_transitive_interfaces);ik->set_local_interfaces(_local_interfaces);_transitive_interfaces = NULL;_local_interfaces = NULL;// Initialize itable offset tablesklassItable::setup_itable_offset_table(ik);// Compute transitive closure of interfaces this class implements// Do final class setupOopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks;if (oop_map_blocks->_nonstatic_oop_map_count > 0) {oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps());}if (_has_contended_fields || _parsed_annotations->is_contended() ||( _super_klass != NULL && _super_klass->has_contended_annotations())) {ik->set_has_contended_annotations(true);}// Fill in has_finalizer, has_vanilla_constructor, and layout_helperset_precomputed_flags(ik);// check if this class can access its super classcheck_super_class_access(ik, CHECK);// check if this class can access its superinterfacescheck_super_interface_access(ik, CHECK);// check if this class overrides any final methodcheck_final_method_override(ik, CHECK);// reject static interface methods prior to Java 8if (ik->is_interface() && _major_version < JAVA_8_VERSION) {check_illegal_static_method(ik, CHECK);}// Obtain this_klass' module entryModuleEntry* module_entry = ik->module();assert(module_entry != NULL, "module_entry should always be set");// Obtain java.lang.ModuleHandle module_handle(THREAD, module_entry->module());// Allocate mirror and initialize static fields// The create_mirror() call will also call compute_modifiers()java_lang_Class::create_mirror(ik,Handle(THREAD, _loader_data->class_loader()),module_handle,_protection_domain,cl_inst_info.class_data(),CHECK);assert(_all_mirandas != NULL, "invariant");// Generate any default methods - default methods are public interface methods// that have a default implementation.  This is new with Java 8.if (_has_nonstatic_concrete_methods) {DefaultMethods::generate_default_methods(ik,_all_mirandas,CHECK);}// Add read edges to the unnamed modules of the bootstrap and app class loaders.if (changed_by_loadhook && !module_handle.is_null() && module_entry->is_named() &&!module_entry->has_default_read_edges()) {if (!module_entry->set_has_default_read_edges()) {// We won a potential raceJvmtiExport::add_default_read_edges(module_handle, THREAD);}}ClassLoadingService::notify_class_loaded(ik, false /* not shared class */);if (!is_internal()) {ik->print_class_load_logging(_loader_data, module_entry, _stream);if (ik->minor_version() == JAVA_PREVIEW_MINOR_VERSION &&ik->major_version() == JVM_CLASSFILE_MAJOR_VERSION &&log_is_enabled(Info, class, preview)) {ResourceMark rm;log_info(class, preview)("Loading class %s that depends on preview features (class file version %d.65535)",ik->external_name(), JVM_CLASSFILE_MAJOR_VERSION);}if (log_is_enabled(Debug, class, resolve))  {ResourceMark rm;// print out the superclass.const char * from = ik->external_name();if (ik->java_super() != NULL) {log_debug(class, resolve)("%s %s (super)",from,ik->java_super()->external_name());}// print out each of the interface classes referred to by this class.const Array<InstanceKlass*>* const local_interfaces = ik->local_interfaces();if (local_interfaces != NULL) {const int length = local_interfaces->length();for (int i = 0; i < length; i++) {const InstanceKlass* const k = local_interfaces->at(i);const char * to = k->external_name();log_debug(class, resolve)("%s %s (interface)", from, to);}}}}JFR_ONLY(INIT_ID(ik);)// If we reach here, all is well.// Now remove the InstanceKlass* from the _klass_to_deallocate field// in order for it to not be destroyed in the ClassFileParser destructor.set_klass_to_deallocate(NULL);// it's officialset_klass(ik);debug_only(ik->verify();)
}//创建java class对象
void java_lang_Class::create_mirror(Klass* k, Handle class_loader,Handle module, Handle protection_domain,Handle classData, TRAPS) {assert(k != NULL, "Use create_basic_type_mirror for primitive types");assert(k->java_mirror() == NULL, "should only assign mirror once");// Use this moment of initialization to cache modifier_flags also,// to support Class.getModifiers().  Instance classes recalculate// the cached flags after the class file is parsed, but before the// class is put into the system dictionary.int computed_modifiers = k->compute_modifier_flags();k->set_modifier_flags(computed_modifiers);// Class_klass has to be loaded because it is used to allocate// the mirror.if (vmClasses::Class_klass_loaded()) {// Allocate mirror (java.lang.Class instance)oop mirror_oop = InstanceMirrorKlass::cast(vmClasses::Class_klass())->allocate_instance(k, CHECK);Handle mirror(THREAD, mirror_oop);Handle comp_mirror;// Setup indirection from mirror->klassjava_lang_Class::set_klass(mirror(), k);InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass());assert(oop_size(mirror()) == mk->instance_size(k), "should have been set");java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror()));// It might also have a component mirror.  This mirror must already exist.if (k->is_array_klass()) {if (k->is_typeArray_klass()) {BasicType type = TypeArrayKlass::cast(k)->element_type();comp_mirror = Handle(THREAD, Universe::java_mirror(type));} else {assert(k->is_objArray_klass(), "Must be");Klass* element_klass = ObjArrayKlass::cast(k)->element_klass();assert(element_klass != NULL, "Must have an element klass");comp_mirror = Handle(THREAD, element_klass->java_mirror());}assert(comp_mirror() != NULL, "must have a mirror");// Two-way link between the array klass and its component mirror:// (array_klass) k -> mirror -> component_mirror -> array_klass -> kset_component_mirror(mirror(), comp_mirror());// See below for ordering dependencies between field array_klass in component mirror// and java_mirror in this klass.} else {assert(k->is_instance_klass(), "Must be");initialize_mirror_fields(k, mirror, protection_domain, classData, THREAD);if (HAS_PENDING_EXCEPTION) {// If any of the fields throws an exception like OOM remove the klass field// from the mirror so GC doesn't follow it after the klass has been deallocated.// This mirror looks like a primitive type, which logically it is because it// it represents no class.java_lang_Class::set_klass(mirror(), NULL);return;}}// set the classLoader field in the java_lang_Class instanceassert(class_loader() == k->class_loader(), "should be same");set_class_loader(mirror(), class_loader());// Setup indirection from klass->mirror// after any exceptions can happen during allocations.k->set_java_mirror(mirror);// Set the module field in the java_lang_Class instance.  This must be done// after the mirror is set.set_mirror_module_field(THREAD, k, mirror, module);if (comp_mirror() != NULL) {// Set after k->java_mirror() is published, because compiled code running// concurrently doesn't expect a k to have a null java_mirror.release_set_array_klass(comp_mirror(), k);}} else {assert(fixup_mirror_list() != NULL, "fixup_mirror_list not initialized");fixup_mirror_list()->push(k);}
}

##klass类添加到字典

//klass加载
void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS) {ClassLoaderData* loader_data = k->class_loader_data();assert(loader_data->class_loader() == class_loader(), "they must be the same");// Bootstrap and other parallel classloaders don't acquire a lock,// they use placeholder token.// If a parallelCapable class loader calls define_instance_class instead of// find_or_define_instance_class to get here, we have a timing// hole with systemDictionary updates and check_constraintsif (!is_parallelCapable(class_loader)) {assert(ObjectSynchronizer::current_thread_holds_lock(THREAD,get_loader_lock_or_null(class_loader)),"define called without lock");}// Check class-loading constraints. Throw exception if violation is detected.// Grabs and releases SystemDictionary_lock// The check_constraints/find_class call and update_dictionary sequence// must be "atomic" for a specific class/classloader pair so we never// define two different instanceKlasses for that class/classloader pair.// Existing classloaders will call define_instance_class with the// classloader lock held// Parallel classloaders will call find_or_define_instance_class// which will require a token to perform the define classSymbol*  name_h = k->name();Dictionary* dictionary = loader_data->dictionary();unsigned int name_hash = dictionary->compute_hash(name_h);check_constraints(name_hash, k, class_loader, true, CHECK);// Register class just loaded with class loader (placed in ArrayList)// Note we do this before updating the dictionary, as this can// fail with an OutOfMemoryError (if it does, we will *not* put this// class in the dictionary and will not update the class hierarchy).// JVMTI FollowReferences needs to find the classes this way.if (k->class_loader() != NULL) {methodHandle m(THREAD, Universe::loader_addClass_method());JavaValue result(T_VOID);JavaCallArguments args(class_loader);args.push_oop(Handle(THREAD, k->java_mirror()));JavaCalls::call(&result, m, &args, CHECK);}// Add the new class. We need recompile lock during update of CHA.{MutexLocker mu_r(THREAD, Compile_lock);// Add to class hierarchy, and do possible deoptimizations.add_to_hierarchy(k);// Add to systemDictionary - so other classes can see it.// Grabs and releases SystemDictionary_lockupdate_dictionary(name_hash, k, class_loader);}k->eager_initialize(THREAD);// notify jvmtiif (JvmtiExport::should_post_class_load()) {JvmtiExport::post_class_load(THREAD, k);}post_class_define_event(k, loader_data);
}//更新ClassLoaderData 的数据字典
// Update class loader data dictionary - done after check_constraint and add_to_hierachy
// have been called.
void SystemDictionary::update_dictionary(unsigned int hash,InstanceKlass* k,Handle class_loader) {// Compile_lock prevents systemDictionary updates during compilationsassert_locked_or_safepoint(Compile_lock);Symbol*  name  = k->name();ClassLoaderData *loader_data = class_loader_data(class_loader);{MutexLocker mu1(SystemDictionary_lock);// Make a new dictionary entry.Dictionary* dictionary = loader_data->dictionary();InstanceKlass* sd_check = dictionary->find_class(hash, name);if (sd_check == NULL) {dictionary->add_klass(hash, name, k);}SystemDictionary_lock->notify_all();}
}//klass实例添加到数据字典
// Add a loaded class to the dictionary.
// Readers of the SystemDictionary aren't always locked, so _buckets
// is volatile. The store of the next field in the constructor is
// also cast to volatile;  we do this to ensure store order is maintained
// by the compilers.void Dictionary::add_klass(unsigned int hash, Symbol* class_name,InstanceKlass* obj) {assert_locked_or_safepoint(SystemDictionary_lock);assert(obj != NULL, "adding NULL obj");assert(obj->name() == class_name, "sanity check on name");DictionaryEntry* entry = new_entry(hash, obj);int index = hash_to_index(hash);add_entry(index, entry);check_if_needs_resize();
}

##C++ new、缓冲池查找、调用jdk/internal/loader/ClassLoaders$AppClassLoader  loadClass 方法加载类的gdb堆栈

##C++ 加载OtherClass类的gdb堆栈

##jhsdb查看OtherClass在内存中值

gdb查找OtherClass的mirror class oop的值,翻译过来就是java class对象

gdb步骤

(gdb) delete

(gdb) b constantPool.cpp:516

(gdb) b SystemDictionary::find_or_define_instance_class

(gdb) n

(gdb) call k->java_mirror()

(gdb) call k->print_on(tty)

(gdb) detach

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/457307.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode动态规划(十三)-目标和

题目 494.目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 &#xff0c;在 1 之前添…

Unity(四十八):Unity与Web双向交互

效果 游戏对象绑定脚本 游戏脚本源码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Tent : MonoBehaviour {public Camera camera;// Start is called before the first frame updatevoid Start(){}// Update is called once…

鸿蒙网络编程系列36-固定包头可变包体解决TCP粘包问题

1. TCP数据传输粘包简介 在本系列的第6篇文章《鸿蒙网络编程系列6-TCP数据粘包表现及原因分析》中&#xff0c;我们演示了TCP数据粘包的表现&#xff0c;如图所示&#xff1a; 随后解释了粘包背后的可能原因&#xff0c;并给出了解决TCP传输粘包问题的两种思路&#xff0c;第一…

网络通信与并发编程(六)线程、进程池与线程池

线程、进程池与线程池 文章目录 线程、进程池与线程池一、线程二、线程的相关操作2.1创建线程的两种方式2.2线程的其他操作2.3死锁现象和递归锁2.4条件2.5定时器2.6 队列与堆栈 三、进程池与线程池 一、线程 线程是指cpu上实际执行计算的单位&#xff0c;而进程是将计算所需资…

潮畔汽车文化营地开营啦!全民测试场启动典礼圆满成功

在这个充满活力与创新的时代&#xff0c;汽车已不仅仅是代步工具&#xff0c;它承载着人们对速度、自由、科技与梦想的追求&#xff0c;成为了一种生活方式的象征。随着汽车文化的日益丰富和多元化&#xff0c;如何更好地连接汽车制造商、消费者以及广大汽车爱好者&#xff0c;…

群控系统服务端开发模式-应用开发-业务架构逻辑开发准备工作

安装与仓库已经调整完毕&#xff0c;现在开发业务架构逻辑&#xff0c;其次再开发功能逻辑。业务架构逻辑开发与功能逻辑开发不是一回事&#xff0c;一定要明白。业务架构指的是做某一件事或是某一种类型的事的逻辑&#xff0c;在互联网web应用中通常指一套系统的外在逻辑&…

Vue学习笔记(四)

事件处理 我们可以使用 v-on 指令 (通常缩写为 符号) 来监听 DOM 事件&#xff0c;并在触发事件时执行一些 JavaScript。用法为 v-on:click"methodName" 或使用快捷方式 click"methodName" 事件处理器的值可以是&#xff1a; 内联事件处理器&#xff1…

Jetpack架构组件_LiveData组件

1.LiveData初识 LiveData:ViewModel管理要展示的数据&#xff08;VM层类似于原MVP中的P层&#xff09;&#xff0c;处理业务逻辑&#xff0c;比如调用服务器的登陆接口业务。通过LiveData观察者模式&#xff0c;只要数据的值发生了改变&#xff0c;就会自动通知VIEW层&#xf…

基于Python大数据的王者荣耀战队数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

IDEA开发工具使用技巧积累

一、IDEA 工具设置默认使用maven的settings.xml文件 第一步&#xff1a;打开idea工具&#xff0c;选中 File ——> New Projects Setup ——> Settings for New Projects 第二步&#xff1a;先设置下自动构建项目这个选项 第三步&#xff1a;选中 Build Tools ——>…

windows下pycharm社区版2024下载与安装(包含新建第一个工程)

windows下pycharm社区版2024下载与安装 下载pycharm pycharm官网 安装pycharm 1.进入官网 pycharm官网 下载 点击Download–>右侧Other versions 下载对应的社区版&#xff08;如下图&#xff09;&#xff1a;下载网址 2.点击运行下载好的安装包 点击下一步 3.更改pychar…

2020款Macbook Pro A2251无法充电无法开机定位及修复

问题背景 up主有一台2020年的Macbook Pro&#xff0c;带Touch Bar&#xff0c;16G512G&#xff0c;四核I5&#xff0c;型号A2251 应该是一周没充电了&#xff0c;之前还用的好好的&#xff0c;后来有一天出差想带上 打开没电&#xff0c;手头上有个小米的66W快充头&#xff0c…

C#的自定义Tip窗体 - 开源研究系列文章

上次编写了自定义的提示和对话框窗体&#xff0c;这次记录的是自定义的Tip窗体&#xff0c;用于显示提示操作。有时间没编程了&#xff0c;这次就当进行了记录。 1、 项目目录&#xff1b; 2、 源码介绍&#xff1b; 1) 实现&#xff1b; 2) 应用&#xff1b; 3、 运行界面&…

Leetcode刷题笔记12

HJ1 字符串最后一个单词的长度 字符串最后一个单词的长度_牛客题霸_牛客网 这里可以使用rfind()&#xff0c;rfind()函数从字符串的末尾向前查找第一个空格的位置。这个空格将是最后一个单词和前面的单词的分隔符。首先使用getline读取字符串&#xff0c;然后用rfind找到最后一…

现在设备普遍切换成TYPE-C适配器后,一拖三数据线接口变革探析

随着科技的飞速发展&#xff0c;电子设备的接口标准也在不断地更新换代。近年来&#xff0c;TYPE-C接口凭借其高速传输、正反可插等显著优势&#xff0c;逐渐成为了众多电子设备的主流接口。从智能手机到平板电脑&#xff0c;从笔记本电脑到移动电源&#xff0c;TYPE-C接口的应…

Java-图书管理系统

我的个人主页 欢迎来到我的Java图书管理系统&#xff0c;接下来让我们一同探索如何书写图书管理系统吧&#xff01; 1管理端和用户端 2建立相关的三个包&#xff08;book、operation、user&#xff09; 3建立程序入口Main类 4程序运行 1.首先图书馆管理系统分为管理员端和…

TPLCM柔性屏自动化贴合应用

在当前的显示屏制造领域&#xff0c;TP&LCM贴合技术是推动产品升级和满足市场需求的关键环节。随着技术的不断进步&#xff0c;全贴合技术因其卓越的显示效果和用户体验&#xff0c;逐渐成为中高端产品的标配。然而&#xff0c;这一技术的高精度要求和复杂工艺也带来了诸多…

物联网数据采集网关详细介绍-天拓四方

一、物联网数据采集网关的概述 物联网数据采集网关&#xff0c;简称数据采集网关&#xff0c;是物联网系统中的重要组成部分&#xff0c;位于物联网设备和云端平台之间。其主要职责是实现数据的采集、汇聚、转换、传输等功能&#xff0c;确保来自不同物联网设备的数据能够统一…

学习笔记——动态路由——OSPF(距离矢量协议)OSPF路由类型

OSPF路由类型 在OSPF中&#xff0c;路由类型指的是不同种类的路由&#xff0c;用于描述网络中不同的路由信息及其传输方式。 1、Intra Area路由(区域内路由) Intra Area路由(区域内路由/本地路由/内部路由)是OSPF协议中的一种路由类型&#xff0c;用于描述在同一个OSPF区域内…

小白直接冲!一区蛇群优化算法+双向深度学习+注意力机制!SO-BiTCN-BiGRU-Attention多输入单输出回归预测

小白直接冲&#xff01;一区蛇群优化算法双向深度学习注意力机制&#xff01;SO-BiTCN-BiGRU-Attention多输入单输出回归预测 目录 小白直接冲&#xff01;一区蛇群优化算法双向深度学习注意力机制&#xff01;SO-BiTCN-BiGRU-Attention多输入单输出回归预测预测效果基本介绍程…