jvm虚拟机内存结构,JVM内存划分

  jvm虚拟机内存结构,JVM内存划分

  我们知道,在C语言中,如果你想使用一个对象,你需要对它执行一个新的操作;如果不使用该对象,需要将其删除。一旦开发人员忘记写delete语句,就会造成内存泄漏。【如果内存被某个对象占用,没有被返回,就叫内存泄漏。】

  Java很聪明。从“手动”进化到了“自动”,把内存的控制权交给了虚拟机。让我们看看jvm是如何执行自动内存管理的。

  如何解决写爬虫IP受阻的问题?立即使用。

  自动内存管理分为两部分:

  为对象分配内存并回收分配给对象的内存。在本文中,我们讨论前者,即内存分区和内存分配。接下来,我们来说说GC(垃圾回收)。

  1、内存划分

  让我们看看虚拟机内存中有什么。JVM的内存区大致分为类文件、类加载子系统、运行时数据区和执行引擎。今天,我们只讨论运行时数据区。【此图基于JDK7。在JDK7之前,常量池存储在方法区。从JDK7开始,常量池就放在堆中了。】

  线程公有

  在运行时数据区,方法区和堆是线程拥有的,也就是说这两个区域是被“回收”的,所以要进行垃圾回收。它是在虚拟机启动时创建的。

  线程私有

  虚拟机堆栈、本地方法堆栈和程序计数器是线程私有的,它们是“一次性的”,因此不需要垃圾回收。

  (一)方法区

  存储由实时编译器编译并由虚拟机加载的数据,如类信息、常数、静态变量和代码。

  有一个运行时常量池。它存储直接引用类文件中描述的符号引用。您可以在编译时和运行时将新的常量放入这个池中。

  (2) 堆

  概念:如果堆栈解决的是程序运行的问题,即程序如何处理数据;那么堆就解决了数据存储的问题,也就是数据怎么放,放在哪里。

  特点:

  a、堆是虚拟机内存中最大的块,约占内存的四分之三。例如,在32位windows平台中,如果每个进程有2GB的内存,则1.5GB的内存通常被划分为堆。可见堆占用的空间是大的。

  b,可以在物理上不连续的内存空间,只要逻辑上连续。

  角色:

  存储对象实例,其中几乎所有的对象实例都分配内存。

  分类:

  从内存回收的角度,可以分为新生代和老一代。

  从内存分配的角度来看,可以分为多线程的私有分配缓冲区。

  (3)虚拟机栈

  虚拟机存储堆栈帧,堆栈帧存储局部变量表、操作数堆栈、动态链接、方法出口和其他信息。

  栈中的栈帧

  每个方法在执行的时候都会创建一个栈帧,一个方法从调用到执行完成的过程,对应的是虚拟机栈中从栈帧到栈帧的过程。

  栈帧中的局部变量表

  它存储编译时已知的各种基本数据类型、对象引用和返回地址类型。因此,所需的内存空间可以在编译期间分配,其大小在运行时不会改变。

  在分配基本数据类型占用的空间时,除了64位的long和double数据类型会占用两个局部变量空间外,其他数据类型只占用一个空间。

  (4)本地方法栈

  本地方法栈的功能与虚拟机栈相同,只是虚拟机栈执行java方法,本地方法栈执行本机方法。

  java方法是开发者编写的java代码,Native方法是java调用非Java代码的接口。

  (5)程序计数器

  程序计数器存储当前线程执行的字节码的行号。当jvm工作时,它通过改变这个计数器的值来选择下一个要执行的字节码指令。

  2、内存分配

  在这一部分,我们讨论对象在java堆中是如何分配、布局和访问的,以及内存分配的原理。

  对象的创建

  让我们用new创建一个对象,看看当系统运行到new时,虚拟机在做什么。这时候的班级就像一块肉,要经过层层安检才能到达人的餐桌。第一步:检查常量池中是否有对应的符号引用。[在方法区域]

  步骤2:检查这个类是否已经被加载、解析和初始化。[在方法区域]

  第三步:获取新对象的内存。有两种方式:指针碰撞和自由列表。[在堆中]

  步骤4:将分配的内存空间初始化为零。

  第五步:对对象进行必要的设置,比如是哪个类实例,对象的哈希代码等等。该信息存储在对象的对象头中。

  步骤6:如果对象在java代码中被赋予了一个初始值,步骤6:执行init方法。这个方法的作用是初始化对象。

  对象的内存布局

  对象内存中的存储布局分为三个部分:对齐和填充对象头实例数据。

  对象头

  对象头中有两部分信息:

  (1)运行时数据,包括哈希代码、GC生成年龄、锁状态标志等。

  (2)类型指针,虚拟机通过该指针确定该对象是哪个类实例。

  示例数据

  存储在实例中的数据是代码中定义的各种类型字段的内容。

  对齐

  对齐用作占位符,但不是必须的。只要保证对象的大小是8字节的整数倍。

  对象的访问定位

  对象创建后,我们就可以使用它了。使用时,如何才能找到自己想要的对象?有两种方式:句柄和直接指针。

  手柄:

  访问是将java堆中的一块内存划分为一个句柄池,句柄包含对象实例数据和类型数据的具体地址信息。

  直接指针:

  直接指针之所以“直接”,是因为它去掉了句柄这个中介。所以比手柄快。在HotSpot虚拟机中,使用了这种方法。

  说完了对象在java heap中是如何分配、布局和访问的,再来说说内存分配的原理。

  内存分配的原则:

  堆大致可分为新生代、老年期和永久期。对象的内存分配主要分配在新生代的Eden区,少数情况下会直接分配到老年。的分配规则不是100%固定的,这取决于垃圾收集器和参数设置的组合。以下是一些分配原则,供参考。

  (1)首先在Eden中分配对象。

  (2)大物件直接进入老年。

  (3)长期存活的对象将进入老年。

  (4)动态物体的年龄判定。

  (5)空间配置的保证。

  以上是JAVA虚拟机中内存的划分。更多问题请访问PHP中文网:JAVA视频教程。以上是JAVA虚拟机(JVM)的详细说明(2)——内存的划分细节。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: