一、java运行时数据区域
一、程序计数器
线程私有,代表当前线程所执行的字节码的信号指示器。可以记录当前线程执行虚拟机字节码指令的 地址
二、java虚拟机栈
线程私有。每个方法都在执行的时候创建一个栈帧,用于存储局部变量表,操作数栈、动态链接、方法出口等等。局部变量表存放编译时期就可以知道的各种基本数据类型、对象引用(reference类型)。如果线程请求栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。当虚拟机栈扩展无法申请到足够的内存时,就会抛出OutOfMemoryError异常
三、本地方法栈
与虚拟机栈类似,不过虚拟机栈是为java方法服务,而本地方法栈为Native方法服务
四、堆
线程共享。虚拟机中内存最大的区域,也是极其重要的一片区域。存放所有对象实例。
五、方法区
线程共享。存储虚拟机加载的类信息,各种常量,静态变量、即时编译器编译后的代码区域等等。
二、对象创建过程
①虚拟机遇到new指令时 ,首先会检查指令的参数在常量池是否能定位到类的符号引用、如果能则代表符号代表的类已被加载、解析初始化过,如果没有则先加载类。
②类加载完成后,为对象分配空间。如果堆内存时完整的,则只许在可用和已用内存间防止一个指针作为分界点指示器,分配内存就是移动对象大小的指示器距离,这种分配叫指针碰撞【在多线程情况下,通过使用cas配合失败重试保证原子性,或者为每个线程分配一个缓冲,哪个线程需要内存,就在缓冲上分配】。如果堆内存不完整,则虚拟机为空一个列表,记录哪些内存块可用,在从可用内存块找到一块足够放下该对象 大小的内存,这种分配方式叫做空闲链表。因此选择哪种方式与采用何种垃圾收集器有关。
③设置对象,如对象是哪个类实例、对象哈希码,对象gc分带年龄【这些对存放在对象头中】,并根据虚拟机运行状态不同,对象头会有不同设置【如多线程中用到的是否使用偏向锁】
④填充对象,填充对象的各种信息
三、对象的回收
一、判断对象是否已死
①引用计数算法:为每个对象设置一个引用计数器,每引用一次,计数器+1;当引用失效时,计数器减一,当计数器为0时即需要回收【无法解决相互引用问题,如下图】
![](https://img.haomeiwen.com/i10981488/392eb6507285d9ff.png)
②可达性分析:从一个GC根节点出发 ,向下搜索走过的路径称为引用链,当一个对象不可达时,则证明对象不可用。在java中,可作为GC根节点包括以下几种:虚拟机栈引用的对象,方法区类静态属性引用的对象,本地方法栈中引用的对象
二:垃圾回收算法
①标记-清除算法(Mark-Sweep):标记所有需要回收的对象,在标记完成后统一回收【不足之处:标记清除效率不高并且会产生大量的内存碎片】
②复制算法(Copying):将内存分为两块,当一块用完了,就将还存活对象复制到另一块,再把已使用过得内存空间一次性清理掉【复制算法在对象存活率较高时要进行较多的复制操作,效率将会变低,并且浪费了很大的空间。】
③标记整理算法(Mark-Compact):标记所有需要回收的对象,将所有存活的对象朝一端移动,清理掉边界以外的内存
④分代算法:将内存分为不同区域,每个区域使用最适当的算法,如有大量回收,少量存活的用复制算法。当对象存活率高没有额外空间分配时就使用标记清除或标记整理算法。
三:垃圾回收器
新生代:
①Serial收集器(单线程、stop the world) 简单高效的收集器,采取复制算法。但是会中断用户线程。在桌面应用场景是新生代默认收集器(新生代较小,清理时间只需几十毫秒)
②ParNew收集器:Serial收集器多线程版本,采取复制算法
③Parallel Scavenge收集器:采取复制算法,关注吞吐量(运行用户代码的时间/(运行代码的时间+垃圾收集的时间)),停顿时间 短适合与用户交互多的 程序,而吞吐量高的程序适合后台运算多cpu利用率高程序,还有一个优点可以通过-XX:UseAdaptiveSizePolicy打开自适应开关,系统可以通过运行情况,动态调整新生代大小,Eden和Survivor区比例,晋升老年代晋升年龄等参数【GC调节自适应策略】,只需设置基本参数堆大小及关注目标【停顿时间或吞吐量】就可以了。
老年代:
①SerialOld收集器:单线程,采取标记整理算法,主要是Client模式下使用【在Server模式下,在JDK1.5前与Parallel Scavenger配合使用及作为CMS后继方案】
②Parallel Old收集器 :多线程标记整理算法 可以与新生代Parallel Scavenge收集器组合使用
③CMS垃圾收集器:基于标记清除算法。获取最短回收停顿。整个回收包括四个部分:
初始标记:stop the world,标记GC Root能关联到的对象
并发标记:标记出
重新标记:stop the world 标记并发标记期间因程序运作而产生变动的对象
并发清除:
缺点:①对CPU十分敏感,在并发阶段会占用线程导致程序变慢中吞吐量较低,默认开启线程数(cpu+3)/4个并发线 程。
②无法处理浮动垃圾:在并发清除的过程中程序可能会产生新的垃圾,要是程序在CMS并发清理线程运行期间就 会出现Concurrent Mode Failure失败,启动后背方案,临时启用Seiral Old进行清理,性能反而降低
③基于标记-清除算法实现,会产生大量内存碎片而导致Full GC。
④G1收集算法:
网友评论