JVM结构与内存模型?(小白篇)

版权声明:禁止转载 https://blog.csdn.net/qq_36505948/article/details/83059147

一、介绍

JVM作为java运行的一个平台,容器,本身也是一个应用程序,它为我们进行java编码提供了很多方便的条件。对于我们学习底层也很重要,那么他是怎么样的一个模型呢?

二、JVM的认识?

作为入门,对JVM的认识要分为两部分,一部分是其结构如何分配,分配的条理是怎么样的。另外一部分的对其内存的基本分析,掌握了这两部分,JVM也算是入门了,可以由大白(●—●)称为小白!

(1):结构模型图

JVM结构模型图_月歌

 在这一步我们需要了解如下:

1.JVM的生命周期?

一个JVM分为守护线程与非守护线程,类似GC则是守护线程,而我们自定义的类则为非守护线程。一个JVM生命周期是跟随当前应用,直到所有非守护线程都结束后,才结束的。只要存在着一个非守护线程则生命周期不能结束!

2.操作系统的结构?(前奏)

如图所示,一个操作系统的存储部分一般可以简单地分为三部分,内存条,PC寄存器,电脑硬盘。内存条里面按照存储和运行不同划分为堆栈,其中栈是运行时单位,栈区负责逻辑的运行,而堆是存储时的单位,堆区负责数据对象的存储。操作系统中的栈区由于操作系统自己管理,堆区由管理员或开发人员负责管理。

PC寄存器,在操作系统中是为了计算机上的硬件,分配计算器的指令,计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机pc寄存器它表现为一块内存(一个字长,虚拟机要求字长最小为32位)虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址,它甚至可以是操作系统指令的本地地址,当虚拟机正在执行的方法是一个本地方法的时候,jvm的pc寄存器存储的值是undefined,所以,虚拟机的pc寄存器是用于存放下一条将要执行的指令的地址(字节码流)

PC寄存器存储的是操作系统下一步的硬件操作和指示,但因为其不是最底层的结构,所以只能被成为 "伪指令"。

电脑硬盘,这个应该不用我说了,就是存储数据的地方。

对于操作系统的理解,PC寄存器发起指令,内存条中的栈区发起应用的调用,加载硬盘中的数据,进入堆区。

3.JVM的内存结构?

JVM的结构跟我们电脑的操作系统非常相似,他存放于我们操作系统中的堆区域!。从操作系统(WINDOWS)角度看JVM就是一个运行与系统内存的java.exe应用!

JVM的内存结构可以类似于操作系统。简单地对应操作系统的堆栈,而方法区用于存放运行后的class字节码文件,可以理解为存储区,类似于操作系统硬盘。他们之间的关系其实是通过cakssloader来关联的,classLoader加载操作系统硬盘中的.class文件,给到方法区,方法区给到堆栈中!

需要明白的是jvm本身是一个提供运行环境的程序或者说是容器,java的虚拟机相当于我们的一个java类,而java虚拟机实例,相当我们new一个java类,不过java虚拟机不是通过new这个关键字而是通过java.exe或者javaw.exe来启动一个虚拟机实例。因此每执行一个应用就会有一个jvm实例启动,一个main方法对应一个jvm实例,有几个main方法则对应了几个jvm。一般一个web项目就是一个main函数的入口。JavaWeb应用程序,本身也可以看成一个main入口发起的应用。

4.简单总结下?

JVM的结构模型与操作系统的模型很相似。当class文件被编译后则会被classLoader加载进入JVM的内存空间。JVM里面划分为方法区(将字节码文件变成内存块的永久存储区,此永久是相对于应用而言),堆,栈,本地方法栈。指令寄存器与计数器(代码的运行和变量的存储,线程的运转都有一定的顺序和步骤),执行引擎(从方法区中读取,完成后置入堆栈中),本地方法接口,本地方法库!以及最后的垃圾收集器。本地方法库的调用都在本地方法栈中


(2):JVM内存模型与字节码信息?

JVM内存模型与方法区字节码信息_月歌

 在这一步我们需要了解如下:

通过第一步,我们可以了解到JVM的内存结构是如何的,JVM到底是个什么东西,数据的大体流向是什么,JVM实例的生命周期和体量如何!  但是,我们仍然不知道,他是如何加载数据的,各个模块的运行都是如何的。方法区里面的字节码文件又有什么东西,只有了解了我们的java代码是如何被加载如何被调用,我们才能将平时的开发与JVM联系起来。从而真正入门JVM的世界~~

1.classLoader的作用?
classLoader存在于jvm中的堆,当一个classLoder启动的时候,它会去电脑硬盘上将xxx.class文件装载到jvm中的方法区,方法区中的这个字节文件会被虚拟机拿来new xxx字节码(),然后在堆内存生成了一个A字节码的对象,A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader。

方法区对于JVM来说就像是操作系统的电脑硬盘一样,起着存储的功能!

2.字节码内存块的信息?

ClassLoader将数据加载到方法区后,其实是将字节码以内存块的形式存储的,这个内存文件中存在的两个引用都是什么,是如何处理的?字节码文件的内存块中主要是对java文件的编译,经过编译后成为适合系统使用的二进制文件(机器语言)。我们可以通过反编译文件进行解析(查看源码的技巧之一,但不适合还原项目开发,反编译后的代码会比较简约,可读性大幅度降低)。

 仔细观察,内存块里面的内容也是我们在编译一个java类的内容,行为和属性分别表示方法和变量,类的修饰符,子类父类路径名称,局部变量,以及类到class的引用,类到classLoader的引用,以及方法表(将类中的行为和属性做成引用方便快速调用类似缓存的查找表)。

其中方法表参考如下解释:如果学习c++的人应该都知道c++的对象内存模型有一个叫虚表的东西,java本来的名字就叫c++- -,它的方法表其实说白了就是c++的虚表,它的内容就是这个类的所有实例可能被调用的所有实例方法的直接引用。也是为了动态绑定的快速定位而做的一个类似缓存的查找表,它以数组的形式存在于内存中。不过这个表不是必须存在的,取决于虚拟机的设计者,以及运行虚拟机的机器是否有足够的内存!


首先,当一个程序启动之前,它的class会被类装载器装入方法区(存储字节码文件的区域),执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置(每一个web应用也可以理解为由一个main函数启动的应用),虚拟机开始为main函数在java栈中预留一个栈帧(每个类中的方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统APIi等等。

这里的本地指的是电脑的操作系统,本地方法接口也是本地电脑操作系统(windows)提供的相应接口,而不是代码本身的方法,代码本身的方法被映射后变成了一序列的逻辑和指令,通过调用操作系统的一些指令而完成!

猜你喜欢

转载自blog.csdn.net/qq_36505948/article/details/83059147
今日推荐