当前位置:首页 > 内存 > 正文

jvm内存结构详解(jvm的内存结构)

  • 内存
  • 2024-06-01 17:44:57
  • 7147

一、详解JVM内存结构组成

你知道JVM内存的结构吗?下面我给大家分享一下JVM内存的结构。它主要包括两个子系统和两个组件:Runtimedataarea组件(运行时数据区)和nativeinterface(本地接口)。组件

JVM内存结构

最近我研究了一些Java内存泄漏的案例,并与我原来的几个朋友进行了讨论。经过广泛的研究,我发现了这一点。JVM中还有很多以前不知道的细节。这里有一些细节要分析,首先看一下JVM的内部结构——

。如,JVM内存的结构主要包括两个子系统和两个组件。这两个子系统是Classloader子系统和Executionengine子系统。Executionengine子系统的两个组件是Runtimedataarea组件和本机接口。(本地接口)

Classloader子系统的作用

将类文件的内容加载到运行时数据中的方法区(methodarea)中基于给定完全限定类名(例如javalangObject)的区域。Java程序员可以扩展javalangClassLoader类来编写自己的Classloader

执行引擎子系统的作用

执行类中的指令。JVM规范(JDK)实现之一是运行时。不同的JDK,例如Sun的JDK和IBM的JDK,主要取决于它们实现的运行时。好还是坏

原生界面组件

与原生库的交互是其他编程语言交互的接口。当你调用原生方法时,你就进入了一个不再受虚拟机限制的新世界。所以也很容易出现原生heapOutOfMemory。JVM无法控制的

RuntimeDataArea组件

这就是我们常说的JVM内存,它主要分为五个部分——

Heap还有只是Java虚拟实例中的一块堆空间

MethodArea加载的类信息保存在Methodarea内存中。当虚拟机加载某种类型时,它就会被存储。使用类加载器定位对应的类文件然后读取类文件的内容并传输给虚拟机

JavaStack虚拟机(java栈)只会直接对Javastack进行两个操作图像单位。压入或弹出堆栈

ProgramCounter(程序计数器)每个线程都有自己的PC寄存器。线程启动时创建的PC寄存器的内容始终指向下一条要执行的指令。地址这里的地址可以是本地指针,也可以是方法区中方法起始指令对应的偏移量

Nativemethodstack(本地方法栈)存放的是进入该区的native方法的地址


二、JVM内存结构

 ()类加载子系统

 连接初始化

 ()方法区被所有线程共享。垃圾收集还会清理方法区中不可用的类型对象

类加载器加载类时从类文件中获取的类型信息

类的完整有效名称

full以及父类的有效名称(除了interface和javalangObject,因为没有超类)

类型修饰符

类型直接接口列表

b常量池存储所有类型类型使用的常量对字段和方法的符号引用

C域信息jvm必须存储该类型在方法区中的所有字段的相关信息以及字段的声明顺序

字段的相关信息包括

域名

域名类型

域名修饰符(publicprivateprotectedstaticfinalvolatiletransient...)

方法信息

方法名称

方法返回类型

方法参数

方法修饰符

方法字节码(abstract和native除外)(由PC寄存器指向)

操作数栈和方法栈帧的局部变量区大小

异常表

e类的静态变量(所有对象共享一份)

F类的类变量声明为final(所有对象共享一份)

​g对加载类的类加载器的引用

​hClass参考

​i方法表

​j示例

​ClassLava{

privateintspeed=;

voidflow();

}

ClassVolcano{

publicstaticvoidmain(String[]args){

​Lavalava=newLava();

​lavaflow();

​}

}

现在我们描述main()方法第一条指令的字节码是如何在不同的jvm实现中实现的。这只是其中之一。

要运行这程序,您需要以某种方式将Volcano发送到jvm。通过这个名称,jvm找到类文件(Volcanoclass)并读取它,从类文件中提取类型信息并将其放入方法区通过解析方法区中找到的字节码,jvm调用main()方法。在运行时,jvm维护一个指向当前类(Volcano)的常量池。注意jvm已经开始执行了。就像大多数jvm一样,它不会等待所有类加载完毕才开始执行。它仅在需要时启动。

main()的第一条指令告诉jvm为第一个元素中列出的类分配足够的内存。常量池

Jvm使用指向火山常量池的指针来查找它,其中一个发现是对Lava类的符号引用,然后它检查方法区以查看熔岩是否已被加载,引用很简单lava类上的全限定名这里我们看到,对于jvm来说,从一个名字尽快找到一个类是多么重要,还有良好的数据结构如哈希表搜索树等。可以使用同样的算法forName()由类class实现

当jvm发现一个叫Lava的类没有被加载时,它开始搜索并加载类文件Lavaclass,它从类文件中提取类型信息并将其放置在方法区中。常量池的第一个元素这个指针可以用来快速找到lava类。这个替换过程称为常量池溶解。这里我们替换了一个原生指针来为新的熔岩对象分配空间。这一次,jvm是否还需要方法区中一个lava对象需要多少空间的信息?

当jvm知道一个lava对象需要多少空间时,它会在堆上分配空间并初始化该实例的变量速度为默认值如果lava的父对象也有实例变量也会被初始化

当新生成的lava对象的引用被压入堆栈时,第一条指令也会被初始化终止。以下说明使用此引用来激活java代码并将速度变量设置为其原始值。另外,指令将使用此引用来调用Lava对象的flow()方法

()堆在运行时存储所有对象和数组

()每次分配新线程时都会激活堆栈

()PC寄存器(程序计数器)

始终指向指令。线程要执行的指令的位置放在方法区的方法字节码中。26491