java中出现OOM情况总结
前言除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能。Java Heap 溢出
·
文章目录
前言
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能。以下代码测试环境为JDK 1.8。
Java Heap 溢出
Java heap space
// -Xmx8m
public class TestOomTooManyObject {
public static void main(String[] args) {
String name = "hello";
for (int i = 0; i < 10000000; i++) {
name += name;
}
System.out.println(name);
}
}
输出结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.String.<init>(String.java:207)
at java.lang.StringBuilder.toString(StringBuilder.java:407)
at com.fast.summary.jvm.oom.TestOomTooManyObject.main(TestOomTooManyObject.java:12)
Metaspace
// -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=10m
// 模拟不断生成类, 但类无法卸载的情况
public class TestOomTooManyClass {
static String base = "string";
public static void main(String[] args) {
testDynamicCreateClass();
}
private static void testDynamicCreateClass() {
AtomicInteger c = new AtomicInteger();
while (true) {
try (FileReader reader = new FileReader("script")) {
GroovyShell shell = new GroovyShell();
shell.evaluate(reader);
System.out.println(c.incrementAndGet());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出结果:
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.codehaus.groovy.util.SingleKeyHashMap.getOrPut(SingleKeyHashMap.java:67)
at org.codehaus.groovy.runtime.metaclass.MetaMethodIndex.<init>(MetaMethodIndex.java:85)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:193)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:221)
at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:233)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:166)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:156)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:139)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:133)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:86)
at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:37)
at org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:88)
at groovy.lang.GroovyObjectSupport.getDefaultMetaClass(GroovyObjectSupport.java:46)
at groovy.lang.GroovyObjectSupport.<init>(GroovyObjectSupport.java:32)
at groovy.lang.Binding.<init>(Binding.java:33)
at groovy.lang.GroovyShell.<init>(GroovyShell.java:63)
at com.fast.summary.jvm.oom.TestOomTooManyClass.testDynamicCreateClass(TestOomTooManyClass.java:21)
at com.fast.summary.jvm.oom.TestOomTooManyClass.main(TestOomTooManyClass.java:14)
Direct buffer memory
// -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
public class TestOomDirectBufferMemory {
public static void main(String[] args) {
System.out.println("查看配置的本地内存maxDirectMemory:" + (sun.misc.VM.maxDirectMemory() / (double) 1024 / 1024) + "MB");
//停顿一下方便看效果
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//-XX:MaxDirectMemorySize=5m 本地内存配置的是5MB,这里实际使用的是6MB
ByteBuffer bb = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
StackOverflowError
/**
* StackOverflowError :栈溢出
* 什么时候会让 Java Method Stack 栈溢出啊?
* 栈的基本特点就是 FILO(First In Last Out),
* 如果 in 的太多而 out 的太少,就好 overflow 了。
* 而 Java Method Stack 的功能就是保存每一次函数调用时的“现场”,
* 即为入栈,函数返回就对应着出栈,所以函数调用的深度越大,栈就变得越大,足够大的时候就会溢出。
* 所以模拟 Java Method Stack 溢出,只要不断递归调用某一函数就可以。
* @author qinfuxiang
*/
public class TestStackOverflowError {
private static int stackLength = 0;
public void stackOverflow() {
++stackLength;
stackOverflow();
}
public static void main(String[] args) {
TestStackOverflowError test = new TestStackOverflowError();
try {
test.stackOverflow();
} catch (Throwable e) {
System.out.println("stack length: " + test.stackLength);
throw e;
}
}
}
运行结果:
Exception in thread "main" java.lang.StackOverflowError
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
at com.fast.summary.jvm.oom.TestStackOverflowError.stackOverflow(TestStackOverflowError.java:18)
Executors 默认的几种会出现OOM
newFixedThreadPool
- LinkedBlockingQueue为无界队列
// -Xmx8m
private static void fixedThreadPool() {
ExecutorService executor = Executors.newFixedThreadPool(2);
LoggerUtils.get().debug("begin...");
while (true) {
executor.submit(() -> {
try {
LoggerUtils.get().debug("send sms...");
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.concurrent.Executors.callable(Executors.java:407)
at java.util.concurrent.FutureTask.<init>(FutureTask.java:152)
at java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:87)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:111)
at com.fast.summary.jvm.oom.TestOomThreadPool.fixedThreadPool(TestOomThreadPool.java:32)
newSingleThreadExecutor
- LinkedBlockingQueue为无界队列
// -Xmx8m -XX:-UseGCOverheadLimit
private static void singleThreadExecutor() {
ExecutorService executor = Executors.newSingleThreadExecutor();
LoggerUtils.get().debug("begin...");
while (true) {
executor.submit(() -> {
try {
LoggerUtils.get().debug("send sms...");
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.concurrent.Executors.callable(Executors.java:407)
at java.util.concurrent.FutureTask.<init>(FutureTask.java:152)
at java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:87)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:111)
at java.util.concurrent.Executors$DelegatedExecutorService.submit(Executors.java:678)
at com.fast.summary.jvm.oom.TestOomThreadPool.singleThreadExecutor(TestOomThreadPool.java:47)
at com.fast.summary.jvm.oom.TestOomThreadPool.main(TestOomThreadPool.java:22)
newCachedThreadPool
- 会不断创建线程
static ExecutorService executorService = Executors.newCachedThreadPool();
static class Task implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static void scheduledThreadPool() {
ExecutorService executor = Executors.newScheduledThreadPool(2);
LoggerUtils.get().debug("begin...");
while (true) {
executor.submit(() -> {
try {
LoggerUtils.get().debug("send sms...");
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
运行结果:
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 java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378)
at com.fast.summary.jvm.oom.TestOomThreadPool.cachedThreadPool(TestOomThreadPool.java:60)
at com.fast.summary.jvm.oom.TestOomThreadPool.main(TestOomThreadPool.java:23)
Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated
newScheduledThreadPool
- DelayedWorkQueue 是无界队列
运行结果:
java.lang.OutOfMemoryError: Java heap spacejava.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:530)
at java.util.concurrent.ScheduledThreadPoolExecutor.submit(ScheduledThreadPoolExecutor.java:632)
at com.fast.summary.jvm.oom.TestOomThreadPool.scheduledThreadPool(TestOomThreadPool.java:81)
at com.fast.summary.jvm.oom.TestOomThreadPool.main(TestOomThreadPool.java:24)
更多推荐
已为社区贡献6条内容
所有评论(0)