JVM是什么?出现背景?
- JVM(Java Virtual Machine)Java虚拟机,他是一个运行在操作系统上的进程,用来运行Java代码(实际上是.class文件中的字节码)。
- 出现背景:java语言是为了一次编写,到处运行的目的而出现的,也就是说java代码可以跨平台运行,这个目的是由JVM来达到的。
Java代码为什么能跨平台运行?
- 先看Java代码的执行过程:
- 我们编写.java文件通过javac(java代码编译器)被编译成.class文件
- jvm将.class文件加载到jvm内存中,再由jvm中不同平台的解释器将.class文件翻译成对应平台的机器指令,从而执行机器指令
可以看到,对于不同平台,由各平台实现的解释器来屏蔽各平台的差异,从而达到不同平台能运行同样的class字节码的目的
JVM内存布局和类加载机制
上文中提到jvm会将.class文件加载到内存中,这个过程不是简单的读取文件字节流到内存中,而是按照.class文件的结构解析其中的各种元数据将其加载到jvm中不同的内存区域中去,下面将详细介绍其中的解析过程(类加载过程)和各个内存区域
- JVM内存布局
jvm内存主要分为线程私有和线程共享两类,还有一种是本地内存- 线程私有
- jvm栈
存放方法调用的相关数据,由一个个栈帧构成,栈帧包含局部变量表(存放方法参数和方法内定义的局部变量)、操作数栈(方法执行期间会从局部变量表或对象的字段中复制常量或变量到操作数栈中)、动态链接(栈帧中存在一个指向运行时常量池中该栈帧所属方法的符号引用,方法调用时要将该符号引用替换为其所在内存地址的直接引用,这种转化称为动态链接)、方法返回地址(方法退出后需要返回的位置,在该位置继续执行后续代码);每一个方法的调用对应着一个栈帧的压栈,出栈。 - 本地方法栈
和jvm栈类似,只不过是本地方法调用时使用。hotspot虚拟机将两个栈合为一个栈 - 程序计数器
指向jvm正在执行的代码
- jvm栈
- 线程共享
- java堆
存放新建的java对象,是垃圾回收器主要的工作区域;jdk7和jdk8,类的静态变量(和类的Class对象在一块)和字符串常量池也存放在java堆中 - 方法区(jdk8属于元空间,内存区域在jvm外。jdk7属于永久代)
- 类的元数据
类、属性、方法等元数据 - JIT代码缓存
JIT会把部分“热点代码”编译成本地机器相关的机器码,并进行优化,然后再把编译后的机器码缓存起来,以备下次使用 - 运行时常量池
存放类加载时产生的各种字面量和符号引用
- 类的元数据
- java堆
- 本地内存
- java8的元空间
存放类的元数据 - DirectByteBuffer这个类
开辟直接内存避免在java堆中来回复制数据
- java8的元空间
- 线程私有
- JVM类加载机制
- 加载
- 通过类的全限定名获得类的字节流
- 按照虚拟机规范将类的元数据结构放入方法区
- 生成一个该类的class实例放入java堆
- 连接
- 验证
- 验证class是否满足虚拟机要求
- 准备
- 初始化类变量内存空间(final修饰的变量这时会直接赋值)
- 解析
- 将符号引用替换为直接引用
- 验证
- 初始化
- 收集静态变量赋值和静态代码块中的语句生成类构造器方法
- 加载