先聊聊jvm内存模型,在网上找到一张有直接内存的图片,方便后面讨论java
这张图真是常看常新,今天咱们从内存溢出的角度从新再审视一遍。 方法区,也称非堆,hotspot中,1.7叫perm区,1.8叫元空间,所以这个区域溢出,1.7就是OutOfMemoryError: PermGen space,1.8是OutOfMemoryError: Metaspace数组
堆溢出比较常见,OutOfMemoryError: Java heap spacebash
虚拟机栈的溢出是 StackOverflowErrorapp
本地方法栈会出现 java.lang.OutOfMemoryError : unable to create new native Threadjvm
直接内存会抛出 OutOfMemoryError: Direct buffer memoryui
如下将逐个撑爆这些空间spa
不停地递归调用,jvm不得不在虚拟机栈上分配栈帧空间,从而致使sofe,感兴趣的还能够查看一下递归的次数,可能经过-Xss进行配置,经过命令jinfo -flag ThreadStackSize [pid]能够查看栈空间大小的配置线程
public class StackOverflowErrorDemo {
private static void test() {
test();
}
public static void main(String[] args) {
test();
}
}
复制代码
先指定-Xmx8m -Xms8m,而后直接在堆中生成一个8m字节的数组,能够直接看到效果3d
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
byte[] bytes = new byte[8 * 1014 * 1024];
}
}
复制代码
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:11)code
若是是1.7,会出现PemGen space, 这要求咱们不断往生成类的信息。因为1.7,字符串常量池已经挪到堆中了,因此使用String.intern()并不会致使perm区溢出
public class OOMDemo {
public static void main(String[] args) {
String str = "hello";
List<String> list = Lists.newArrayList();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
str += (i + "").intern();
list.add(str);
}
}
}
复制代码
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448) at java.lang.StringBuilder.append(StringBuilder.java:136) at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:18)
那要怎么作呢,这里咱们须要动态地生成一些类,直到把perm区撑爆,jvm参数配置:-XX:MaxPermSize=8m
static class OOMTest{}
public static void main(final String[] args) {
int i = 0;
try {
for (; ; ) {
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, args);
}
});
enhancer.create();
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
复制代码
Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) ... 8 more
将jdk改成1.8,-XX:MaxMetaspaceSize=20m 从新执行上述程序,结果变成Metaspace溢出
java.lang.OutOfMemoryError: Metaspace at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345) at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492) at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305) at com.meituan.waimai.jvm.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:36)
配置jvm参数,-XX:MaxDirectMemorySize=8m,而后分配9m的直接内存:
public class DirectMemoryDemo {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(9 * 1024 * 1024);
}
}
复制代码
能够看到
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory at java.nio.Bits.reserveMemory(Bits.java:694) at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) at com.meituan.waimai.jvm.DirectMemoryDemo.main(DirectMemoryDemo.java:13)
不停地建立java线程,就能够把本地方法栈撑爆
public class NativeThreadDemo {
public static void main(String[] args) {
for (; ; ) {
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
复制代码
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:717) at com.meituan.waimai.jvm.NativeThreadDemo.main(NativeThreadDemo.java:21)
这个程序跑完忘了关,结果一会mac重启了,很是可怕。。。。 关于unable to create new native Thread,知乎上有个很是深入地讨论 www.zhihu.com/question/64…