哪些区域会出现内存溢出,会有什么现象?
内存溢出指的是内存中某一块区域的使用量超过了允许使用的最大值,从而使用内存时因空间不足而失败,虚拟机一般会抛出指定的错误。
在Java虚拟机中,只有程序计数器不会出现内存溢出的情况,因为每个线程的程序计数器只保存一个固定长度的地址。
# 堆内存溢出:
堆内存溢出指的是在堆上分配的对象空间超过了堆的最大大小,从而导致的内存溢出。堆的最大大小使用-Xmx参数进行设置,如-Xmx10m代表最大堆内存大小为10m。
package q1oom;
import java.io.IOException;
import java.util.ArrayList;
//-Xmx10m
public class HeapOOM {
public static void main(String[] args) throws InterruptedException, IOException {
ArrayList<Object> objects = new ArrayList<Object>();
while (true){
objects.add(new byte[1024 * 1024 * 1]);
}
}
}
溢出之后会抛出OutOfMemoryError,并提示是Java heap Space导致的:
# 栈内存溢出:
栈内存溢出指的是所有栈帧空间的占用内存超过了最大值,最大值使用-Xss进行设置,比如-Xss256k代表所有栈帧占用内存大小加起来不能超过256k。
package q1oom;
/**
* -Xss180k 每个线程栈内存最大180k
*/
public class StackOOM {
public static void main(String[] args) {
recursion();
}
public static int count = 0;
//递归方法调用自己
public static void recursion() {
long a,b,c,d,f,g,h,i,j,k;
System.out.println(++count);
recursion();
}
}
溢出之后会抛出StackOverflowError:
# 方法区内存溢出:
方法区内存溢出指的是方法区中存放的内容比如类的元信息超过了方法区内存的最大值,JDK7及之前版本方法区使用永久代(-XX:MaxPermSize=值)来实现,JDK8及之后使用元空间(-XX:MaxMetaspaceSize=值)来实现。
package q1oom;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.jar.asm.Opcodes;
import java.io.IOException;
/**
* JDK8 -XX:MaxMetaspaceSize=20m JDK7 -XX:MaxPermSize=20m
*/
public class MethodAreaOOM extends ClassLoader {
public static void main(String[] args) throws IOException {
MethodAreaOOM demo1 = new MethodAreaOOM();
int count = 0;
while (true) {
String name = "Class" + count;
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC, name, null
, "java/lang/Object", null);
byte[] bytes = classWriter.toByteArray();
demo1.defineClass(name, bytes, 0, bytes.length);
System.out.println(++count);
}
}
}
元空间溢出:
永久代溢出:
# 直接内存溢出:
直接内存溢出指的是申请的直接内存空间大小超过了最大值,使用 -XX:MaxDirectMemorySize=值 设置最大值。
溢出之后会抛出OutOfMemoryError:
package q1oom;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* -XX:MaxDirectMemorySize=50m
*/
public class DirectOOM {
public static int size = 1024 * 1024 * 100; //100mb
public static List<ByteBuffer> list = new ArrayList<ByteBuffer>();
public static int count = 0;
public static void main(String[] args) throws IOException, InterruptedException {
while (true) {
ByteBuffer directBuffer = ByteBuffer.allocateDirect(size);
list.add(directBuffer);
}
}
}
溢出之后出现:
# 总结:
内存溢出指的是内存中某一块区域的使用量超过了允许使用的最大值,从而使用内存时因空间不足而失败,虚拟机一般会抛出指定的错误。
堆:溢出之后会抛出OutOfMemoryError,并提示是Java heap Space导致的。
栈:溢出之后会抛出StackOverflowError。
方法区:溢出之后会抛出OutOfMemoryError,JDK7及之前提示永久代,JDK8及之后提示元空间。
直接内存:溢出之后会抛出OutOfMemoryError。