说明
本系列为第一遍阅读的笔记,主要以摘录为主,等后面有一定经验后二刷、三刷,再根据自己经验对一些常用、常见、重点进行举例解释。
阅读目标
本次阅读主要以应付面试为主,目标是对jvm有个大概认知,知道常见面试问题中的答案及相关原理,根据读书内容整理出便于自己理解的思路及相关重点。详细目标如下:
- 内存分配和回收策略
- GC收集器
- GC算法
- 判断对象存活的方法
- 类加载器
- 类加载机制(类的加载过程)
- 类加载机制(类的初始化)
(文末列出了网络上其它主要博文)
源码下载
概要
这里有一篇整理的不错的图
原文链接
第一章
// todo
第二章
通过本章的学习,我们明白了虚拟机里面的内存是如何划分的,哪部分区域、什么样的代码和操作可能导致内存溢出异常。虽然Java有垃圾收集机制,但内存溢出异常离我们并不遥远, 本章只是讲解了各个区域出现内存溢出异常的原因。
下一章将详细讲解Java垃圾收集机制为了避免内存溢出异常的出现都做了哪些努力。
拓展阅读
通过javap反汇编字节码文件,获取jvm执行的汇编代码文件,来反推jvm执行过程,进一步理解jvm内部栈、堆工作步骤和原理
javap的基本用法
java指令集
虚拟机里面的内存是如何划分的
jvm内存模型
哪部分区域、什么样的代码和操作可能导致内存溢出异常
- 2-3:不断创建无法自动回收的对象,导致后续操作无法获得更多足够内存抛出OutOfMemoryError异常
- 2-4:栈深度超过虚拟机允许最大深度,抛出StackOverflowError异常
/** * 2-3 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * @author zzm */
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while (true) {
list.add(new OOMObject());
}
}
}
/** * 2-4 * VM Args:-Xss128k * @author zzm */
public class JavaVMStackSOF {
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}
/** * 2-5 * VM Args:-Xss2M (这时候不妨设大些) * @author zzm */
public class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable {
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
/** * 2-6 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M * @author zzm */
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
// 使用List保持着常量池引用,避免Full GC回收常量池行为
List<String> list = new ArrayList<String>();
// 10MB的PermSize在integer范围内足够产生OOM了
int i = 0;
while (true) {
list.add(String.valueOf(i++).intern());
}
}
}
/** * 2-7 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M * @author zzm */
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
public static void main(String[] args) {
String str1 = new StringBuilder("中国").append("钓鱼岛").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
} }
}
/** * 2-8 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M * @author zzm */
public class JavaMethodAreaOOM {
public static void main(String[] args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
static class OOMObject {
}
}
/** * 2-9 * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M * @author zzm */
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
参考资料
《JVM常见面试题及答案》https://blog.csdn.net/zd836614437/article/details/64126826