内存溢出

 堆内存溢出

要想保证堆内存溢出,那么只要不断创建对象并且对象不被回收,那么对象数量到达最大堆限制后就会出现内存溢出的异常了。

虚拟机参数:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError

 1 public class HeapOverflowTest {
 2 
 3     public static void main(String[] args) {
 4         List<HeapOverflowTest> hofts = new ArrayList<HeapOverflowTest>();
 5         while(true){
 6             hofts.add(new HeapOverflowTest());
 7         }
 8     }
 9     
10 }

结果

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid18963.hprof ...
Heap dump file created [27465755 bytes in 0.108 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at algorithm.HeapOverflowTest.main(HeapOverflowTest.java:11)

栈内存溢出

java虚拟机规范中描述如果线程请求的栈深度太深,会产生栈溢出,比如无线调用自己的方法。

栈内存溢出有两种情况:

1.线程请求的栈深度超过虚拟机所允许的最大深度,会抛出StackOverflowError异常。

2.如果虚拟机在扩展栈无法申请到足够的内存空间,会抛出OutOfMemoryError异常。

虚拟机参数:-Xss228k

 1 public class StackOverflowTest {
 2 
 3     private int stackLength;
 4     
 5     public void stackLeak(){
 6         stackLength++;
 7         this.stackLeak();
 8     }
 9     
10     public static void main(String[] args) {
11         
12         StackOverflowTest soft = new StackOverflowTest();
13         try{
14             soft.stackLeak();
15         }catch(Throwable e){
16             System.out.println("stackLength="+soft.stackLength);
17             throw e;
18         }
19     }
20     
21 }

结果

stackLength=1517
Exception in thread "main" java.lang.StackOverflowError
    at algorithm.StackOverflowTest.stackLeak(StackOverflowTest.java:8)
    at algorithm.StackOverflowTest.stackLeak(StackOverflowTest.java:9)
    at algorithm.StackOverflowTest.stackLeak(StackOverflowTest.java:9)
    at algorithm.StackOverflowTest.stackLeak(StackOverflowTest.java:9)

如果不断地建立线程的方式会产生OutOfMemoryError。操作系统分配给进程的内存是有限制的,比如32位windows是2GB。虚拟机提供了参数来控制java堆和方法区两个部分内存的最大值,剩余内存为2GB-最大堆容量-最大方法区容量-程序计数器(很小,可以忽略),虚拟机进程本身

的消耗不考虑,剩下的都是栈内存了。栈内存是线程私有的,那么每个线程分配的栈容量大,那么建立的线程数必然减少,所以很容易把剩下的内存耗尽。虚拟机默认参数,栈深度1000~2000没什么问题,正常方法应该问题不大。如果建立了过多线程导致的OutOfMemoryError,在不能

减少线程或者更换64位虚拟机的情况下,只能通过减少最大堆容量和减少栈容量来换取更多的线程了。

方法区和运行时常量池溢出

 1 public class ConstantPoolOverflowTest {
 2 
 3     public static void main(String[] args) {
 4         List<String> list = new ArrayList<String>();
 5         int i =0;
 6         while(true){
 7             list.add(String.valueOf(i++).intern());
 8         }
 9     }
10 }

结果

Error occurred during initialization of VM
java.lang.OutOfMemoryError: PermGen space
    at sun.misc.Launcher.<init>(Launcher.java:71)
    at sun.misc.Launcher.<clinit>(Launcher.java:57)
    at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1489)
    at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1474)
Exception in thread "Reference Handler" 

对于Hotspot来说,方法区=永久代。

原文地址:https://www.cnblogs.com/tp123/p/6479143.html