一.Java虚拟机栈和本地方法栈内存异常探究
1.如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量时,Java虚拟机会抛出一个StackOverflowError异常
package com.stack.over;
/*
* 构造自己的实例,不断递归调用自己,当递归的栈深度到达一定的程度,Java虚拟机就会抛出StackOverflowError异常
* VM栈深度设置: -Xss128k 设置栈深度为128K
*/
public class JavaVmStackSOF {
private int stackLength = 1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable{
// TODO Auto-generated method stub
JavaVmStackSOF oom = new JavaVmStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
// TODO Auto-generated catch block
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}
2.如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或者在建立新的线程时,没有足够的内存去创建对应的虚拟机栈,那么Java虚拟机将会抛出一个OutOfMemoryError
package com.stack.over;
/*
* 1.Java虚拟机栈设置成可以动态拓展,并且动态拓展已经尝试,仍然无法申请到足够的内存,Java虚拟机就会抛出异常
* 2.Java虚拟机尝试建立新线程时,如果当前已经没有足够的内存去创建新 线程,或操作系统拒绝创建新线程,这时Java虚拟机也会抛出异常
* 注意:此段代码运行将会创建很多线程,让系统变得十分卡慢,直到内存不足,终止运行
*/
public class JavaVmStackOOM {
public void dontstop(){
while(true){
}
}
public void stackLeakByThread(){
while(true){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
dontstop();
}
});
thread.start();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
JavaVmStackOOM oom = new JavaVmStackOOM();
oom.stackLeakByThread();
}
}
1.如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那么Java虚拟机将会抛出一个OutOfMemoryError
package com.heap.over;
import java.util.ArrayList;
import java.util.List;
/*
* 1.不断在Java堆中创建对象,并保证对象不会被内存回收,随着while的不断循环执行,对象会越来越多,直至超出Java堆的最大容量
* 2.将JVM的内存参数设置在20M之内,Java堆发生溢出时,Java虚拟机会自动把当前Java堆的内存印象荡复到磁盘中,供后续调试分析:
* -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
*/
public class HeapOOM {
public static class OOMObject{
}
public static void main(String[] args) {
// TODO Auto-generated method stub
List list = new ArrayList();
while(true){
list.add(new OOMObject()); //对象一直被List集合引用,保证不会被回收
}
}
}
三.Java常量池与方法区溢出异常
package com.constantPool.over;
import java.util.ArrayList;
import java.util.List;
/*
* 运行时常量池溢出的代码
* 把虚拟机的永久代内存限制起始10M,最大10M: -XX:PermSize=10M -XX:MaxPermSize=10M
* 1.不断循环,产生字符串常量,字符串常量会随整形数字i的增加而不断变化
*/
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
// TODO Auto-generated method stub
//使用List保持着常量池引用,避免Full GC回收常量池行为
List list = new ArrayList ();
//10M的PermSize在Integer范围内足够产生OOM
int i = 0 ;
while(true){
list.add(String.valueOf(i++).intern()); //随i增加不断变化
}
}
//jdk1.7开始把字符串常量池罗列到Java堆中,即使这么多对象也不足够让内存撑爆,不会抛出异常,jdk1.6的永久代会抛异常
}