2021-10-20 04:34:53 -04:00
|
|
|
|
# JVM简介
|
|
|
|
|
|
|
|
|
|
write once run everywhere
|
|
|
|
|
|
|
|
|
|
## jvm空间加载运行
|
|
|
|
|
|
2021-10-28 22:19:52 -04:00
|
|
|
|
参考jvm规范:https://docs.oracle.com/javase/specs/index.html
|
|
|
|
|
|
2021-10-20 04:34:53 -04:00
|
|
|
|
### 空间、运行时数据区
|
|
|
|
|
|
|
|
|
|
- 线程共享
|
|
|
|
|
- Heap堆:在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。存储数据不是线程安全的,<u>**堆和常量池**</u>空间不足时会触发OutOfMemoryError
|
|
|
|
|
- MetaSpace元数据区:在1.8之后取代Method Area 方法区永久代,不在jvm中,使用本地内存,受操作系统内存限制。存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
|
|
|
|
|
- 线程隔离
|
|
|
|
|
- VM Stack虚拟机栈:每个线程创建一个单独的运行时堆栈。对于每一个方法调用,一个称为栈内存栈帧被创建。所有局部变量将被创建在栈内存中。栈区域时线程安全的,因为他不是一个共享资源。
|
|
|
|
|
- Navive Method Stack本地方法栈:与虚拟机所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
|
|
|
|
|
- Program Counter Register 程序计数器:每个线程必须分开程序计数器登记,当前执行的指令一旦被执行,程序计数器更新下一个指令。一块较小的内存空间。他的作用可以看做是当前线程所执行的字节码的行号指示器。
|
|
|
|
|
|
|
|
|
|
### 加载
|
|
|
|
|
|
|
|
|
|
- 类加载器
|
|
|
|
|
- Bootstrap:加载环境变量中$JAVA_HOME/jre/lib/rt.jar里所有的class,不是ClassLoader子类。
|
|
|
|
|
- Extension:加载java平台中扩展功能的一些jar包。包括环境变量中$JAVA_HOME/jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
|
|
|
|
|
- Application:加载classpath中指定的jar包及目录中class。
|
|
|
|
|
- Custom自定义:应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行是实现ClassLoader
|
|
|
|
|
|
|
|
|
|
### 链接
|
|
|
|
|
|
|
|
|
|
- 验证:字节码校验器会检查生成的字节码是否正确,如果验证失败会停止运行
|
|
|
|
|
- 准备:对于所有静态变量内存分配和默认值分配
|
|
|
|
|
- 识别:解析或识别是从运行时常量池的符号引用中动态具体的过程。
|
|
|
|
|
|
|
|
|
|
### 初始化
|
|
|
|
|
|
|
|
|
|
- 类或接口的初始化由执行类或接口初始化方法构成,这里所有的静态变量与原来的值将被指派,静态块将被执行。
|
|
|
|
|
|
|
|
|
|
## 内存空间分配
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
## 垃圾收集器
|
|
|
|
|
|
|
|
|
|
- 并行parallel:多个垃圾收集线程并行工作,此时用户线程处于等待状态。
|
|
|
|
|
- 并发concurrent:用户线程和垃圾收集线程同时执行。
|
|
|
|
|
- 吞吐量:用户代码执行时间/(用户代码执行时间+垃圾收集时间)
|