参考《深入理解java虚拟机》
一 内存组成:
1 jvm栈(VM stack): 描述java方法执行的内存模型,每个方法在运行时都会产生一个栈帧(存储:局部变量表,操作数栈,动态链接,方法出口等)。每个方法从调用到执行完成的过程,对应一个栈帧在jvm栈中入栈到出栈的过程;
局部变量表存储了各种基本数据类型、对象引用和返回地址--编译器可知;
可能的异常:StackOverflowError--线程请求的栈深度大于虚拟机所允许的深度(方法调用深度过大/递归深度太深)
2 本地方法栈(Native Method Stack):描述jvm使用到的native方法栈;
3 java 堆:存放对象实例,各个线程共享。
是GC管理的主要区域,为了便于GC,将堆细分为:新生代和老年代;再细分为Eden,From Survivor,To Survivor
-Xms10m -Xmx10m--堆内存大小(这样的vm参数代表堆内存不可扩展);
当堆内存不足时会抛出:OutOfMemoryError异常;
4 方法区(Method Area),有时也被称为永久代(Permanent Generation):存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译的代码等数据;
运行时常量池是方法区的一部分,对比Class文件常量池的重要特征是具备动态性,运行时可将新的常量放入池中,如 String类的intern()方法(当这个字符串在常量池不存在的话会创建常量,并返回地址,如果存在,直接返回地址)
JDK7以后的HotSpot中,已经把原本存放在永久代的字符串常量池移出到heap中;
-XX:PermSize=20M -XX:MaxPermSize=20M--方法区大小
可能抛出异常:OutOfMemoryError
5 直接内存(Direct Memory):并不是jvm运行时数据区的一部分,也不是虚拟机规范中定义的内存
-XX:MaxDirectMemorySize=10M;可以指定DirectMemory的容量,如果没有指定,则默认和-Xmx指定值一样大;
例如NIO,可以使用Native函数库直接分配堆外内存,然后通过一个存储在堆上的DirectByteBuffer 对 象 作为这个内存的引用,这样避免了在java堆和Native堆中来回复制数据,提高性能;基于通道(Channel)与缓冲区Buffer的IO方式;
内存不足时也会引起OutOfMemoryError
二 OutOfMemoryError异常
1 java堆溢出: java heap space;
不断创建对象,且保证GC Roots到对象之间有可达路径避免垃圾回收机制清除这些对象;
添加 -XX:+HeapDumpOnOutOfMemoryError 使虚拟机在内存溢出异常时Dump当前内存堆快照,使用内 存分析工具分析;
2 jvm栈和native method栈:-Xss128k :配置栈容量
StackOverflowError:线程请求的栈深度大于虚拟机所允许的最大深度;
OutOfMemoryError:创立过多的线程(栈容量越大,可以创建的线程数量就越少)。因为windows平台的虚 拟机的java线程是映射到操作系统的内核线程的,所以测试可能会导致操作系统假死;
3 方法区和运行时常量池溢出:PermGen Space
测试方法:使用CGLib动态产生大量类/大量的jsp文件;
4 本机直接内存溢出 :明显特征是Heap Dump文件中不会看到明显的异常。