《深入理解Java虚拟机》学习笔记

本篇是《深入理解Java虚拟机-Java 高级特性与最佳实践》学习笔记,周志明著,Understanding the JVM-Advanced Features and Best Practices,机械工业出版社,2011.6出版。

重温Java JVM知识,重点学习了与日常开发工作相关性最大的“自动化内存管理”模块,对Java容器优化、内存问题解决很有帮助;习惯了从互联网看电子书,难以集中和记忆,现在找几本纸质书重温,可以很清静、很安静的理解和消化,受益匪浅。

HeapSize OOM -- Java heap space

class HeapOOM {
        public static void main(String[] args) {
                java.util.List<String> list = new java.util.ArrayList<String>();
                while(true) {
                        list.add("内存溢出啊,内粗溢出啊!");
                }
        }
}

执行java -Xmx2m HeapOOM,堆内存瞬间溢出,报错:java.lang.OutOfMemoryError:Java heap space

HeapSize OOM -- GC over head limit exceeded

import java.util.*;
class GCOverHead {
        public final static byte[] DEFAULT_BYTES = new byte[12*1024*1024];
        public static void main(String[] args) {
                List<byte[]> temp = new ArrayList<byte[]>();
                while(true) {
                        temp.add(new byte[1024*1024]);
                        if(temp.size()>3) {
                                temp.clear();
                        }
                }
        }
}

执行java -XX:+PrintGCDetails -XX:+UseGCOverheadLimit -Xmn5m -Xmx20m GCOverHead ,据说会报java.lang.OutOfMemoryError:GC over head limit exceeded,意思是不断在做Full GC,每次GC完后释放一点点内存,然后一下子就又满了,不断重复,当次数达到一定量,并且平均FULL GC时间达到一定比例时,就会报错;

但是,我的程序一直就无限循环运行,不报错误。。。

PermGen OOM

import net.sf.cglib.proxy.Enhancer;
class ClassPermGenOOM {
        public static void main(String[] args) {
                while(true) {
                        createProxy(ClassPermGenOOM.class);
                }
        }
        public static Object createProxy(Class<?> targetClass) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(targetClass);
                enhancer.setUseCache(false);
                enhancer.setCallback(new MethodInterceptor() {
                        public Object intercept(Object object,
                                Method method,Object[] args,
                                MethodProxy methodProxy) throws Throwable {
                                return methodProxy.invokeSuper(object,args);
                        }       
                });
                return enhancer.create();
        }
}

执行java -XX:+TraceClassUnloading -XX:PermSize=10m -XX:MaxPermSize=10 ClassPermGenOOM,会报出java.lang.OutOfMemoryError:PermGen space错我。

DirectBuffer OOM

import java.nio.ByteBuffer;
class ByteBufferOOM {
        public static void main(String[] args) {
                ByteBuffer.allocateDirect(257*1024*1024);
        }
}
~ 

执行java -XX:MaxDirectMemorySize=256m ByteBufferOOM,则会报出错误java.lang.OutOfMemoryError:Direct bufer memory。

StackOverflowError

栈溢出,无限递归即可。

死递归和死循环不一样,死循环时,栈空间不会递增;而死递归由于需要记录退回的路径,就必须记住递归过程中的方法调用过程,以及每个方法运行过程中的本地变量,这个我们称之为上下文信息,随着内容的增加,就会占用更多的内存空间,JVM是为了控制它的无限制增长,才做了安全检测的处理。

文章导航