1. java堆溢出
EclipseIDE设置:debugconfiguration-->javaapplication-->class-->VMArguments
-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails |
/**
* VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
*
*/
public class HeapOOM {
static class OOMObject{
}
public static void main(String[] args){
List<OOMObject> list = new ArrayList<OOMObject>();
while(true){
list.add(new OOMObject());;
}
}
}
运行结果:
Exceptioninthread "main" java.lang.OutOfMemoryError: Java heap space
分析:内存泄漏Memory Leak,对象应该被回收却没有
内存溢出Memory Overflow空间不够,通过-Xms设置堆最小值,-Xmx设置堆最大值,缩短对象生命周期和持有时间,减少程序运行期的内存消耗。
2. 虚拟机栈和本地方法栈溢出
-Xss设置栈容量
递归导致*Error
/**运行结果:
* VM Args: -Xss128k
*
*/
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;
}
}
}
stacklength: 2275
Exceptionin thread "main"java.lang.*Error
atcom.java.vm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:10)
分析:
只要单线程,不管是栈帧太大,还是虚拟机栈容量太小都抛出*Error
创建线程导致OOM
/**运行结果:
* VM Args: -Xss2m
*
*/
public class JavaVMStackOOM {
private void dontStop(){
while(true){
}
}
public void stackLeakByThread(){
while(true){
Thread thread = new Thread(new Runnable(){
public void run(){
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args){
JavaVMStackOOM oom =new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
Exceptionin thread "main" java.lang.OutOfMemoryError: unable to create newnative thread
分析:此时的OOM与栈空间的大小无关,减少最大堆和减少栈容量可换取更多线程。
3. 运行时常量池溢出
使用String.intern()这个native方法,向常量池添加内容。该方法的作用,如果池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象,否则,将此String对象包含的字符串添加到常量池中,并返回此String对象的引用。
/**运行结果:
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*
*/
public class RuntimeConstantPoolOOM {
public static void main(String[] args){
//使用list保持常量池引用,避免Full GC回收常量池行为
List<String> list = new ArrayList<String>();
//10MB的PermSize在integer范围内足够产生OOM了
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
}
Exceptionin thread "main" java.lang.OutOfMemoryError: PermGen space
4. 方法区溢出
借助CGLib使得方法区出现内存溢出
/**运行结果:
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*
*/
public class JavaMethodAreaOOM {
static class OOMObject{
}
public static void main(String[] args){
while(true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor(){
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable{
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
}
Caused by:java.lang.OutOfMemoryError: PermGen spac
分析:
在动态生成大量class的应用中,如大量JSP或动态产生JSP的应用,要注意类的回收状态。