JVM内存模型
JVM:运行时数据区域(线程共享和非共享的)
线程共享的:堆区,方法区
非线程共享的:程序计数器,Java虚拟机栈,本地方法栈
- 堆区:存放对象实例,分配内存。新生代(Eden,From Survivor,To Survivor),老年代;堆大小=新生代+老年代。其中堆大小可以通过参数-Xms(堆的最小指)、-Xmx(堆的最大值)来设置。(注:-Xss 栈容量)(新生代:老年代=1:2,Eden:From:To Survivor = 8:1:1)
- 方法区:方用于存储已被虚拟机加载的类信息、常量、静态变量;(常量池)
- 程序计数器:(标记程序指令的执行)用来标志当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器上的值来选取下一条需要执行的字节码指令。
- java虚拟机栈:每个方法被执行的时候都会创建一个栈帧用于存储局部变量表(方法参数、局部变量和对象引用类型)、操作数栈(操作栈,方法进行参数传递)、动态连接(每个栈帧都包含一个执行运行时常量池中该栈帧所属方法的引用)、方法出口(方法出口分为两种, 一种收到返回命令,正常退出;第二种执行遇到异常导致方法退出)等。(编译时确定)
- 本地方法栈:虚拟机栈为执行Java方法(字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
- 内存泄漏:StackOverflowError,OutOfMemoryError
- 垃圾回收:主要回收的是堆区的资源(回收对象/方法区—判断对象是否可回收—回收算法)
- 对象是否存活:(1)引用记数法(对每次引用进行记数,但无法避免相互引用),(2)引用链可达性分析,以“GC Roots”的对象作为起始点向下搜索,如果一个对象没有任何引用链相连时,则该对象可以回收。GC Roots(各种可能的对象)
- 垃圾回收算法:标记—清除法(碎片问题),复制算法(两块内存区域,复制存活对象,交换),标记—压缩算法(标记存活对象压缩到内存空间一端)。
- 分代收集: 新生代使用复制算法:将Eden和一个(From)Survival的存活对象全部放入到另一个(To)Survival空间中,最后清理掉刚刚的Eden和Survival空间(当Survival空间不够时,由老年代进行内存分配担保)。老年代采用标记-删除,或者标记-整理算法。
- 类加载机制:虚拟机把表示类的class文件加载到内存,经过校验、转换解析、初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制.