第一部分、闲扯+概述

近来在研读《深入理解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内存区域划分及垃圾回收的更多相关文章

  1. JVM的内存区域划分以及垃圾回收机制详解

    在我们写Java代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉.因为JVM中有垃圾自动回收机制.在之前的博客中我们聊过Objective-C中的MRC(手动引用计数)以 ...

  2. JVM内存管理机制和垃圾回收机制

    JVM内存管理机制和垃圾回收机制 JVM结构 图片描述: java源码编译成class文件 class文件通过类加载器加载到内存 其中方法区存放的是运行时的常量.静态变量.类信息等,被所有线程共享 堆 ...

  3. JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释

    以下内容转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836 jvm区域总体分两 ...

  4. JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释(转)

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  5. JVM内存区域划分Eden Space,Survivor Space,Tenured Gen,Perm Gen

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  6. JVM内存模型和GC垃圾回收

    JVM 内存区域 1.程序计数器 这是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器,指的是上次代码被执行的地方,线程私有. 2.Java 虚拟机栈 它是 Java方法执行的 ...

  7. [转]JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释

    jvm区域总体分两类,heap区和非heap区.heap区又分:Eden Space(伊甸园).Survivor Space(幸存者区).Tenured Gen(老年代-养老区). 非heap区又分: ...

  8. JVM内存区域划分

    前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...

  9. JVM内存区域划分(JDK6/7/8中的变化)

    前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同 ...

随机推荐

  1. canvas(五)createPattern

    /** * Created by xianrongbin on 2017/3/9. * 图片填充 */ var dom = document.getElementById('clock'), ctx ...

  2. node.js中fs文件系统模块的使用

    node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...

  3. ORACLE多表关联UPDATE 语句[z]

    [z]https://www.cnblogs.com/franson-2016/p/5988303.html 1) 最简单的形式 SQL 代码 --经确认customers表中所有customer_i ...

  4. idea打包含第三方依赖的jar包

    1.打开idea,打开java项目,选择file-->Project Structure,添加依赖的jar包 2.配置artfacts 点击ok,不需要做任何操作 点击jar,右键新建一个lib ...

  5. c# sshnet控制linux 使用unzip的一些问题

    无法使用unzip 解压缩 linux文件夹下的zip文件 于是想在win下生成一个 shell 文件传到linux 下运行,结果这个sh文件在linux  运行时出错,同样的文件在linux下生成就 ...

  6. PHPNow升级PHP版本

    PHPNow升级PHP版本 phpnow下载地址:http://www.jb51.net/softs/12868.html 1,先把PHP5.3.5下载下来,在官网我是没找到VC6的版本,只能从Goo ...

  7. java多线程系列9 高级同步工具(3) CyclicBarrier

    CyclicBarrier 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)   然后一再执行 public class CyclicBar ...

  8. eclipse启动时出现无法创建java虚拟机

    最 近一直在用eclipse开发android程序,今天不知怎么的启动eclipse时就会出现Failed to create java virtual machine,无法打开eclipse程序,折 ...

  9. Eclipse添加JDK,JRE切换

    Eclipse添加JDK Window---preferences 切换JDK,JRE

  10. J2CACHE 两级缓存框架

    概述 缓存框架我们有ehcache 和 redis 分别是 本地内存缓存和 分布式缓存框架.在实际情况下如果单台机器 使用ehcache 就可以满足需求了,速度快效率高,有些数据如果需要多台机器共享这 ...