罗罗初探JVM

什么是虚拟机

虚拟机:是一款软件,用来执行一系列虚拟计算机指令
虚拟机可以分为系统虚拟机,程序虚拟机,vmware就属于系统虚拟机,完全就是对计算机的仿真。程序虚拟机的代表就是java虚拟机,在虚拟机中执行的指令就是java字节码指令。java虚拟机存在内存之中,看不见,和vmware不同,vmware是可以看见的。

我们来看看JVM的大概
在这里插入图片描述
类加载器Class Loader
负责加载class文件,class文件在文件开头有特定的文件标识(cafe babe),将class文件加载到内存中,并将这些内容转换成方法区中的运行时数据结构(说白了,方法区就是存储类模板),只要符合文件结构就加载,至于说能不能运行,它不管,由执行引擎Execution Engine负责。

Runtime data area 运行数据区: 我们写的程序都被加载到这里,之后才开始运行。
Runtime data area 运行数据区包括:Method Area方法区,java堆,java栈,本地方法区,PC寄存器
在这里插入图片描述
Method Area方法区
供各线程共享的运行时内存区域。它存储了每一个类的结构信息,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容。上面讲的是规范,在不同虚拟机里头实现是不一样的,最典型的就是永久代(PermGen space)和元空间(Metaspace),但实例变量存在堆内存中,和方法区无关。
注意:jdk1.8之前是永久代(PermGen space),1.8之后是元空间(Metaspace),区别在于永久代使用堆内存,元空间使用的是本机物理内存,jdk1.7版本中已经将永久代 里的字符串常量池移走
Stack栈
栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配。

那栈存储什么呢?
栈帧(方法)中主要保存3类数据:
1.本地变量(Local Variables) :输入参数和输出参数以及方法内的变量;
2.栈操作(Operand Stack) :记录出栈、入栈的操作;
3.栈帧数据(Frame Data) :包括类文件、方法等等。

栈运行原理:
栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,
A方法又调用了B方法,于是产生栈帧F2也被压入栈,
B方法又调用了C方法,于是产生栈帧F3也被压入栈,

执行完毕后,先弹出F3栈帧,再弹出F2栈帧,再弹出F1栈帧…
遵循“先进后出” ,“后进先出”原则。栈的顶部就是当前执行的方法。
每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。栈的大小和具体JVM的实现有关,通常在256K-756K之间,与等于1Mb左右。

PC寄存器
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。

这块内存区域很小,它是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令。
如果执行的是一个Native方法,那这个计数器是空的。

作用:用以完成分支、循坏、跳转、异常处理、线程恢复等基础功能。不会发生内存溢出(OutOfMemory-00M)错误

执行引擎(Execution Engine)
也叫做解释器,负责解释命令,提交操作系统执行, 是核心组件之一,负责执行虚拟机字节码。

Неар堆
一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存逻辑上分为三部分:
Young Generation Space 新生区(1/3):伊甸区,from区,to区
Tenure generation space 养老区(2/3)
Metaspace 元空间
物理上就只有两个部分:
Young Generation Space 新生区(1/3)
Tenure generation space 养老区(2/3)在这里插入图片描述
当伊甸区满了的时候,进行YGC,有幸活下来的对象,复制到from区,再一次伊甸区满出发GC的时候,会扫描伊甸区和from区,对这两个区域进行垃圾回收,如果还有对象存活,直接复制到To区(如果有对象的年龄到达了老年的标准,则复制到老年区),同时把这些对象的年龄+1.然后清空伊甸区和from区中的对象,此时from区没有对象,而to区有对象,那么from就成为了To 区(谁空谁是To),原to区成了from区,部分对象会在from区和to 区之间来来回回复制交换,如果交换了15次,还存活了下来,就存入老年代。如果老年代也满了,就会出现OOM错误。

本地方法栈
与操作系统相关,计算机底层用了C, C++,而java无法直接与操作系统产生联系,所以有了第三方接口,调用本地方法库。

猜你喜欢

转载自blog.csdn.net/qq_42224683/article/details/107289870
JVM
今日推荐