堆溢出
Java堆独一的浸染就是存储工具实例,只要担保不绝建设工具而且工具不被接纳,那么工具数量到达最大堆容量限制后就会发生内存溢出异常了。所以测试的时候把堆的巨细牢靠住而且让堆不行扩展即可。测试代码如下
package com.xrq.test; import java.util.ArrayList; import java.util.List; /** * 测试内容:堆溢出 * * 虚拟机参数:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError */ public class HeapOverflowTest { public static void main(String[] args) { List<HeapOverflowTest> list = new ArrayList<HeapOverflowTest>(); while (true) { list.add(new HeapOverflowTest()); } } }
运行功效
java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid8876.hprof ... Heap dump file created [15782068 bytes in 0.217 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:2760) at java.util.Arrays.copyOf(Arrays.java:2734) at java.util.ArrayList.ensureCapacity(ArrayList.java:167) at java.util.ArrayList.add(ArrayList.java:351) at com.xrq.test.HeapOverflowTest.main(HeapOverflowTest.java:18)
这种异常很常见,也很好发明,因为都提示了“Java heap space”了,定位问题的话,按照异常仓库阐明就好了,行号都有指示。办理方案的话,可以调大堆的巨细可能从代码上检视是否存在某些工具生命周期过长、持有状态时间过长的环境,长时间少措施运行期间的内存耗损。
栈溢出
Java虚拟机类型中描写了假如线程请求的栈深度太深(换句话说要领挪用的深度太深),就会发生栈溢出了。那么,我们只要写一个无限挪用本身的要领,自然就会呈现要领挪用的深度太深的场景了。测试代码如下
package com.xrq.test; /** * 测试内容:栈溢出测试(递归挪用导致栈深度不绝增加) * * 虚拟机参数:-Xss128k */ public class StackOverflowTest { private int stackLength = 1; public void stackLeak() { stackLength++; stackLeak(); } public static void main(String[] args) throws Throwable { StackOverflowTest stackOverflow = new StackOverflowTest(); try { stackOverflow.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + stackOverflow.stackLength); throw e; } } }
运行功效:
stack length:1006 Exception in thread "main" java.lang.StackOverflowError at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:14) at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:15) at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:15) at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:15) at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:15) at com.xrq.test.StackOverflowTest.stackLeak(StackOverflowTest.java:15) ...
后头都是一样的,昆山软件开发,忽略。通过不绝建设线程的方法可以发生OutOfMemoryError,因为每个线程都有本身的栈空间。不外这个操纵有危险就不做了,劳务派遣管理系统,原因是Windows平台下,Java的线程是直接映射到操纵系统的内核线程上的,假如写个死轮回无限发生线程,那么大概会造成操纵系统的假死。
上面无限发生线程的场景,从别的一个角度说,就是为每个线程的栈分派的内存空间越大,反而越容易发生内存溢出。其实这也很好领略,操纵系统分派给历程的内存是有限制的,好比32位的Windows限制为2GB。虚拟机提供了了参数来节制Java堆和要领区这两部门内存的最大值,昆山软件开发,剩余内存为2GB-最大堆容量-最概略领区容量,措施计数器很小就忽略了,虚拟机历程自己的淹灭也不算,剩下的内存就是栈的了。每个线程分派到的栈容量越大,可成立的线程数自然就越少,成立线程时就越容易把剩下的内存耗尽。
StackOverFlowError这个异常,有错误仓库可以阅读,较量好定位。并且假如利用虚拟机默认参数,栈深度在大大都环境下,到达1000~2000完全没有问题,正常要领的挪用这个深度应该是完全够了。可是假如成立过多线程导致的OutOfMemoryError,在不能淘汰线程数可能改换64位虚拟机的环境下,就只能通过减小最大堆容量和减小栈容量来调换更多的线程了。
要领区和运行时常量池溢出
运行时常量池也是要领区的一部门,所以这两个区域一起看就可以了。这个区域的OutOfMemoryError可以操作String.intern()要领来发生。这是一个Native要领,意思是假如常量池中有一个String工具的字符串就返回池中的这个字符串的String工具;不然,将此String工具包括的字符串添加到常量池中去,而且返回此String工具的引用。测试代码如下
package com.xrq.test; import java.util.ArrayList; import java.util.List; /** * 测试内容:常量池溢出(这个例子也可以说明运行时常量池为要领区的一部门) * * 虚拟机参数-XX:PermSize=10M -XX:MaxPermSize=10M */ public class ConstantPoolOverflowTest { public static void main(String[] args) { List<String> list = new ArrayList<String>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } }