JVM 进阶 (十三):阶段学习回顾
一、内存分类
各位小伙伴,到上一篇博文为止,我们的内存模型相关知识就已经讲完了!不知道大家吸收了多少,这里我们简单的来回顾一下吧!
在博文《JVM进阶(三):内存分配与回收策略》中讲到,内存基本分为 JAVA 栈、本地方法栈、堆和方法区。
首先栈存放的是基本类型变量,局部变量,和对象的引用,他在内存中是一块连续的区域,有大小限制,是由系统自动分配的,因此它的读写速度比较快,而且会自动释放掉为该变量所分配的内存空间;还有一点就是他还存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息。
堆存放对象和数组;在运行时动态分配内存(比如 new()
),较慢,但灵活;是不连续的内存区域,在发出申请的时候,系统首先会遍历一个存有空闲地址节点的链表,找到第一个满足申请大小的节点,将他从链表删除,并分配给申请者,如果空间剩余,则将多出来的加入链表;由Java虚拟机
的自动垃圾回收器来管理。分为一个Eden
区和两个Survivor
区。
方法区主要存放静态变量,常量,全局变量。他的大小不必是固定的,jvm
可以根据应用的需要动态调整,同样方法区也不必是连续的。方法区可以在堆(甚至是虚拟机自己的堆)中分配。jvm
可以允许用户和程序指定方法区的初始大小,最小和最大尺寸。因为方法区是被所有线程共享的,所以必须考虑数据的线程安全。假如两个线程都在试图找一个类,在该类还没有被加载的情况下,只应该有一个线程去加载,而另一个线程需要等待。
本地方法栈则是为执行Native
方法服务,但这个在不同JVM
内有不同的内部实现,比如在HotSpot JVM
中 Java 虚拟机栈和本地方法栈被实现为同一个栈区。
二、收集方法
在博文《JVM进阶(五):GC 之标记》中讲到,对于收集方法来说一般有两种,“复制”和“标记-清除-整理”。“复制”算法需要留有部分空间用于复制后的存储,适用于朝生夕死的对象;“标记-清除-整理”适用于年老代,清除后形成逻辑上连续的区域,避免了内存碎片。
三、标记方法
在博文《JVM进阶(五):GC 之标记》中讲到,对象被回收之前都要先被标记为可回收的对象,一般有引用计数和可达性分析法。JAVA
采用的可达性分析,从“GC Roots
”开始组建一张张的关系网,不在关系网上的就会被清除。标记有两次,因为被标记后还可能会执行finalize()
方法。“GC Roots
”被记录在OopMap
中,能够让虚拟机快速的得到他们,不用遍历整个堆来寻找“GC Roots
”了。
四、STW
在博文《JVM进阶(九):年轻代收集器》、《JVM进阶(十):年老代收集器》、《JVM进阶(十一):JAVA G1收集器》中讲到,回收的时候需要暂停程序的所有线程,这个过程叫做STW
,我们的程序需要优化的时候,缩短STW
也是优化的一部分。
各种收集器都为缩短STW
的时间提供了不同的策略,并行的、串行的,作用于年轻代的,作用于年老代的,还有作用于整个堆的。各有各的优劣势,需要搭配使用,不能随意组合。
好啦,这一整块我们算是大概回忆完啦,在后面的博文中我们就要开始讲虚拟机中的类加载机制了!
五、拓展阅读
《JVM专栏》
版权声明: 本文为 InfoQ 作者【No Silver Bullet】的原创文章。
原文链接:【http://xie.infoq.cn/article/c516bc00beb544c16b71ab701】。文章转载请联系作者。
评论