JVM
1.1什么是JVM
jvm翻译就是java虚拟机,是属于jdk中的jre(java运行时环境)中的重要组成部分,正式由于有虚拟机的存在,可以让java实现一次编译到处运行。因为通俗点说代码是有hotSpot虚拟机(虚拟机不止hotSpot)来运行,每种操作系统有不同的虚拟机版本,所以开发人员只用关心的是java代码的辨析
1.2JVM内存结构
jvm内存模型有堆,栈,本地方法栈,方法区(元空间),程序计数器
- 栈内存:线程启动时,在jvm内存区域中开辟一块该线程专属的内存空间,成为栈内存
- 虚拟机栈
虚拟机栈也叫本地方法栈可暂且理解为何线程栈是一样的,java底层代码由c和c++编写,当调用底层native方法时,占用该区域
3.堆内存:java绝大部分对象实际存放的位置,比如new()出来的对象,还有spring容器管理的对象都会在此内存中,堆内存结构分布有eden区,新new出来的对象会占用该区域,还有survivor区(s0,s1)和老年代区,当内存占用满时会出现OOM内存溢出错误,具体的堆内存会在后面继续学习
4.程序计数器
程序计数器用来记录当前线程指令执行的行号,比如多线程情况下线程执行途中cpu执行权被别的线程抢占,当轮到该线程继续执行时,就会通过程序计数器记录的行号,回到之前执行的位置继续执行,下面会有详解
5.方法区:方法区也叫元空间,主要存放类信息,静态变量,常量等。
什么是栈?
栈其实可以理解为数据结构中的栈,有一大特点为FILO(FirstInLastOut)先进后出的结构,java中每个线程启动的时候就会在栈内存区域中分配一块该线程专属的内存空间给线程。因此栈也可以称为线程栈,看如下代码
public class Math {
public static final int initData = 666;
public static User user = new User();
public int compute(){//一个方法对应一个栈贞
int a = 1;
int b = 2;
int c = (a+b)*10;
return c;
}
public static void main(String[] args) {
Math math = new Math();
math.compute();
System.out.println("test");
}
}
1.2当main线程启动时,jvm给这给main线程分配一块线程专属内存区域,用来存放线程内部的局部变量等信息
1.3为了方便理解,这里使用java自带的编译命令生成class字节码指令文件
在命令窗口中输入javap -v Math.class>Math.txt
输入命令之后会在该class目录下生成一个字节码指令文件如下图
部分jvm指令
jvm指令可自行搜索jvm指令集,这里通过编译的class文件对比指令集可看到过程如下:
0: iconst_1 将int类型常量压入操作数栈
1: istore_1 把int类型的值存入局部变量即给a赋值 a = 1
2: iconst_2 将int类型常量压入栈
3: istore_2 把int类型的值存入局部变量即给b赋值 b = 1
4: iload_1 iload_1 从局部变量1中装载int类型值 (我的理解是装载到cpu寄存器,准备进行运算)
5: iload_2 iload_2 从局部变量2中装载int类型值
6: iadd iadd 执行int类型的加法(cpu执行加法运算)
7: bipush 10 bipush 将一个8位带符号整数压入栈
9: imul imul 执行int类型的乘法
10: istore_3 istore_3 将int类型值存入局部变量3即把运算结果赋值给c
11: iload_3 iload_3 从局部变量3中装载int类型值
12: ireturn 返回结果
栈帧
当线程在栈中获得内存空间之后,当线程调用方法时会在当前获得的线程内存中再生成一小块方法的内存区域,称之为栈帧,每个方法对应一个栈帧。里面有4块区域,分别是局部变量表、操作数栈、动态链接、方法出口
下期继续学习栈帧中的内容