标签:
所有对象的实例都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,如果程序使用的内存超过了堆最大内存(-Xmx),则会溢出Java heap space。
了解java内存模型看这里:java内存模型是什么样的
了解堆内存看这里:java堆内存是什么样的
了解java垃圾回收机制看这里:java垃圾回收机制是什么
实例:
public class HeapOOM {
static class OOMObject{}
/**
* @param args
*/
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while(true){
list.add(new OOMObject());
}
}
}
加上JVM参数运行:
-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError
其中-verbose:gc是为了打印GC过程的详细情况,上述程序就能很快报出内存溢出(OOM):
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
并且能自动生成Dump文件,Dump记录了进程内存的完整信息。
了解Dump文件看这里:什么是Dump文件
方法区(永久代)是存放虚拟机加载类的相关信息(如类、静态变量和常量),大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能使永久代溢出PermGen space。
实例:
public class MethodAreaOOM {
static class OOMOjbect{}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
while(true){
Enhancer eh = new Enhancer();
eh.setSuperclass(OOMOjbect.class);
eh.setUseCache(false);
eh.setCallback(new MethodInterceptor(){
@Override
public Object intercept(Object arg0, Method arg1,
Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
return arg3.invokeSuper(arg0, arg2);
}
});
eh.create();
}
}
}
加上永久代的JVM参数后:
-XX:PermSize=10M -XX:MaxPermSize=10M
运行后会报如下异常:
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space
静态变量或常量也会有可能撑爆方法区:
public class ConstantOOM {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> list = new ArrayList<String>();
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
}
同样加上JVM参数:
-XX:PermSize=10M -XX:MaxPermSize=10M
运行后报如下异常:
Exception in thread “main” java.lang.OutOfMemoryError: PermGen space
栈是存放线程调用方法时存储局部变量、操作、方法出口等与方法执行相关的信息,栈大小由-Xss来调节,方法调用层次太多会使栈溢出StackOverflowError。
实例:
package com.cutesource;
public class StackOOM {
/**
* @param args
*/
private int stackLength = 1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable{
// TODO Auto-generated method stub
StackOOM oom = new StackOOM();
try{
oom.stackLeak();
}catch(Throwable err){
System.out.println("Stack length:" + oom.stackLength);
throw err;
}
}
}
设置JVM参数:
-Xss128k
运行报出异常:
Exception in thread “main” java.lang.StackOverflowError
打印出Stack length:1007,这里可以看出,128k的栈容量能承载深度为1007的方法调用。当然这个错误很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域(线程内分配了自己的栈,但是进程中所有线程可使用的栈总大小是一定的):
package com.cutesource;
public class StackOOM {
/**
* @param args
*/
private int stackLength = 1;
private void dontStop(){
while(true){
try{Thread.sleep(1000);}catch(Exception err){}
}
}
public void stackLeakByThread(){
while(true){
Thread t = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
dontStop();
}
});
t.start();
stackLength++;
}
}
public static void main(String[] args) throws Throwable{
// TODO Auto-generated method stub
StackOOM oom = new StackOOM();
try{
oom.stackLeakByThread();
}catch(Throwable err){
System.out.println("Stack length:" + oom.stackLength);
throw err;
}
}
}
运行报出异常:
Exception in thread “main” java.lang.OutOfMemoryError:unable to create new native thread
在windows上运行这个例子要很小心,可能会出现系统假死的情况,需要重启机器。
Java千百问_07JVM架构(013)_java什么情况会内存溢出
标签:
原文地址:http://blog.csdn.net/ooppookid/article/details/51530578