jvm是分为两部分,jdk和HotSpot,我们一般写的程序是从JDK开始启动,HotSpot源码对于jdk来说就是一个lib库,libjvm.so<br>HotSpot这个项目只有一个main方法。它位于/jdk/src/share/bin/main.c
接着会走到JLI_Launch方法,该方法会设置一系列的系统属性,关键的方法在JVMInit
LoadJavaVM方法中给ifn成员属性赋值
ifn的createVM成员赋值,JNI_CreateJavaVM
设置classPath
处理AddOption参数
Xss/Xmx/Xms在这里处理
处理启动参数
如果是-jar 启动则重写classpath
JVMInit方法中调用了ContinueInNewThread
如果通过-Xss配置了就取配置的参数,没有就取默认的参数,这个参数呢是从ifn结构体里面取得<br>我们需要找到ifn赋值的地方看看这个取出来的默认值是多少,单位是K
ifnd的GetDefaultJavaVMInitArgs属性是通过JNI_GetDefaultJavaVMInitArgs这个方法拿到的
接着又通过pthread_create创建出一个main线程,然后join阻塞住,注意,这个main线程是JVM的主线程,<br>不是程序的主线程,程序主线程在创建完JVM的主线程之后他就会阻塞,接着JVM主线程执行线程执行函数JavaMain
这里的JavaMain里面,会调用InitializeJVM进行初始化。初始化JVM完之后,还会调用LoadMainClass加载main方法
那么Threads::createVM做了哪些事情呢?
osstream_init做了输出流的赋值<br>通过defaultStream::instance赋值,<br>并且通过tty-time_stamp().update_to(1);更新了时间戳
os::init<br>在使用TLS之前进行一些OS的初始化工作
Argumentes::init_system_properties这里涉及了一些jvm的一些基本系统属性,像JVM的版本号,以及jvm的classpath路径等等
JDK_Version_init()JVM的版本号初始化,major和minor
Arguments:init_version_specific_system_properties,在知道JVM的版本号之后,更新一些系统属性
Arguments::parse<br>解析-XX:+PrintVMOptions/-XX:+IgnoreUnrecognizedVMOptions类似的参数
os::init_before_ergo
Argument::apply_ergo
set_ergonomics_flags()<br>这里会走到os::is_server_class_machine()
set_ergonomics_flags()方法再往下走<br>Arguments::set_use_compressed_oops()<br>这里会设置JVM的Flag参数取决于是否使用了压缩技术<br>接着还会调用set_use_compressed_klass_ptrs()
set_shared_spaces_flags()
ArgumentsExt::check_gc_consistency_ergo()
最终会走到check_gclog_consistency<br>检查用户设置的收集器是否冲突
Arguments::set_heap_size.根据可用的物理机器内存设置堆空间大小
初始化元空间的标志和对齐
Arguments::set_bytecode_flags(),设置字节码相关的flag标志
Arguments::set_aggressive_opts_flags
if (PauseAtStartup) {<br> os::pause();<br> }
启动JVM计时器<br>create_vm_timer.start();<br>
os::init_2,在解析完参数之后,初始化os相关模块
fast_thread_clock_init()初始化线程时钟
os::set_polling_page()分配一个页面并将其标记为可读以便安全点轮询
os::Linux::signal_sets_init():初始化信号处理<br>os::Linux::install_signal_handlers():安装操作系统信号处理器<br>
Arguments::adjust_after_os()
ThreadLocalStorage::init();TLS类似ThreadLocal<br>
pd_init(),验证下vm_page_size()
os::allocate_thread_local_storage() <br>key一旦被创建,所有线程都可以访问它,单个线程可根据自己的需要往key中填入不同的值,<br>这就相当于提供了一个同名而不通知的全局变量,一键多值
set_thread_index()
generate_code_for_get_thread()是一个空方法
ostream_init_log(),初始化输出日志相关
vm_init_globals()创建全局数据结构并在堆中创建系统类
check_ThreadShadow()
basic_types_init()验证基本数据类型所占用的字节数是否正确
eventlog_init()
mutex_init()使用了Mutex的锁初始化
chunkpool_init()内存池的初始化
PerfMemory::initialize() 初始化perfMemory
// Attach the main thread to this os thread<br> JavaThread* main_thread = new JavaThread();<br><br>将主线程附着在这个os线程上
// Initialize Java-Level synchronization subsystem<br> ObjectMonitor::Initialize() ;<br><br>初始化Java级别同步子系统
// Initialize global modules<br> jint status = init_globals();
management_init();
void bytecodes_init() {<br> Bytecodes::initialize();<br>}<br>初始化字节码指令
void classLoader_init() {<br> ClassLoader::initialize();<br>}
void codeCache_init() {<br> CodeCache::initialize();<br>}<br>初始化代码缓存空间
void VM_Version_init() {<br> VM_Version::initialize();<br><br>#ifndef PRODUCT<br> if (PrintMiscellaneous && Verbose) {<br> os::print_cpu_info(tty);<br> }<br>#endif<br>}
os_init_globals()
void stubRoutines_init1() { StubRoutines::initialize1(); }
universe_init()
Universe::initialize_heap()
interpreter_init()
invocationCounter_init()
marksweep_init()
accessFlags_init()
void templateTable_init() {<br> TemplateTable::initialize();<br>}<br>这里会初始化每条字节码指令对应的执行流
例如,_new指令对应的执行流
InterfaceSupport_init()
SharedRuntime::generate_stubs()
void universe2_init() {<br> EXCEPTION_MARK;<br> Universe::genesis(CATCH);<br>}<br>创建基本类型对应的数组oop TypeArrayKlass
void referenceProcessor_init() {<br> ReferenceProcessor::init_statics();<br>}<br>初始化统计相关的时钟
void jni_handles_init() {<br> JNIHandles::initialize();<br>}<br>给_global_handles、_weak_global_handles 赋值
void vmStructs_init() {<br> debug_only(VMStructs::init());<br>}<br>构建一些调试相关的内容,并检查是否设置正确
void vtableStubs_init() {<br> VtableStubs::initialize();<br>}<br>初始化继承相关的table
void InlineCacheBuffer_init() {<br> InlineCacheBuffer::initialize();<br>}<br>初始化方法内联缓冲区
compilerOracle_init()
compilationPolicy_init()<br>根据命令行参数确定编译策略
compileBroker_init()
VMRegImpl::set_regName()
universe_post_init():该方法做了一些预分配的工作<br>1.预分配一个空的对象数组<br>2.预分配一些Error Exception<br>3.设置静态方法用于注册finalizer
javaClasses_init()<br>计算每个类的字段偏移量,并检查它们偏移量计算是否正确,<br>这个方法必须发生于vtalbe初始化完成之后,也就是类的关系确定之后
void stubRoutines_init2() { StubRoutines::initialize2(); }
CommandLineFlags::printFlags()<br>根据名称排序,打印JVM的flag参数设置
main_thread->cache_global_variables()<br>在虚拟机完全创建出来之后应该缓存全局变量
initialize_class(vmSymbols::java_lang_String(), CHECK_0);<br>initialize_class(vmSymbols::java_lang_System(), CHECK_0);<br><br>预加载一些核心类String、System.......