JVM的面试相关问题
面试中的相关问题主要是三块
1.JVM 内存区域划分
2.JVM 的类加载机制
3.JVM 的垃圾回收机制
JVM Java虚拟机
VM Virtual Machine 虚拟机,用 软件 来 模拟 硬件
传统意义上的"虚拟机" 更多指的是 VMWare, Virtual Box, Hyper-V, KVM(构造出虚拟的电脑,甚至可以在虚拟机的电脑上安装独立的操作系统)
一台计算机:
*CPU
*储存器
*输入设备
*输出设备
通过硬件来模拟软件
Java 的虚拟机,并不是虚拟电脑的所有核心硬件(一部分),也不能运行独立的操作系统,只是可以运行Java代码
JVM 更准确额说是 Java语言的"运行时环境",核心功能就是把 Java 代码,翻译成计算机可以识别的机器指令(低效的,更高效的,像C/C++/Go,编译出来的程序就是标准的 CPU 构成的指令程序)
带来的好处是,可更好的做到"跨平台"和硬件无关
Java 程序是怎么运行的?
1.编写代码,是编写了.Java文本文件
2.通过 Javac 这样的 命令行工具,把.java 编译成.class文件(字节码文件)二进制的,.java 中的每个 class 都会对应一个.class 文件,一个.java文件中可以出现多个 class(只能有一个 public)
3.通过 java 这样的命令行工具,运行对应的.class文件 java 命令行工具,对应到一个 java 进程,这个 java 进程就可以理解成一个 Java 虚拟机了(也可以叫 JVM 的进程),JVM 的进程,就会对,class 文件中的内容解释执行了
Java 代码中的"抛出异常"实在 3 这个阶段产生的
1.JVM 内存区域划分
java 程序跑起来,得到 java 进程,需要从操作系统申请一大块空间
java 进程就需要把这一大块空间,分成多个区域,分别赋予不同的功能
简化的模型
1)程序计数器
非常小的空间,只需要保存一个"地址",描述当前 java 程序需要运行的下一个字节码指令的位置
一个 java 进程中应该有几个程序计数器呢?
应该是存在多个的
线程是 cpu 调度执行的基本单位.
每个线程都得有一个程序计数器来记录
操作系统中也是有类似的设定的,会在 CPU 上专门准备一个寄存器,就会用这个寄存器,表示"下一条指令执行的地址",这个寄存器称为 EIP(计组里就会把这个概念称为"程序计数器"简称为 PC(Program Counter))
CPU 执行指令,只是"默认是循序执行的",比如遇到 if, while, for,方法调用,抛出异常....都会使指令不在按照循序执行,跳转到某个位置
线程是"并发执行",产生一个调度,一个线程,执行一段时间之后,需要调度走,后续在调度回来
保存上下文,这个线程执行过程的所有相关寄存器的值(包括了 PC)
程序计数器的值,java代码干预不了,程序计数器值,代表的要执行的指令的地址,也是在元数据区
2)元数据区(在 Java 8 之前 称为 方法区,放的是 类 对应 的指令)
元数据区的内容,Java 代码也干预不了,你的代码中写了多少类,元数据区的内容也就确定了
Java 代码中,会创建类,基于 类 创建对象,对象当然是要有内存空间来保存的,类同样也需要再内存空间中保存
java 中提出了"类对象"概念
JVM 中,通过特殊的对象,表示一个类的基本信息
*类的名字是啥
*类继承的父类是啥
*实现的接口是啥
*有啥属性(属性的名字,类型,public/private)
*有啥方法(方法的名字,参数列表,返回值,public/private)
*类静态成员
*常量
3)栈(这里的栈和数据结构中的栈是不同的概念)
数据结构的栈 -> 钱
JVM 的栈 -> 人民币
这个区域保存了方法调用关系
java 的方法保证了,当前方法执行完毕返回上一层,调用位置继续执行
这个栈也是后进先出的特点,这里的元素,有固定的说法,把 JVM 的栈中的每一个元素,称为"栈帧(frame)"
栈帧表示一次"方法调用"
1)方法的产生是哪些
2)方法中的局部变量有哪些
3)方法执行结束之后,返回值的结果
4)方法执行结束之后,跳转回的地址
4)堆
堆存放了 new 出来的对象,对象对应的内存空间在堆中,常量之前是放到元数据区的,后来放到了堆中
class Test {private int n;private static int m;public void test1() {//...}static public void test2() {//...}
}
main(){Test t = new Test();
常见误区:
内置类型在栈上
引用类型在堆上
关键是变量的形态
局部变量 => 栈
成员变量 => 堆
静态成员变量 => 元数据区