浅谈JVM内存分配

JVM 内存分配

  由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。如下是具体java程序的执行过程:
在这里插入图片描述
 首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。

运行时数据区通常包括这几个部分:

1.程序计数器(Program Counter Register)、
2.虚拟机栈(VM Stack)、
3.本地方法栈(Native Method Stack)、
4.方法区(Method Area)、
5.堆(Heap)。 如下图所示:
在这里插入图片描述

运行时存储区具体存储了哪些数据?

1. 程序计数器:
* 本质:程序计数器本质上是一块较小的内存空间。
可以把程序计数器简单地看作是当前线程所执行的字节码的行号指示器。 字节码解释器在工作时,通过改变程序计数器的值来选取下一条需要执行的字节码指令。 除此之外,程序的分支、循环、跳转、异常处理、线程恢复等基本功能都需要依赖程序计数器来完成。
* 特性:程序计数器是一个个线程私有内存。每个线程都私有一个程序计数器,用来记录线程当前执行的位置,好让线程恢复执行的时候知道上一次执行的位置。所以各个线程之间的计数器相互独立,互补影响。
 若线程正在执行的是一个Java方法,那么当前线程的程序计数器记录的是正在执行的虚拟机字节码指令的地址;若线程正在执行的是一个Native方法,则这个计数器值为空。 注:Native方法是指不使用Java语言写的方法,或者是使用Java语言写的直接操控计算机硬件的方法。
2. java 栈:
* 本质:JVM栈是用来描述Java方法执行过程的一个内存模型。
  JVM栈中存放着一个个栈帧,每个栈帧都对应着一个Java方法。 当一个Java方法被执行时,JVM会在JVM栈中创建一个栈帧,用于存储:局部变量表、操作数栈、动态链接、方法出口等信息。
每一个Java方法被调用到执行完成的过程,都对应着一个个栈帧在JVM栈中的入栈和出栈。
* 特性:JVM栈是线程私有的,每一个线程拥有一个独立的JVM栈,这个线程中所要执行的方法就会在它所对应的JVM栈中创建栈帧。
3. 堆:
* 本质:堆内存的唯一目的就是存放所有的对象实例。
 Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。Java的垃圾回收机制会自动进行处理,这部分空间也是Java垃圾收集器管理的主要区域,又称GC堆。
 从jdk1.7 之后,常量池就存放在堆中,而不是在方法区。类中不被关键字static修饰,产生一个对象,则存放在堆中。
在堆中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。当然并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。
* 特性:堆是被所有线程共享的,在JVM中只有一个堆。
4. 方法区:
* 本质:方法区也是JVM需要使用的一块内存区域,它用来存储已经被JVM加载的类的信息、常量、静态变量(static修饰)、编译后的代码等数据。 也是被线程共享的区域。
注:在JVM规范中,没有强制要求方法区必须实现垃圾回收。很多人习惯将方法区称为“永久代”,是因为HotSpot虚拟机以永久代来实现方法区,从而JVM的垃圾收集器可以像管理堆区一样管理这部分区域,从而不需要专门为这部分设计垃圾回收机制。不过自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。
5. 本地方法栈:
* 本质: 本地方法栈则是为执行本地方法(Native Method)服务的,用于管理本地方法的调用,本地方法不是java实现的,而是使用C实现的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一,不区分本地方法栈和虚拟机栈。
(HotSpot VM,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。)

谈谈栈与堆的存储:

* 栈是运行单位,堆是存储单位 。
1.堆(对象):
 引用类型的变量,其内存分配在堆上或者常量池(字符串常量,基本数据类型常量),需要通过new等方式创建。
 堆内存的主要作用是存放运行时new创建的对象。(主要用于存放对象,存取速度慢,可以运行时动态分配内存,生存期不需要提前确定)。
2.栈(基本数据类型变量,对象的引用变量):
 基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放。
 栈内存的主要作用是存放基本数据类型和引用变量。栈的内存管理是通过栈的"后进先出"模式来实现的。(主要用来执行程序,存取速度快,大小和生存期必须确定,缺乏灵活性)

Last:以上内容从网络摘抄总结,如有错误,欢迎评论交流HooHoo!!!

猜你喜欢

转载自blog.csdn.net/nn1__2970/article/details/83384792
今日推荐