本文章为看《深入理解JAVA虚拟机》的笔记
- JAVA堆异常溢出:
/**
* Vm args:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
* 堆的最小值参数-Xms,堆的最大值参数-Xmx
* -XX:+HeapDumpOnOutOfMemoryError表示让虚拟机在出现内存异常时Dump出当前的内存对快照
* java 堆内存溢出测试,深入理解java虚拟机 p51
* @author Rail
*
*/
public class HeapOutOfMemoryError {
static class OutOfMemoryError{
}
public static void main(String[] args) {
List<OutOfMemoryError> list = new ArrayList<OutOfMemoryError>();
while(true){
list.add(new OutOfMemoryError());
}
}
}
运行结果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid4208.hprof …
Heap dump file created [1029185391 bytes in 10.681 secs]
2.JAVA虚拟机栈和本地方法栈溢出:
1) 在Hotspot中,不区分JAVA虚拟机栈和本地方法栈。在JAVA虚拟机规范中描述了两种与之相关的异常:
- 如果线程请求的栈深度超出了虚拟机允许的最大深度,将抛出StackOverflowError异常,测试代码:
/**
* VM args:-Xss128k
* -Xss128k 减小栈内存至128k
* @author Rail
*
*/
public class JavaVMStackOverFlowError {
private int stackLength = 1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args){
JavaVMStackOverFlowError sof = new JavaVMStackOverFlowError();
try{
sof.stackLeak();
}catch(Throwable e){
System.out.println("stackLength: "+sof.stackLength);
throw e;
}
}
}
打印结果:
stackLength: 989
Exception in thread “main” java.lang.StackOverflowError
at jvm.JavaVMStackOverFlowError.stackLeak(JavaVMStackOverFlowError.java:11)
- 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError,测试代码:
/**
* VM args:-Xss2M
* 该程序执行容易死机,我的电脑运行死机两次
* @author Rail
*
*/
public class JavaVMStatckOutOfMemoryError {
public void dontStop(){
while(true){
}
}
public void stackLeakByThread(){
while(true){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
t.start();
}
}
public static void main(String[] args) {
JavaVMStatckOutOfMemoryError sofm = new JavaVMStatckOutOfMemoryError();
sofm.stackLeakByThread();
}
}
运行结果,本人电脑运行时死机两次,未成功输出结果,在书上的输出结果为:
Exception in thread main java.lang.OutOfMemoryError:unable to create new native thread
3.方法区和运行时常量池溢出:
/**
* VM args:-XX:PermSize10M -XX:MaxPermSize=10M
* PermSize 方法区大小
* @author Rail
*
*/
public class RuntimeContantPoolOutOfMemoryError {
public static void main(String[] args) {
//保存对常量池字符串的应用,避免Full GC回收常量池的行为
List<String> list = new ArrayList<String>();
//10M在int的范围足够产生OutOfMemoryError
int i = 0;
while(true){
list.add(String.valueOf(i++));
}
}
}
运行结果,在jdk6及之前,常量池分配在永久代内,通过-XX:PermSize10M -XX:MaxPermSize=10M限制其大小,而:
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.lang.Integer.toString(Integer.java:401)
at java.lang.String.valueOf(String.java:3087)
at jvm.RuntimeContantPoolOutOfMemoryError.main(RuntimeContantPoolOutOfMemoryError.java:17)
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize10M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0