开始学习 java虚拟机的原理,参考《深入理解Java虚拟机 第二版》周志明一书和“chjttony”博友所总结的简版学习笔记《深入理解java虚拟机》学习笔记,边学习边记忆,由于自己的记忆力愈来愈差,只好使用博客来帮助记忆了。
内存模型总览
其中方法区和堆是线程共享内存,Java虚拟机栈、本地方法栈以及PC是线程私有区域。
程序计数器 当前线程的字节码行号指示器控制程序的分支、循环、跳转、异常处理及县城恢复等基础功能Java虚拟机的多线程是通过线程轮流切换并分配处理器时间片来实现是唯一一个没有规定OOM的内存区域Java虚拟机栈 生命周期和线程相同描述了Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧来存放局部变量表、操作数栈、动态链接、方法出口等信息,当前正在执行的方法成为当前帧,一个方法的执行过程,其实就是方法帧入栈和出栈的过程局部变量表存放了:基本数据类型数据、对象引用、方法返回地址,而且局部变量表的内存在进入方法时是完全确定的,不会动态修改StackOverFlowError异常:线程请求的深度大于虚拟机所允许的最大深度OutOfMemoryError异常:虚拟机栈动态扩展时没有可用内存时本地方法栈 类似Java虚拟机栈,区别是 本地方法栈是为操作系统的本地方法服务HotSpot虚拟机将两者合二为一堆 对象实例及数组对象的内存都在此分配,也是GC的主要区域OutOfMemoryError方法区 存储已被虚拟机加载的类信息、常量、静态变量、类的Class对象引用等信息运行时常量池:存放编译期生成的各种字面变量、符号引用、直接引用等OutOfMemoryError直接内存 不属于JVM的运行时数据区NIO可以只要Native方法直接分配对外内存,然后使用DirectByteBuffer进行引用。垃圾回收算法要解决三个问题: 1.哪些内存需要回收? 2.什么时候回收?:内存不足,引发GC动作 3.如何回收
标记-清除算法:第一步,根据可达性分析,标记处所以需要回收的对象;第二步,回收标记的对象内存。 缺点:
效率不高,无论是标记还是回收;产生空间碎片,容易再次引起GC动作复制算法:把内存分为相同的两块儿,每次使用其中一块,标记完成后,把存活的对象复制到另一块内存中。 优点:
提高了效率解决了内存碎片化问题 缺点:内存浪费严重改进的复制算法:改进了复制算法的空间浪费,将内存分为8:1:1的三份,分别命名为Eden、Survivor From和Survivor To,其中的Eden+Survivor两块内存用于分配内存和GC,标记以后,把存活的对象复制到另一块儿Survivor的内存上,加入Survivor内存不够存放这些存活的对象,则向老年代进行分配担保。 适用于新生代这种绝大部分对象都是朝生暮死的情况,对于老年代这种就不适用了。
标记-整理算法:类似 标记-清除 算法,与之不同的是,标记之后不是直接清除,而是将存活的对象向一端移动,然后清除掉边界以外的内存。
分代收集算法:即对象存活率高的地方,如老年代,使用标记-整理算法,称为Major GC/Full GC;对象存活率低的地方,如新生代,使用改进的复制算法,称为Minor GC新闻热点
疑难解答