- 内存溢出:程序无法申请到可用的内存
- 内存泄漏:程序占用的内存无法释放
JVM参数中,设置堆内存大小:
- -Xms 最小堆内存
- -Xmx 最大堆内存
- 堆中创建了太多对象来不及被GC回收掉时,程序还在继续申请内存,创建对象时,就会出现OutOfMemoryError
- 可以通过把堆内存设置的很小,然后创建一个大对象直到把堆内存撑爆模拟
/**
* 模拟堆内存溢出
*/
public class OutOfMemoryTest {
public static void main(String[] args) {
List<User> list = new ArrayList<>();
//- 循环创建的实例对象被list引用,所以无法被GC回收
for(int i =0;;i++){
System.out.println("轮次:" + i);
list.add(new User(UUID.randomUUID().toString()));
}
}
public static class User {
private String id;
public User(String id){
this.id = id;
}
public String getId() {
return id;
}
}
}
设置线程栈内存小:
- -Xss 一个线程堆栈的最大内存容量,可以容纳很多栈帧,设置太大时,系统创建的线程就有限,设置过小时,方法调用过深时会出现栈内存溢出(StackOverflowError),不同于堆内存中存储很多实例,栈中存的引用地址居多(JDK7后默认开启逃逸分析,JIT即时编译优化后,也会在栈内存上创建实例对象,这样明显减少了堆中的GC次数),还有局部变量等,所以占用空间相对小很多,除非调用链很深很深,或者死循环这种,超过了可用栈深度。
/**
* 模拟栈内存溢出
*/
public class StackOverflowTest {
private static int count = 0;
public static void main(String[] args) {
test();
}
/**
* 递归调用自己,直到栈溢出
*/
public static void test(){
System.out.println(String.format("调用深度:%d,id:%s", count, UUID.randomUUID().toString()));
count++;
test();
}
}
阅读参考:对象并不一定都在堆内存上分配,https://blog.csdn.net/w372426096/article/details/80333657