java.lang.OutOfMemoryError: java heap space
heap 空间不足,对象分配在 heap 上。
话说,为啥对象要分配在 heap 上,因为对象的大小在 compile-time 是无法确定的。
不像基本的数据类型,如 int 是 4Bytes,这些在 compile-time 就可以确定要多少空间,分配在 stack 上。
大对象分配
vm options:
-Xms8m -Xmx8m
package com.example.demo;
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
byte[] b = new byte[10 * 1024 * 1024]; // 分配 10M 的数组对象。
}
}
错误提示
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.example.demo.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:5)
java.lang.OutOfMemoryError: GC overhead limit exceeded
花费大量时间 gc ,但是回收效果差。
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
public class GCOverheadDemo {
public static void main(String[] args) {
int i = 0;
List<String> list = new ArrayList<>();
try{
while (true){
list.add(String.valueOf(++i).intern());
}
} catch(Throwable e){
System.out.println(i);
throw e;
}
}
}
java.lang.OutOfMemoryError: Direct Buffer Memory
Native Memory
类似 C 中认工 malloc/free
metaspace
NIO
Netty
jvm 可以使用的最大本地内存
本机物理内存(local memory) / 4
sun.mi(c.VM.maxDirectMemory() / 1024 / 1024 / 1024.0
测试代码
vm options:
-XX:MaxDirectMemorySize=5m
package com.example.demo;
import sun.misc.VM;
import java.nio.ByteBuffer;
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
// 可以使用的 Direct Memory 是本机物理内存的四分之一
System.out.println(VM.maxDirectMemory() / 1024 / 1024 / 1024);
ByteBuffer bb = ByteBuffer.allocateDirect(10 * 1024 * 1024);
}
}
错误信息
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.example.demo.DirectBufferMemoryDemo.main(DirectBufferMemoryDemo.java:11)
java.lang.OutOfMemoryError: unable to create new native
thread
Linux root 所用资源和默认单进程可创建线程最大数量
root 使用资源无限制。
[root@s101 ~]# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@s101 ~]# ulimit
unlimited
[root@s101 ~]# cat /proc/sys/kernel/threads-max
14368
测试代码
public class TwoManyThreads {
public static void main(String[] args) {
// unable to create new native thread
for(int i = 0;;i++){ // 一直创建线程
System.out.println("=====>" + i);
new Thread(()->{
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e){
e.printStackTrace();
}
},""+i).start();
}
}
}
错误信息
.
.
.
=====>14234
=====>14235
=====>14236
=====>14237
=====>14238
=====>14239
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.example.demo.TwoManyThreads.main(TwoManyThreads.java:14)
java.lang.OutOfMemoryError: Metaspace
- java8 metaspace
- HotSpot 虚拟机
方法区
的实现 - 使用操作系统的 Native Memory,类似 C 的内存管理方式 malloc/free ,不适用 GC。
- 存放那些东西?
1. 虚拟机加载的类
2. 静态变量
3. JIT 编译后的代码
4. 常量池
测试代码
利用 cglib 一直生成 class。
vm options:-XX:MaxMetaspaceSize=10m
package com.example.demo;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MetaspaceOOMDemo {
static class OOMTest{
}
public static void main(String[] args) {
int i = 0;
try{
while (true){
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invoke(o,args);
}
});
enhancer.create();
}
}catch(Throwable e){
System.out.println("多少个之后:" + i);
e.printStackTrace();
}
}
}