1、java堆溢出
代码如下
import java.util.ArrayList;
import java.util.List;
/**
* Vm args:-Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
* 堆的最小值参数-Xms,堆的最大值参数-Xmx
* -XX:+HeapDumpOnOutOfMemoryError表示让虚拟机在出现内存异常时Dump出当前的内存堆转储快照
* -XX:HeapDumpPath:为快照文件位置
* Java 堆内存溢出测试,深入理解java虚拟机 p51
*/
//-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:/
public class HeapOOM {
static class OOMObject{}
//psvm
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while (true){
list.add(new OOMObject());
}
}
}
运行
我们用Memory Analyzer 打开 dump出来的堆转储快照
官网:http://www.eclipse.org/mat/downloads.php 下载
打开
具体分析就不说了
2、java虚拟机栈和本地方法栈溢出
/**
* VM args:-Xss128k
* -Xss128k 减小栈内存至128k
*/
public class JavaVMStackSOF {
private int stackLength=1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
JavaVMStackSOF oom=new JavaVMStackSOF();
try{
oom.stackLeak();;
}catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}
运行
/**
* VM args:-Xss2M
* 该程序执行容易死机,我的电脑运行死机两次
*
*/
public class JavaVMStatckOOM{
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) {
JavaVMStatckOOM sofm = new JavaVMStatckOOM();
sofm.stackLeakByThread();
}
}
书上的运行结果如下
3、方法区和运行时常量池溢出
/**
* VM args:-XX:PermSize=10M -XX:MaxPermSize=10M
* PermSize 方法区大小
*/
public class RuntimeContantPoolOOM{
public static void main(String[] args) {
//使用List保存对常量池字符串的应用,避免Full GC回收常量池的行为
List<String> list = new ArrayList<String>();
//10M的PermSize在int的范围足够产生OutOfMemoryError
int i = 0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
}
运行结果(JDK1.6及之前的运行结果),
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space
在jdk6及之前,常量池分配在永久代内,通过-XX:PermSize10M -XX:MaxPermSize=10M限制其大小,而JDK1.7后就不会出现相同的结果,while循环将一直进行下去。。。。。。
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern()==str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
String str3 = new StringBuilder("goo").append("gle").toString();
System.out.println(str3.intern() == str3);
}
结果如下
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public class JavaMethodAreaOOM {
public static void main(String[] args) {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
return proxy.invokeSuper(obj, arg);
}
});
enhancer.create();
}
}
static class OOMObject {
}
}
运行结果:
Caused by: java.lang.OutOfMemoryError: PermGen space
4、本机直接内存溢出
/**
* VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at baby.oom.DirectMemoryOOM.main(DirectMemoryOOM.java:20)