主题
面试速答(先看这里)
**一句话结论:**Java堆用于存储对象实例。
60秒标准回答:
Java堆用于存储对象实例。堆溢出通常是由于创建了太多对象,而没有足够的堆内存来存储这些对象
我们只需要写一个死循环, 在里面不断地创建对象就行了。一直运行下去,就会导致OOM
Java栈用于存储局部变量和方法调用。栈溢出通常是因为过深的方法调用,如递归调用没有正确的终止条件
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**我们只需要写一个死循环, 在里面不断地创建对象就行了。
- **要点2:**Java栈用于存储局部变量和方法调用。
- **要点3:**元空间用于存储类的元数据。
- **要点4:**对于元空间溢出的示例,需要使用javassist这个第三方库来动态创建类。
**记忆锚点:**Java → javassist → 请分别写出一个Java堆 → 是由于创建了太多对象 → 堆内存来存储这些对象 → 在里面不断地创建对象
加分表达:
- 你可以通过 Maven 将 javassist 添加到项目依赖中。
追问准备:
- 围绕「Java」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「javassist」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「请分别写出一个Java堆」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
Java堆溢出
Java堆用于存储对象实例。堆溢出通常是由于创建了太多对象,而没有足够的堆内存来存储这些对象。
我们只需要写一个死循环, 在里面不断地创建对象就行了。一直运行下去,就会导致OOM
latex
import java.util.ArrayList;
import java.util.List;
public class HeapOverflow {
public static void main(String[] args) {
List<Object> objects = new ArrayList<>();
while (true) {
objects.add(new Object()); // 不断创建对象并保留引用
}
}
}Java 栈溢出
Java栈用于存储局部变量和方法调用。栈溢出通常是因为过深的方法调用,如递归调用没有正确的终止条件。
latex
public class StackOverflow {
public static void main(String[] args) {
recursiveMethod(1); // 递归调用,没有终止条件
}
private static void recursiveMethod(int i) {
recursiveMethod(i);
}
}元空间溢出
元空间用于存储类的元数据。元空间溢出通常是由于加载了太多类或者类的元数据过大。
latex
import javassist.ClassPool;
public class MetaspaceOverflow {
public static void main(String[] args) {
ClassPool classPool = ClassPool.getDefault();
for (int i = 0; ; i++) {
classPool.makeClass("Class" + i).toClass(); // 动态创建大量的类
}
}
}对于元空间溢出的示例,需要使用javassist这个第三方库来动态创建类。你可以通过 Maven 将 javassist 添加到项目依赖中。