JVM内存模型

 一直对jvm内存模型不太清晰,今天看了学习视频深入学习了一下,可能学到的知识也只是皮毛,
 但是在这里还是记录一下,方面今后深入学习,不说废话了,开始记录一下今天的学习内容。 截
 了几张图供学习时参考,下面以Math中的math和main方法作为例子来分析jvm各个区域之间的
 执行及它们之间的关系。

在这里插入图片描述

整个jvm分为三大块区域:类装载区域、运行时数据区、执行引擎区域。

首先,在程序启动时,会编译生成字节码class文件,jvm会将class文件通过类装载子系统把
class文件中的内容通过反编译机制加载到内存模型的方法区中,加载的这部分内容也是常听到的类
元信息(加载一个类的属性、方法等,也可以称之为类模板);

程序开始执行时,会在栈内存中开辟一块空间来执行当前线程,栈中包含多个栈桢,每一个栈桢就相
当于类中的一个方法,类似于图中的math方法和main方法,其中math方法对应一个栈桢,main方
法对应一个栈桢;

每个栈桢中分为几部分区域,分别为局部变量表、操作数找、动态链接、方法出口。

例如程序中的int a = 1,这一个步骤就是将1压入到操作数栈中,然后再将操作数栈中的1赋值到
局部变量,这一步执行完也就是下图中a = 1在局部变量表中所示,同样程序中b、c也是进行同理的
操作(这些步骤将class文件通过javap命令反汇编成可读的jvm执行步骤);栈中的方法出口就是
每个方法执行后所返回的内容并且标识这个方法的结束,在程序执行的每一步,程序计数器都发挥着
作用,它是用来记录下一行代码执行的行号,这个行号就是上边说的反汇编后的文件中可看到的数
字(标识程序运行的每一步)。

在看main方法中,先是new了一个Math,在这个过程中,它是在堆中开辟了一个区域创建了一个
math,然后栈中的局部变量表中的math指向了堆中math的地址,其中堆中math是通过方法区中的类
元信息进行创建的。在整个调用过程中,都是由执行引擎进行着调度,在jdk1.8之前,类元信息都
是在方法区中开辟空间,但在1.8时,将类元信息直接加载到物理内存中也就是下图中的直接内存,
这样也是更好的利用内存空间,毕竟物理内存是会比虚拟机内存空间更充裕的。

在这里插入图片描述

对于堆大致说一下,它分为几个区域:年轻代和老年代,图中年轻代看起来好像占用空间比较大,
实际上老年代会占用三分之二的空间,而年轻代只会占用三分之一的空间;

年轻代中还分为Eden区,From区和To区,所占内存比为8:1:1,其中From区和To区也被称为
Survivor区(也就说说如果整个堆是600M,那么老年代会占400M,年轻代会占200M,Eden区占
160M,Survivor区占40M),下面说一下它们的执行流程。

在执行过程中,当新创建对象之后,也就是程序中new Math的时候是会在Eden区存放,当Eden区
空间全部被占用之后,jvm的执行引擎会开启一个gc的线程去进行垃圾回收,会将没有引用的对象清
除,有地址引用的对象放到From区中,当From区空间被全部占用后,执行引擎也会启用gc垃圾回收
线程去清理无用对象,然后将还有引用的对象放入到To区,此时To区就成为From区,当Eden区进行
gc时,会将还有引用的对象放到现在的From区(也就是刚刚是To区的),当这个From区空间被占满
时,又会调用gc进行垃圾回收,把还有引用的对象放到To区(也就是一开始的From区),From区和
To区循环交替存放还有地址引用的对象,当交替变换15次后(jvm默认,也可通过参数进行设置),
会将还存活的也就是还在引用的对象放入到老年代,当老年代空间也被全部占满后,也会触发gc进行
垃圾回收,但如果老年代中的对象都是引用着的无法清理时,此时程序会抛出OutOfMemoryError
异常,所以如果想要进行jvm调优,大部分还是对堆进行调优,小部分对方法区进行优化。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值