初探JVM(1)
一. JVM简介
1. 什么是JVM
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
2. JVM的组成
JVM 整体组成可分为以下四个部分:
a). 组成
- 类加载器(ClassLoader)
- 运行时数据区(Runtime Data Area)
- 执行引擎(Execution Engine)
- 本地库接口(Native Interface)
b). 各个组成部分的用途:
程序在执行之前先要把Java代码转换成字节码(.class文件),JVM首先需要把字节码通过一定的方式 把文件加载到内存中 ,而字节码文件是JVM的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器 将字节码翻译成底层系统指令(二进制)再交由CPU去执行,而这个过程中需要调用其他语言的接口 来实现整个程序的功能,这就是这4个主要组成部分的职责与功能。
3. jvm,jdk,jre三者关系
jdk包含了Java的运行环境jre,同时包含了Java开发工具。jvm是Java的虚拟机,也是执行Java代码最核心的部分,jvm可以保护Java代码不被破坏,他属于一种抽象类计算机,jre里面包含了jvm,即jdk也包含了jvm
二. 类加载机制
1.类加载过程
a). 装载
- 通过类加载器 将字节码文件转成字节流,然后存入运行时数据区
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在堆内存中生成代表一个类的java.lang.class对象,作为数据访问路口
b). 链接(验证->准备->解析)
- 验证: 验证类格式的完整性,语言格式的正确性,字节码的完整性等
- 准备:为静态变量分配内存,并分配默认值
-
解析:符号引用转变成了直接引用
:符号引用是以一组符号来描述所引用的目标,符号可以是任何的字面形式的字面量,只要不会出现冲突能够定位到就行。布局和内存无关。
:是指向目标的指针,偏移量或者能够直接定位的句柄。该引用是和内存中的布局有关的,并且一定加载进来的。
c). 初始化
三. 类加载器
四. 运行时数据区
运行时数据区被分成了5大区域分别是:
a). 方法区
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息/常量//静态信息/即时编译器编译后的代码等数据.虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来;
- 存放类型信息,类型的常量池,方法数据,元数据,结构方法,运行时常量池
- 方法区的生命周期是jvm虚拟机的是绑定在一起的
- 各个线程共享
- 当方法区内存不足时,会抛出OutOfMemoryError
- jdk1.7中的方法区叫Perm Space,占用的是虚拟机内存
- jdk1.8中的方法区叫Meta Space(元空间),特性:
b). 堆
堆是虚拟机启动时创建,是虚拟机所管的内存中最大的一块,Java的所有对象和数组,都会在与虚拟机的进程绑定的,所以他是线程共享的,内存不足时会抛出OutOfMemoryError
1. 栈
分为Java栈和native栈
- 线程私有
- 最小计量单位栈帧(每个方法的执行)
- 栈深度不够深抛出异常*Error (无限递归,不停的压栈,栈的深度超过虚拟机可允许的最大深度)
2. 栈帧
结构:
- 局部变量表
保存方法中定义的局部变量,以及方法参数,操作是在操作数栈完成的 - 操作数栈
以压栈和出栈的方式来操作元素 - 动态链接 符号引用变成直接引用
当在 的解析 阶段不确定时(),会在这里的方法执行中确定 - 返回地址
返回数据,如果出现异常,就会抛出 - 即时信息/附加信息
虚拟机没有定义的,如栈帧的高度以及其他信息
c). 程序计数器
每个线程都有自己的程序计数器,如果调用的是本地native方法,那么他的计数器为空,因为他在Java层面看不到了,如是Java方法,他记录的是虚拟机字节码指令的地址