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 出来的对象,对象对应的内存空间在堆中,常量之前是放到元数据区的,后来放到了堆中

java 复制代码
class Test {
    private int n;
    private static int m;
    
    public void test1() {
        //...
    }
    
    static public void test2() {
        //...
    }
}
main(){
    Test t = new Test();

常见误区:

内置类型在栈上

引用类型在堆上

关键是变量的形态

局部变量 => 栈

成员变量 => 堆

静态成员变量 => 元数据区

相关推荐
YuTaoShao36 分钟前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
麦兜*7 小时前
Spring Boot启动优化7板斧(延迟初始化、组件扫描精准打击、JVM参数调优):砍掉70%启动时间的魔鬼实践
java·jvm·spring boot·后端·spring·spring cloud·系统架构
天涯学馆9 小时前
前端开发也能用 WebAssembly?这些场景超实用!
前端·javascript·面试
desssq11 小时前
力扣:70. 爬楼梯
算法·leetcode·职场和发展
然我12 小时前
别再只用 base64!HTML5 的 Blob 才是二进制处理的王者,面试常考
前端·面试·html
莫空000012 小时前
深入理解JavaScript的Reflect API:从原理到实践
前端·面试
磊叔的技术博客13 小时前
LLM 系列(六):模型推理篇
人工智能·面试·llm
岁忧13 小时前
(LeetCode 面试经典 150 题 ) 58. 最后一个单词的长度 (字符串)
java·c++·算法·leetcode·面试·go
jingling55516 小时前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
莫空000016 小时前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试