JVM 虚拟机创建
进入vm/runtime/thread.cpp文件的第3317行,查看主要方法Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain),源码如下:
3317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713 | jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { extern void JDK_Version_init(); // Preinitialize version info. VM_Version::early_initialize(); // Check version if (!is_supported_jni_version(args->version)) return JNI_EVERSION; // Initialize the output stream module ostream_init(); // Process java launcher properties. Arguments::process_sun_java_launcher_properties(args); // Initialize the os module before using TLS os::init(); // Initialize system properties. Arguments::init_system_properties(); // So that JDK version can be used as a discrimintor when parsing arguments JDK_Version_init(); // Update/Initialize System properties after JDK version number is known Arguments::init_version_specific_system_properties(); // Parse arguments // Note: this internally calls os::init_container_support() jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; os::init_before_ergo(); jint ergo_result = Arguments::apply_ergo(); if (ergo_result != JNI_OK) return ergo_result; if (PauseAtStartup) { os::pause(); } HS_DTRACE_PROBE(hotspot, vm__init__begin); HOTSPOT_VM_INIT_BEGIN(); // Record VM creation timing statistics TraceVmCreationTime create_vm_timer; create_vm_timer.start(); // Timing (must come after argument parsing) TraceTime timer("Create VM", TraceStartupTime); // Initialize the os module after parsing the args jint os_init_2_result = os::init_2(); if (os_init_2_result != JNI_OK) return os_init_2_result; jint adjust_after_os_result = Arguments::adjust_after_os(); if (adjust_after_os_result != JNI_OK) return adjust_after_os_result; // intialize TLS ThreadLocalStorage::init(); // Initialize output stream logging ostream_init_log(); // Convert -Xrun to -agentlib: if there is no JVM_OnLoad // Must be before create_vm_init_agents() if (Arguments::init_libraries_at_startup()) { convert_vm_init_libraries_to_agents(); } // Launch -agentlib/-agentpath and converted -Xrun agents if (Arguments::init_agents_at_startup()) { create_vm_init_agents(); } // Initialize Threads state _thread_list = NULL; _number_of_threads = 0; _number_of_non_daemon_threads = 0; // Initialize global data structures and create system classes in heap vm_init_globals(); // Attach the main thread to this os thread JavaThread* main_thread = new JavaThread(); main_thread->set_thread_state(_thread_in_vm); // must do this before set_active_handles and initialize_thread_local_storage // Note: on solaris initialize_thread_local_storage() will (indirectly) // change the stack size recorded here to one based on the java thread // stacksize. This adjusted size is what is used to figure the placement // of the guard pages. main_thread->record_stack_base_and_size(); main_thread->initialize_thread_local_storage(); main_thread->set_active_handles(JNIHandleBlock::allocate_block()); if (!main_thread->set_as_starting_thread()) { vm_shutdown_during_initialization( "Failed necessary internal allocation. Out of swap space"); delete main_thread; *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again return JNI_ENOMEM; } // Enable guard page *after* os::create_main_thread(), otherwise it would // crash Linux VM, see notes in os_linux.cpp. main_thread->create_stack_guard_pages(); // Initialize Java-Level synchronization subsystem ObjectMonitor::Initialize() ; // Initialize global modules jint status = init_globals(); if (status != JNI_OK) { delete main_thread; *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again return status; } // Should be done after the heap is fully created main_thread->cache_global_variables(); HandleMark hm; { MutexLocker mu(Threads_lock); Threads::add(main_thread); } // Any JVMTI raw monitors entered in onload will transition into // real raw monitor. VM is setup enough here for raw monitor enter. JvmtiExport::transition_pending_onload_raw_monitors(); // Create the VMThread { TraceTime timer("Start VMThread", TraceStartupTime); VMThread::create(); Thread* vmthread = VMThread::vm_thread(); if (!os::create_thread(vmthread, os::vm_thread)) vm_exit_during_initialization("Cannot create VM thread. Out of system resources."); // Wait for the VM thread to become ready, and VMThread::run to initialize // Monitors can have spurious returns, must always check another state flag { MutexLocker ml(Notify_lock); os::start_thread(vmthread); while (vmthread->active_handles() == NULL) { Notify_lock->wait(); } } } assert (Universe::is_fully_initialized(), "not initialized"); if (VerifyDuringStartup) { // Make sure we're starting with a clean slate. VM_Verify verify_op; VMThread::execute(&verify_op); } EXCEPTION_MARK; // At this point, the Universe is initialized, but we have not executed // any byte code. Now is a good time (the only time) to dump out the // internal state of the JVM for sharing. if (DumpSharedSpaces) { MetaspaceShared::preload_and_dump(CHECK_0); ShouldNotReachHere(); } // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::enter_start_phase(); // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents. JvmtiExport::post_vm_start(); { TraceTime timer("Initialize java.lang classes", TraceStartupTime); if (EagerXrunInit && Arguments::init_libraries_at_startup()) { create_vm_init_libraries(); } initialize_class(vmSymbols::java_lang_String(), CHECK_0); // Initialize java_lang.System (needed before creating the thread) initialize_class(vmSymbols::java_lang_System(), CHECK_0); initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0); Handle thread_group = create_initial_thread_group(CHECK_0); Universe::set_main_thread_group(thread_group()); initialize_class(vmSymbols::java_lang_Thread(), CHECK_0); oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0); main_thread->set_threadObj(thread_object); // Set thread status to running since main thread has // been started and running. java_lang_Thread::set_thread_status(thread_object, java_lang_Thread::RUNNABLE); // The VM creates & returns objects of this class. Make sure it's initialized. initialize_class(vmSymbols::java_lang_Class(), CHECK_0); // The VM preresolves methods to these classes. Make sure that they get initialized initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0); initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0); call_initializeSystemClass(CHECK_0); // get the Java runtime name after java.lang.System is initialized JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); JDK_Version::set_runtime_version(get_java_runtime_version(THREAD)); // an instance of OutOfMemory exception has been allocated earlier initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0); initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0); initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0); initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0); initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); } // See : bugid 4211085. // Background : the static initializer of java.lang.Compiler tries to read // property"java.compiler" and read & write property "java.vm.info". // When a security manager is installed through the command line // option "-Djava.security.manager", the above properties are not // readable and the static initializer for java.lang.Compiler fails // resulting in a NoClassDefFoundError. This can happen in any // user code which calls methods in java.lang.Compiler. // Hack : the hack is to pre-load and initialize this class, so that only // system domains are on the stack when the properties are read. // Currently even the AWT code has calls to methods in java.lang.Compiler. // On the classic VM, java.lang.Compiler is loaded very early to load the JIT. // Future Fix : the best fix is to grant everyone permissions to read "java.compiler" and // read and write"java.vm.info" in the default policy file. See bugid 4211383 // Once that is done, we should remove this hack. initialize_class(vmSymbols::java_lang_Compiler(), CHECK_0); // More hackery - the static initializer of java.lang.Compiler adds the string "nojit" to // the java.vm.info property if no jit gets loaded through java.lang.Compiler (the hotspot // compiler does not get loaded through java.lang.Compiler). "java -version" with the // hotspot vm says "nojit" all the time which is confusing. So, we reset it here. // This should also be taken out as soon as 4211383 gets fixed. reset_vm_info_property(CHECK_0); quicken_jni_functions(); // Must be run after init_ft which initializes ft_enabled if (TRACE_INITIALIZE() != JNI_OK) { vm_exit_during_initialization("Failed to initialize tracing backend"); } // Set flag that basic initialization has completed. Used by exceptions and various // debug stuff, that does not work until all basic classes have been initialized. set_init_completed(); Metaspace::post_initialize(); HS_DTRACE_PROBE(hotspot, vm__init__end); HOTSPOT_VM_INIT_END(); // record VM initialization completion time Management::record_vm_init_completed(); // Compute system loader. Note that this has to occur after set_init_completed, since // valid exceptions may be thrown in the process. // Note that we do not use CHECK_0 here since we are inside an EXCEPTION_MARK and // set_init_completed has just been called, causing exceptions not to be shortcut // anymore. We call vm_exit_during_initialization directly instead. SystemDictionary::compute_java_system_loader(THREAD); if (HAS_PENDING_EXCEPTION) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } // Support for ConcurrentMarkSweep. This should be cleaned up // and better encapsulated. The ugly nested if test would go away // once things are properly refactored. XXX YSR if (UseConcMarkSweepGC || UseG1GC) { if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::makeSurrogateLockerThread(THREAD); } else { ConcurrentMarkThread::makeSurrogateLockerThread(THREAD); } if (HAS_PENDING_EXCEPTION) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } } // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::enter_live_phase(); // Signal Dispatcher needs to be started before VMInit event is posted os::signal_init(); // Start Attach Listener if +StartAttachListener or it can't be started lazily if (!DisableAttachMechanism) { AttachListener::vm_start(); if (StartAttachListener || AttachListener::init_at_startup()) { AttachListener::init(); } } // Launch -Xrun agents // Must be done in the JVMTI live phase so that for backward compatibility the JDWP // back-end can launch with -Xdebug -Xrunjdwp. if (!EagerXrunInit && Arguments::init_libraries_at_startup()) { create_vm_init_libraries(); } // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); if (TRACE_START() != JNI_OK) { vm_exit_during_initialization("Failed to start tracing backend."); } if (CleanChunkPoolAsync) { Chunk::start_chunk_pool_cleaner_task(); } // initialize compiler(s) CompileBroker::compilation_init(); if (EnableInvokeDynamic) { // Pre-initialize some JSR292 core classes to avoid deadlock during class loading. // It is done after compilers are initialized, because otherwise compilations of // signature polymorphic MH intrinsics can be missed // (see SystemDictionary::find_method_handle_intrinsic). initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK_0); initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK_0); initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK_0); } Management::initialize(THREAD); if (HAS_PENDING_EXCEPTION) { // management agent fails to start possibly due to // configuration problem and is responsible for printing // stack trace if appropriate. Simply exit VM. vm_exit(1); } if (Arguments::has_profile()) FlatProfiler::engage(main_thread, true); if (MemProfiling) MemProfiler::engage(); StatSampler::engage(); if (CheckJNICalls) JniPeriodicChecker::engage(); BiasedLocking::init(); RTMLockingCounters::init(); if (JDK_Version::current().post_vm_init_hook_enabled()) { call_postVMInitHook(THREAD); // The Java side of PostVMInitHook.run must deal with all // exceptions and provide means of diagnosis. if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } } { MutexLockerEx ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); // Make sure the watcher thread can be started by WatcherThread::start() // or by dynamic enrollment. WatcherThread::make_startable(); // Start up the WatcherThread if there are any periodic tasks // NOTE: All PeriodicTasks should be registered by now. If they // aren't, late joiners might appear to start slowly (we might // take a while to process their first tick). if (PeriodicTask::num_tasks() > 0) { WatcherThread::start(); } } create_vm_timer.end(); _vm_complete = true; return JNI_OK;} |