JVM生命周期
此处的VM为HotSpot VM。
JVM的启动方式
启动HotSpot VM的组件是启动器。
HotSpot VM有多个启动器,常见的启动器如下:
- Unix/linux 上最常见的是java;
- windows上是java和javaw;
- 通过JNI接口JNI_CreateJavaVM启动内嵌的JVM;
- 网络启动器javaws(java Web Start),网络浏览器通过它来情动applet;
JVM的启动流程
- 解析命令行选项
- 启动器会直接处理一些命令行选项,例如-client或-server。他们决定加载那个JIT编译器,其他 参数则传给HotSpot VM
- 设置堆大小和JIT编译器
- 如果没有指定参数则使用默认参数
- 设置环境变量如LD_LIBRARY_PATH和CLASSPATH
- 如果命令行有 -jar选项,启动器则会从指定的JAR的manifest中查找MAIN-Class,否则从命令行读取Main-Class
- 使用标准java本地接口(java Native interface,JNI)方法JNI_CreateJavaVM在新创建的线程中创建HotSpot VM。
- 一旦创建并初始化好HotSpot VM ,就会加载Java Main-Class,启动器也会从java-Main-class中得到java main方法的参数。
- HotSpot VM 通过JNI方法CallStaticVoidMethod调用java main方法,并将命令行选项传给他
至此,JVM开始正式执行java程序。
JVM的销毁
一旦java程序或java main方法执行结束,执行以下操作:
- JVM就必须检查和清理所有程序或者方法执行过程中产生的未处理异常;
- 方法和程序的退出状态必须返回给它的调用者。
- 调用JNI接口的方法DetachCurrentThread将java main方法与HotSpot VM 脱离,每次调用DetachCurrentThread时,线程数就会减一,因此JNI接口知道如何关闭不JVM,并确保JVM中没有正在执行的操作,java栈中也没有激活的java桢。
附录
JNI DestroyJava 详解
- 如果JVM 启动过程中发生错误,启动器则调用DestroyJavaVM关闭JVM。
- 如果JVM启动后的执行过程霍城很严重的异常,启动器会调用DestroyJavaVM关闭JVM。
DestroyJavaVM关闭JVM的步骤如下:
- 一直等待,直到只有一个非守护的线程(当前线程)执行;
- 调用java.lang.Shutdown.shutdown(),它会调用java上的shotdown钩子方法,如果finalization-on-exit=true,则运行java对象的finalizer。
- 运行JVM上的shutdown钩子,停止以下线程:性能分析器,统计数抽样器,监控线程和GC线程。发出状态时间通知JVMTI,然后关闭JVMTI,停止信号线程。
- 调用HOTSPOT的javaThread::exit()释放JNI处理快,移除保护页并将当前线程从已知线程队列中移除。
- 停止JVM线程,并将遗留的JVM线程带到安全点并停止JIT编译器线程。
- 停止追踪JNI,JVM及JVMTI屏障。
- 为那些仍以本地代码运行的线程设置标记“vm exited”
- 删除当前线程
- 删除或移除所有的IO流,释放PerfMemory资源
- 最后返回调用者
CLC