一、有哪些内存溢出异常?
OutOfMemoryError:
当堆、栈(多线程场景)、方法区(永久区)、本地内存(元数据、直接内存),数据容量达到最大时产生
StackOverFlowError:
线程请求的栈深度大于虚拟机栈允许的最大深度(默认1MB)时产生
二、堆溢出产生原因及解决方法?
产生原因:
不停的创建对象或对象占用空间特别大,在对象数量达到堆最大容量时产生OutOfMemoryError
解决方法:
使用-XX:+HeapDumpOnOutOfMemoryError,可以让java虚拟机在出现内存溢出时,产生当前堆内存快照以便进行异常分析,主要分析哪些对象占用了内存
代码示例:
1 import java.util.ArrayList; 2 import java.util.List; 3 4 /** 5 * 描 述:堆内存溢出 6 * 作 者:潇邦 7 */ 8 public class HeapOOM { 9 10 public static void main(String[] args) { 11 int i = 0; 12 List<String> list = new ArrayList<>(); 13 while (true) { 14 list.add("abc"); 15 i++; 16 } 17 } 18 19 }
三、栈溢出产生原因及解决方法?
产生原因:
线程请求的栈深度大于虚拟机允许的最大深度,将抛出StockOverFlowError
多线程环境虚拟机栈在扩展时无法申请到足够内存空间,将抛出OutOfMemoryError
解决方法:
StockOverFlowError:一般函数层级过多导致,如死循环、死递归
OutOfMemoryError:一般多线程环境产生才会产生,一般用减少内存的方法,即减少栈容量来换取更多线程。
该参数可以设置栈容量(-XX:ThreadStackSize=512)
单线程栈代码示例:
1 /** 2 * 描 述:栈内存溢出StackOverflowError 3 * 作 者:潇邦 4 */ 5 public class StackOverFlow { 6 private int var; 7 8 public void run() { 9 var++; 10 run(); 11 } 12 13 public static void main(String[] args) { 14 StackOverFlow stackOverFlow = new StackOverFlow(); 15 try { 16 stackOverFlow.run(); 17 } catch (Exception e) { 18 System.out.println("Exception-栈深度:" + stackOverFlow.var); 19 e.printStackTrace(); 20 } catch (Error e) { 21 System.out.println("Error-栈深度:" + stackOverFlow.var); 22 e.printStackTrace(); 23 } 24 } 25 }多线程栈代码示例:
1 /** 2 * 描 述:多线程环境栈引发OutOfMemoryError 3 * 作 者:潇邦 4 */ 5 public class StackOom { 6 7 public void call() { 8 try { 9 Thread.sleep(10000); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 } 14 15 public void stackLeakByThread() { 16 while (true) { 17 new Thread(new Runnable() { 18 public void run() { 19 call(); 20 } 21 }).start(); 22 } 23 } 24 25 public static void main(String[] args) { 26 StackOom soed = new StackOom(); 27 soed.stackLeakByThread(); 28 } 29 }