• 1. 第二章Java内存区域与内存溢出异常
  • 2. Java技术体系 Java的发展史 展望Java技术的未来 实战:自已编译JDK回顾
  • 3. 运行时数据区域 对象的访问 实战:OutOfMemoryError本章目标
  • 4. Java虚拟在系统中的位置
  • 5. Java 虚拟机运行时数据区 运行时数据区域运行时数据据 方法区 Method Area虚拟机栈 VM Stack本地方法栈 Native Method Stack堆 Heap 程序计数器 Program Counter Register执行引擎本地库接口本地方法库线程隔离的数据区由所有线程共享的数据库
  • 6. 程序计数器(Program Counter Register) 是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 程序计数器
  • 7. Java虚拟机栈 Java虚拟机栈描述的是方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧(Stack Frame)用于存储局部变量表,操作栈,动态链接方法出口等信息。每一个方法被调用直至执行完成过程,就对应一个栈帧在Java虚拟机栈中从入栈到出栈的过程 局部变量表:存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double,对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址)) Java虚拟机栈区域的异常状况:1)如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。2)当扩展时无法申请足够的内存时会抛出OutOfMemoryError异常 Java虚拟机栈
  • 8. 本地方法栈(Native Method Stacks) 与Java虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用的Native方法服务方法。 本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 本地方法栈
  • 9. Java堆(Java Heap) 对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都要在堆上分配内存。 Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆” 如果在堆中没有内存完成的实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。 Java堆
  • 10. 方法区(Method Area) 方法区与Java堆一样,是各个线程共享的内存区域,它用于存储被虚拟加载的类信息,常量,静态变量,即时编译后的代码等数据。 这个区域的内存回收目标主要针对常量池的回收和对类型的卸载,一般来说这个区域的回收”成绩”比较难令人满意,特别是类型的卸载。 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 方法区
  • 11. 通过句柄访问对象 对象的访问Java栈本地变量表intshortreferencedouble………………..方法区对象类型数据Java堆到对象实例数据的指针到对象类型数据的指针句柄池对象实例数据实例池|||||||||||||||||||
  • 12. 通过指针直接访问对象对象的访问Java栈本地变量表intshortreferencedouble………………..方法区对象类型数据Java堆对象实例数据对象类型数据的指针
  • 13. Eclipse关于内存参数的配置 下图配置中限制Java堆的大小为40MB,不可扩展(将堆的最小值-Xms与-Xmx设为一样即可避免堆自动扩展) 实战OutOfMemoryError异常
  • 14. Java堆溢出(Java heap space) public class HeapOOM { // -Xms20M -Xmx20M -Xmn10M -XX: +PrintGCDetails -XX:SurvivorRatio=8 static class OOMobject{ } /** * @param args */ public static void main(String[] args) { List list=new ArrayList(); while(true){ list.add(new OOMobject()); } } }实战OutOfMemoryError异常
  • 15. 虚拟机栈和本地方法栈溢出(StackOverflowError) public class JavaVMStackSOF { private int statkLength=1; public void stackLeak(){ statkLength++; stackLeak(); } public static void main(String[] args) throws Exception{ JavaVMStackSOF oom=new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Exception e) { System.out.println("stack length: "+oom.statkLength); throw e; } } }实战OutOfMemoryError异常
  • 16. 运行时常量池溢出(OutOfMemoryError) Exception in thread "main" java.lang.OutOfMemoryError: PermGen space public class RuntimeConstantPoolOOM { /** * @param args */ public static void main(String[] args) { // 使用List保持着常量池引用,避免Full Gc回收常量池行为 List list=new ArrayList(); //10MB的PermSize在integer范围内足够产生OOM了. int i=0; while(true){ list.add(String.valueOf(i++).intern()); } } }实战OutOfMemoryError异常
  • 17. 方法区溢出 实战OutOfMemoryError异常