Java虚拟机(JVM)内存区域

        Java虚拟机内存区域分为五部分:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。其中程序计数器、Java虚拟机栈、本地方法栈属于线程私有内存区,其生命周期与线程相同,随线程的产生而产生,随线程的消亡而消亡。这几个区域的内存在方法或线程结束时,自然就跟着回收了。因此这三个区域的内存分配和回收具有确定性,不需要考虑内存回收的问题。而Java堆和方法区属于线程共享内存区,所有线程都可以访问。只有在程序运行期间才能知道创建哪些对象,因此这两个区域的内存分配和回收都是动态的,也是垃圾收集器收集的主要区域。

下面分别介绍这五个区域。

1)       程序计数器

程序计数器是一块较小的内存空间,可以当做线程执行的字节码行号指示器。字节码解释器工作的时候就是通过改变程序计数器的值,来选取下一条所要执行的字节码指令,分支、跳转、循环、异常处理、线程恢复等都需要依赖程序计数器来完成。程序计数器是Java虚拟机中唯一不会发生内存溢出(OutOfMemoryError)的区域。

Java虚拟机的多线程是通过线程间的轮流切换并分配处理器执行时间的方式来完成的,任意时刻一个处理器只会执行一条线程中的指令。为了使线程切换后能恢复到正确的执行位置,每个线程都有一个独立的程序计数器,各线程之间独立存储、互不影响,因此是线程私有内存区。

2)       Java虚拟机栈

Java虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行结束都伴随着一个栈帧在虚拟机栈中从入栈到出栈的过程。

Java虚拟机栈也是线程私有内存区,生命周期与线程相同。基于栈的内存区域都可能发生两种异常:栈溢出和内存溢出。如果线程请求栈的深度大于虚拟机栈所允许的最大深度,并且无法扩展时,将会发生栈溢出(StackOverflowError)异常;如果可以扩展,在扩展时无法申请到足够的内存,将会发生栈溢出(OutOfMemoryError)异常。

局部变量表用于存放方法参数和方法内部定义的局部变量,其数据类型是编译期可知的各种基本数据类型、对象引用类型(reference)和返回(returnAddress)类型(它指向了一条字节码指令的地址)。局部变量表所需的内存空间在编译期间完成分配,即在Java程序被编译成Class文件时,就确定了所需分配的最大局部变量表的容量。当进入一个方法时,这个方法需要在栈中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

3)       本地方法栈

本地方法栈与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务(即程序员自己写的方法),而本地方法栈则为使用到的本地操作系统(Native)方法服务。本地方法栈也是基于栈,因此也会发生栈溢出或内存溢出异常。

4)       Java堆

Java堆是虚拟机所管理的最大一块内存,是所有线程共享的一块内存区域,在虚拟机启动时创建。Java堆用来存放对象实例,几乎所有的对象实例和数组都在这里分配内存。Java堆是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”。

Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。在实现时,既可以是固定大小的,也可以是可扩展的,目前主流虚拟机都是可扩展的。如果在堆中没有足够的内存可分配,且无法扩展时,将会抛出内存溢出异常。

从垃圾收集的角度来看,Java堆还可以细分为新生代和老年代。新生代包括Eden、Survivor from、Survivor to,详情请见下面下面一章。

5)       方法区

方法区也是线程共享的内存区域,用于存储被虚拟机加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据。

和堆一样,方法区同样可以处于物理上不连续的内存空间中,只要逻辑上连续即可。在实现时,既可以是固定大小的,也可以是可扩展的。方法区可以不进行垃圾收集,相对而言,方法区的垃圾收集行为很少,主要是对常量池的回收和对类型的卸载。当方法区没有足够的内存完成分配时,会发生内存溢出异常。

平时所说的“永久代”(PermGen space)指的是方法区。

“运行时常量池”是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。运行时常量池具有动态性,常量既可以在编译期产生并进入常量池,也可以在运行期间进入常量池,常见的是String类的intern()方法。运行时常量池是方法区的一部分,因此也会发生内存溢出异常。

转载请注明出处 https://www.cnblogs.com/Y-oung/p/9762682.html

工作、学习、交流或有任何疑问,请联系邮箱:[email protected]

原文地址:https://www.cnblogs.com/Y-oung/p/9762682.html

时间: 2024-08-05 10:13:31

Java虚拟机(JVM)内存区域的相关文章

深入Java虚拟机——JVM内存详解

在C++中,程序员拥有每一个对象的所有权,但与此同时还肩负着释放对象内存空间的责任:而Java由于有了虚拟机的帮助,程序员拥有对象的所有权的同时不再需要释放对象的内存空间.由于是JVM自动进行对象内存的释放,所以内存泄漏和内存溢出的问题也很少出现. Java虚拟机在运行时将内存空间分成5个部分,分别是:方法区.虚拟机栈.本地方法栈.堆.程序计数器. 程序计数器 本质 程序计数器本质上是一块较小的内存空间. 作用 可以把程序计数器简单地看作是当前线程所执行的字节码的行号指示器. 字节码解释器在工作

Java虚拟机各内存区域的位置及功能的介绍

Java虚拟机运行时数据区: 相关区域介绍: 程序计数器: 功能:当前线程所执行字节码的行号指示器.若是Java方法记录指令地址,若为Native方法,则不记录 隔离性:线程隔离 Error:无 Java虚拟机栈: 功能:描述Java方法执行的内存模型:每个方法执行的同时都会创建一个栈帧,用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 隔离性:线程隔离 Error:线程请求的栈深度大于虚拟机所允许的深度时,抛出 StackOverflowError 异常: 动态扩展时无法申请到足够的内

深入理解Java虚拟机笔记---内存区域

Java虚拟机在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有自各的用途,以及创建及销毁时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁.根据<Java虚拟机规范(第2版)>规定,Java虚拟机管理的内存区域包括以下几个运行时数据区域,下如图 1.程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过

java虚拟机01-java内存区域与内存溢出异常

1.运行时数据区域 1.程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行字节码的行号指示器,字节码解释器工作时就是通过改变程序计数器的值来选取下一条指令的地址.分支.循环.跳转.异常处理.线程恢复等基础功能都是由这个计数器来完成.    每一条线程都要有一个属于自己的独立的程序计数器,所以该块内存是线程私有的    如果当前执行的是一个java方法,则这个计数器记录的是正在执行指令的字节码地址:如果当前当前执行的是一个native方法,则计数器的值为空 (undefined)    

JAVA虚拟机JVM-1.内存区域

运行时数据区域 包含:程序计数器,java虚拟机栈,本地方法栈,java堆,方法区,运行时常量池.具体相关结构如下图. 区域 是否公用 相关概念 其他描述 程序计数器 线程私有 当前线程执行的字节码行号指示器 如果当前线程执行的java方法,那么计数器 java虚拟机栈 线程私有 java方法执行的线程内存模型 方法执行的时候创建的栈帧用户保存局部变量表,操作数栈,动态链接,方法出口等信息.可能抛出StackOutflowError异常. 本地方法栈 线程私有 本地方法执行的线程内存模型 本地N

Java虚拟机的内存区域

本博文只是源自周志明<深入理解Java虚拟机> Java运行数据区图解: 程序计数器图解: Java的虚拟机栈图解: Java的本地方法栈图解: Java堆图解: 直接内存图解:

深入理解java虚拟机一 JAVA运行时内存区域与class文件

一 JAVA运行时内存区域 JVM在加载class文件时,会将class文件定义的数据结构转为运行时内存中的数据,那么jvm是如何安排运行时的内存区域呢? jvm将运行时内存划分为以下几个部分: 堆:所有线程共享 方法区:类信息.静态变量.常量等 运行时常量池:class文件的常量池(字面常量和符号引用)+运行时产生的常量 程序计数器:  当前线程执行的字节码的行号指示器 虚拟机栈:栈帧 = 本地局部变量表.操作数栈.动态链接.出口信息 本地方法栈:native方法 直接内存:不属于jvm管理,

【Java高级】JVM内存区域模型和加载过程

JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中.

Java虚拟机的内存管理

众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某程度上,当出现内存泄漏,Debug会变得难度更大. 所以,Java程序员,有必要去了解Java虚拟机对于内存的管理以及垃圾回收的机制. Java虚拟机是如何判断一个对象可以回收? 当一个对象没有被任何其他所引用时,这个对象被Java虚拟机视为可回收. 早起的虚拟机,使用引用计数的方法判断对象是否可回

深入理解JVM之JVM内存区域与内存分配

深入理解JVM之JVM内存区域与内存分配 在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处: http://www.cnblogs.com/hellocsl/p/3969768.html?utm_source=tuicool&utm_medium=referral 看了此博客后,发现应该去深入学习下jvm的内存模型,就是去认真学习下<深入理解Java虚拟机>,其内容可能会<