什么是内存溢出,那些区域会发生内存溢出
首先我们要知道java是如何运行一个JVM进程,如下代码
public class Demo3 {
public static void main(String[] args) {
String message = "hello world";
System.out.println(message);
}
}
如上几步,能发生OOM地方
Metaspace如何触发内存溢出呢
我们用下面参数设置Metaspace内存大小
-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=512m
固定512M,当Metaspace满了之后,就会触发FULL GC,回收的条件也比较苛刻,如这个类加载器被回收,这个类的所有对象实例都被回收等等,所以一旦Metaspace满了,未必会回收里面的很多类,一旦回收之后,还是有很多存活的类,如果继续想Metaspace加入更多的类信息,就会导致OOM
导致Metaspace的一般原因如下
虚拟机栈溢出
我们知道一个线程的虚拟机栈的内存大小是固定的,一般默认是1MB,正如我们之前讲的main()方法,就会产生一个main的栈帧,如下代码
public class Demo3 {
public static void main(String[] args) {
String message = "hello world";
System.out.println(message);
sayHello("我是肉丝");
}
public static void sayHello(String name){
System.out.println("你好,杰克"+name);
}
}
每一个方法的调用,都会在虚拟机栈中创建一个栈帧,保存对应的局部变量,但是此时我们要注意的是每一个帧栈也是要占内存的,虽然一些变量和其他的对象数据占不了太大的内存,但是实际上也是要占用的,
如果一个线程不断的调用各种方法,不停的把方法的栈帧压入虚拟机栈,就会不断的占用这个线程1MB的栈内存,最终会导致栈内存溢出
什么情况下会发生栈内存溢出呢
public static void sayHello(String name){
sayHello(name);
}
如上代码,出现这种不断递归调用,就有可能导致栈内存溢出,一般来说不会导致栈内存溢出,除非你的bug才会导致
堆内存溢出
最终就会由于堆内存实在放不下对象,导致内存溢出,JVM崩溃
一般什么场景会导致堆内存溢出呢