1,java堆溢出
JAVA堆用于存储对象实例,只要不断的创建对象,保证GC Roots到对象直接有可达路径,避免垃圾回收机制清楚对象,那么对象数量叨叨一定程度后,会产生内存溢出异常。
如下代码,限制Java堆大小为1024m,并且-Xms和-Xmx的参数相同,即不可扩展。同事在Run Configuration中增加VM 参数:
-XX:+HeapDumpOnOutOfMemoryError
让虚拟机在出现内存溢出异常时,Dump出当前的内存堆转储快照。
package com.jvm.exception;
import java.util.ArrayList;
import java.util.List;
public class HeapSpaceException {
public static void main(String[] args) {
List<byte[]> byteList = new ArrayList<byte[]>();
while(true){
byteList.add(new byte[1024]);
}
}
}
运行结果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2783.hprof ...
Heap dump file created [3795151132 bytes in 3.289 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.jvm.exception.HeapSpaceException.main(HeapSpaceException.java:13)
内存中首先提示OutOfMemoryError,让后提升Java heap space。
一般出现此类问题,可以采用内存分析工具,如Eclipse Memory Analyzer进行分析。
如果内存泄露,则查看泄露对象到GC Roots的引用链,确定内存泄露位置。
如果内存未泄露,则应当检查虚拟机的参数(-Xmx 和 -Xms)。
2,虚拟机栈和本地方法栈溢出
由于HotSpot虚拟机并没有区分虚拟机栈和本地方法栈,因此对HotSpot来说,-Xoss(设置本地方法栈大小)参数存在,但实际是无效的。栈容量只能通过-Xss参数设定。虚拟机栈和本地方法栈,在Java虚拟机规范中定义了两种异常:
-1,如果线程请求栈深度大于虚拟机所允许的最大深度,将抛出StackOverFlowError异常。
-2,如果虚拟机找扩展栈时无法申请到足够的内存空间,则抛出OutOfMmemoryError。
首先在单线程环境中,使用-Xss参数减少栈内存容量,抛出StackOverFlowError。
package com.jvm.exception;
/**
* 默认-Xss参数
* @author jinglongjun
*
*/
public class StackOverFlowError {
private int stackLength = 1;
public void stackLeak(){
stackLength ++;
stackLeak();
}
public static void main(String[] args) {
StackOverFlowError sof = new StackOverFlowError();
try{
sof.stackLeak();
}catch(Throwable e){
System.out.println("stackLength : " + sof.stackLength);
throw e;
}
}
}
输出内容:
stackLength : 10828
Exception in thread "main" java.lang.StackOverflowError
at com.jvm.exception.StackOverFlowError.stackLeak(StackOverFlowError.java:13)
at com.jvm.exception.StackOverFlowError.stackLeak(StackOverFlowError.java:14)
单线程环境,定义大量本地变量,增大方法栈中本地变量表的长度。结果抛出StackOverFlowEoor时,输出的堆栈深度相应的缩小。
这种情况模拟了很久没有模拟出来。因为本文是参考《深入理解Java虚拟机》这本书的,书中也未给出例子。
在单线程下,总是抛出StackOverFlowError。
多线程模拟。
建议不要尝试运行下面的代码。
建议不要尝试运行下面的代码。
建议不要尝试运行下面的代码。
package com.jvm.exception;
public class OutOfMemoryError {
public void dontStop(){
while(true){
}
}
public void stackLengthThread(){
while(true){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) {
OutOfMemoryError oome = new OutOfMemoryError();
oome.stackLengthThread();
}
}
以上代码会抛出:
OutOfMemoryError。