JVM内存区域划分及垃圾回收
第一部分、闲扯+概述
近来在研读《深入理解java虚拟机》一书,读完之后做个小结,算是记录一下自己的学习所得,在成长的路上,只能死磕。
要理解JVM,就要先从其内存区域划分开始,知道其由几部分构成,再了解各部分的功能,这样就能对其整体有一个了解。
话不多说,总体图先呈上:

可以看到,线程私有的内存区域有虚拟机栈、本地方法栈、程序计数器,这些区域都不会出现线程安全问题;而线程共享的区域有堆、方法区。
下面对其各个分区域进行介绍。
第二部分:JVM内存区域划分
1、首先是最简单的程序计数器,每个线程都有一个独立的计数器,用来记录线程执行的虚拟机字节码指令。另外,如果是Native方法,则计数器中的
值为undifined。
2、本地方法栈:类似于虚拟机栈,只是此处运行的是native方法
3、虚拟机栈:运行java方法的地方,基本单位是栈帧,一个方法从开始执行到结束的过程,就是一个栈帧在虚拟机栈中入栈到出栈的过程。(本来
认真准备了两张栈帧跟局部变量表的逻辑示意图,不知道怎么的传不上来,只能省去,<手动擦汗>)
3.1、局部变量表:顾名思义,是存返方法中变量的地方。
局部变量表存放变量的单位是Slot 槽,每个槽都能存放一个32位的变量,64位的由连续的两个槽来存放。如果执行的是非static方法,则第一个槽中
存放的是当前对象的引用,即this。具体存放的引用,是直接或间接能定位到这个对象在堆中的位置的一个值,比如对象的起始地址。
3.2、操作数栈:是LIFO(后入先出)栈,虚拟机就是一个基于操作数栈的执行引擎。在处理数据中处于重要位置。一个32位的数据占据栈中一个容量。比如执行a+b时,字节码
指令会先往栈中压入a跟b,然后iadd指令执行时,将栈顶的两个值a跟b弹出,相加,再压入栈中,完成计算。
3.3、动态链接:存放的是方法区的运行时常量池中此栈帧对应的方法的引用
3.4、返回地址:记录方法执行完之后返回的位置,回到这个位置程序才能正确的继续执行下去。
4、方法区:最主要的功能,便是存放字节码文件、Class对象、常量等
5、堆区:此部分是虚拟机中上连栈下连方法区的中枢之地,也是垃圾收集的重地,可以说基本所有的对象都存放在此区域。
对象在堆区中,由三部分组成:对象头、实体数据、对齐填充
对象头:一般由两部分组成,一部分是用于存放hash值、分代年龄、锁标识的称为Mark Word的区域,另一部分用于存放指向方法区中对象类型的指针(直接指针定位时有);
实体数据:存放正常的对象数据;
对齐填充:对象的内存占用大小为8字节的整数倍,如果不够,用此部分来填充。
堆区按照垃圾收集区域,划分为两部分:新生代、老年代,一般默认比例是1:2,而在新生代中,又分成了三部分,分别为Eden、Survivor From 、Survivor To ,默认比例
为8:1:1。
第三部分、垃圾回收
触发条件:当内存中可用空间不够时才会触发垃圾回收
什么样的对象会被回收:通过可达性分析算法,如果发现某个对象与GC ROOTS没有连接,则此对象满足被回收的条件。
GC ROOTS定义:1) 虚拟机栈中引用的对象;2)本地方法栈中引用的对象;3) 类静态属性引用的对象;4) 常量引用的对象
如何回收:标记清除算法、复制算法、标记整理算法、分代搜集算法,目前主流虚拟机中使用的就是分代搜集算法
分代搜集算法的过程:JVM开发团队发现,对于新生代中大部分的对象,存活时间都很短,所以新生代使用复制算法,且工作空间与空闲空间之比为9:1(9即上面所说的一个
Eden与Survivor From之和),因为新生代绝大部分对象会被清理,清理之后还剩下的对象就放在那一份的Survivor To中,如果空间不够,再往老年代放,另外经历过一定次数的
新生代处理还没被回收的对象,也会转移到老年代中;而对于老年代,用标记整理算法或者标记清除算法,因为老年代对象数量庞杂,且大多数不满足清理条件,所以老年代的
垃圾回收耗时长效果相对较差。新生代中Eden区域专门用于存放新对象,如果此区域内存空间不足,则触发新生代GC,此之谓Minor GC;同样老年代空间不足,触发Full GC(亦
称之为Major GC),耗时长,要尽量避免,一般来说Full GC次数一天不能超过一次。
垃圾收集器:针对新生代跟老年代都有不同的垃圾搜集器,例如针对新生代的有Serial、ParNew等,针对老年代的有CMS、Serial Old等,不同的搜集器之间只能有特定的
几个组合(不能随意地组合使用,会有不兼容),具体看项目实际情况而定。目前BZ所在公司用的是ParNew与CMS的组合,虽然CMS用的是标记清除算法,会使垃圾收集后的内存
碎片较多,但是万能的前辈们早就想到了这些,提供了-XX:+UseCMSCompactAtFullCollection指令压缩内存中的碎片,以及-XX:CMSFullGCsBeforeCompaction指令设置多少次
Full GC后整理内存碎片。
针对垃圾收集这一块,BZ还没有实际动手通过相关知识解决过项目中的问题,目前只是纸上谈兵,后面会摸索一下如何通过工具监控项目中的内存状况,并整理出来。学习之
路,还是要多给自己打打鸡血~
JVM内存区域划分及垃圾回收的更多相关文章
- JVM的内存区域划分以及垃圾回收机制详解
在我们写Java代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉.因为JVM中有垃圾自动回收机制.在之前的博客中我们聊过Objective-C中的MRC(手动引用计数)以 ...
- JVM内存管理机制和垃圾回收机制
JVM内存管理机制和垃圾回收机制 JVM结构 图片描述: java源码编译成class文件 class文件通过类加载器加载到内存 其中方法区存放的是运行时的常量.静态变量.类信息等,被所有线程共享 堆 ...
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
以下内容转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836 jvm区域总体分两 ...
- JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释(转)
jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- JVM内存区域划分Eden Space,Survivor Space,Tenured Gen,Perm Gen
jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- JVM内存模型和GC垃圾回收
JVM 内存区域 1.程序计数器 这是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器,指的是上次代码被执行的地方,线程私有. 2.Java 虚拟机栈 它是 Java方法执行的 ...
- [转]JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...
- JVM内存区域划分
前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...
- JVM内存区域划分(JDK6/7/8中的变化)
前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...
随机推荐
- Java16-java语法基础——异常
Java16-java语法基础——异常 一.异常概念 1.异常:应用程序在运行过程中出现的错误或非正常的意外情况,即虚拟机的通常操作中可能遇到的异常,是一种常见的运行错误. 2.原因:数组越界.空指针 ...
- 贝叶斯---最大似然估计(高翔slam---第六讲 )
1.贝叶斯---最大似然估计 回顾一下第二讲的经典SLAM模型: 通过传感器(例如IMU)的运动参数u来估计运动(位姿x)[定位],通过相机的照片的观测参数z来估计物体的位置(地图y)[建图],都是有 ...
- python小结 1
1.变量 记录状态 类型:数字,字符串,元组,列表,字典 可变不可变(内存地址不变的情况下,值能不能改变): 不可变:字符串,数字,元组 可变:列表,字典 访问顺序: 直接访问:数字 有序:字符串,列 ...
- mysql c-api 预处理语句
stmt = mysql_stmt_init(mysql) mysql_stmt_prepare(stmt, "SELECT ?", strlen("SELECT ?&q ...
- js 定时更改div背景图片
今天遇到一个业务场景,使用js将一个div标签的背景图片定时更换一下. 之前百度了几个,有css+js,也有css3的,不过css3的兼容有问题,之后同事提示,可以使用js直接来更换div的北京图片, ...
- 基于Zxing的二维码的二维码扫描之横屏扫描
最近项目条码扫描要改为横屏,网上所搜了一下,然后发现我写的需要改动几行代码就可以了,还是很给力的. 如未查看之前的代码,请移步: 基于Zxing的二维码生成和二维码扫描 修改下面写代码就可以实现横屏条 ...
- 【转】《深入理解C# 3.x的新特性》博文系列汇总
[转]<深入理解C# 3.x的新特性>博文系列汇总 较之C# 2.0, C# 3.x引入了一系列新的特性,为我们编程带来很大的便利,通过有效地利用这些新特性,我们可以编写出更加简洁.优雅的 ...
- IDA显示字节机器码
默认居然不显示,有点坑. 要像CE一样显示出来,需要 菜单 Options >> General Disassembly选项卡Number of opcode bytes写上非0,写1好像 ...
- vim折叠设置(转载)
vim折叠设置(转载) set foldmethod=indent "set default foldmethod"zi 打开关闭折叠"zv 查看此行zm 关闭折叠zM ...
- ESP32 windows开发环境的搭建(官方方法)
首先保证电脑中的已经下载了git客户端,没有的自行去https://git-scm.com/下载 STEP1: 获得编译工具链 Windows没有内置的“make”环境,所以安装工具链你将需要一个兼容 ...