01 JVM 与 Java 基础
这一块在面试里是干什么的
主要用来判断:
- 你是不是只会写业务代码
- 你对 Java 运行机制是否有基本理解
- 出线上问题时能不能定位方向
先记住这几个关键词
- JDK:开发工具包,包含
javac、java等工具 - JRE:运行 Java 程序需要的环境
- JVM:真正执行 Java 字节码的虚拟机
一句话:
“Java 代码先编译成字节码,再由 JVM 执行。”
Java 为什么跨平台
因为 Java 编译后的产物是字节码,不直接依赖操作系统。
不同平台只要有对应的 JVM,就能执行同一份字节码。
== 和 equals
==:比较地址,基本类型时比较值equals:比较内容,默认还是比较地址,很多类比如String重写后比较值
面试回答:
“== 更偏向判断是不是同一个对象,equals 更偏向判断内容是否相等。”
String 为什么不可变
原因:
- 线程安全
- 可以缓存 hash
- 适合作为 map key
- 字符串常量池可以复用对象
常见追问:
StringBuilder:可变,单线程快StringBuffer:可变,方法带同步
集合先记最常问的
ArrayList 和 LinkedList
ArrayList:基于数组,查询快,插入删除慢LinkedList:基于链表,插入删除相对方便,查询慢
大部分业务场景优先用 ArrayList。
HashMap 和 ConcurrentHashMap
HashMap:线程不安全ConcurrentHashMap:线程安全,适合并发场景
面向对象先会说什么
四大特性:
- 封装
- 继承
- 多态
- 抽象
最容易被问的是多态。
一句话:
“父类引用指向子类对象,运行时调用子类实现,这就是多态。”
JVM 内存区域
先记主干,不要一开始背太细:
- 堆:放对象实例,是垃圾回收主战场
- 栈:放局部变量、方法调用信息
- 方法区:放类信息、常量、静态变量等
- 程序计数器:记录当前线程执行到哪里
常见高频题:
对象主要放哪
一般放在堆里。
局部变量放哪
一般在线程栈里。
什么是垃圾回收
JVM 自动回收不再使用的对象,减少手动释放内存的成本。
如何判断对象是否可回收
主流答案是“可达性分析”。
一句话:
“如果一个对象从 GC Roots 出发不可达,就可以认为它可以被回收。”
常见 GC
短期先知道名字和特点:
- Serial:单线程,简单
- Parallel:吞吐量优先
- CMS:低停顿,已逐渐淡出
- G1:现在最常见,兼顾吞吐和停顿
高频面试一句话:
“G1 把堆划分成多个 Region,目标是在可控停顿时间下完成回收。”
什么是 OOM
Out Of Memory,内存溢出。
常见原因:
- 堆内存不够
- 内存泄漏
- 大对象太多
- 无限创建对象
什么是内存泄漏
对象已经没用了,但仍然被引用,导致 GC 无法回收。
final、finally、finalize
final:关键字,修饰类/方法/变量finally:异常处理里一定会执行的代码块finalize:对象回收前的方法,已不推荐依赖
异常体系
Exception:可处理异常RuntimeException:运行时异常,可以不显式捕获Error:严重错误,应用一般不处理
高频题:
throw 和 throws
throw:真的抛出异常throws:声明这个方法可能抛出异常
高频快答
重载和重写
- 重载:同一个类中,方法名相同,参数不同
- 重写:子类重写父类方法
HashMap 为什么快
通过 hash 定位桶,再在桶内查找,平均时间复杂度接近 O(1)。
ArrayList 默认扩容
面试不用背死数值,记住“底层是动态数组,容量不够会扩容并拷贝旧数据”即可。
这一章最小记忆包
- Java 跨平台靠字节码 + JVM
==比地址,equals比内容String不可变- 对象一般在堆,局部变量一般在栈
- GC 通过可达性分析判断是否回收
- G1 是当前常见垃圾回收器
- OOM 是内存溢出,内存泄漏是对象没用但回收不了