Java的内存区域

java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外的人想进去,而墙内的人想出来。[来自深入理解java虚拟机]

对于java程序员来说,在虚拟机自动内存管理机制的帮助下,不需要对每个new的对象手动释放内存,也不容易触发内存泄漏和内存溢出的问题,但是一旦触发这个问题,如果我们不了解虚拟机对内存的使用原理,是很难找到问题的。

所谓java的内存区域,主要是运行时数据区域。java虚拟机在运行java程序时,将它所管理的内存划分成不同的区域,每个区域有各自的作用对象和生存周期。根据java虚拟机规范1.7的规定,把内存划分成这几个部分:程序计数器,java虚拟机栈,本地方法栈,java堆,方法区。如图一所示,

图一  java运行时数据区域

接下来就分别来描述这几块区域的定义以及作用:

程序计数器

程序计数器时一块很小的内存区域,用来记录线程执行到的位置。因为java虚拟机的多线程时通过线程轮流切换和分配处理器执行的方式实现的,所以当一个线程恢复时,能够找到到正常的执行位置。由此可见,此区域也是线程私有的,各个线程之间互不影响。

java虚拟机栈

虚拟机栈和程序计数器一样也是线程私有的,生命周期与所属的线程同步。当虚拟机在执行一个方法的同时会创建一个栈帧,用来存储局部变量,方法出口,动态链接等信息。一个方法的调用和执行,就对应着一个栈帧从虚拟机栈中入栈和出栈的过程。

局部变量表中存放基本数据类型,int,boolean,byte,char,short,long,double,float,对象的引用,这些在编译期间她们的大小就是已知的,当执行一个方法时,需要在栈帧中分配多少内存也是固定的,在方法执行的过程中时不变的。

这个区域可能会出现两种异常:StackOverflowError,OutOfMemoryError,当线程请求的栈深度大于虚拟机允许的最大深度会抛出StackOverflowError异常,不过一般虚拟机都会动态扩展,但是如果扩展时没有足够的内存就会抛出OutOfMemoryError。

本地方法栈

本地方法栈和虚拟机栈的作用时相似的,只不过本地方法栈为虚拟机使用到的Native方法服务。有些虚拟机就把本地方法栈和虚拟机栈合二为一了。

java堆

java堆与前几块区域不同,它是虚拟机中所有线程共享的一块区域,在虚拟机启动时创建。对于大部分应用来说,java堆时虚拟机所管理的内存中最大的一块。用来存放对象实例和数组。

java堆也是垃圾收集器所管理的主要的区域,因此有时它也被称作GC堆(Garbage Collected Heap)。由于现在的垃圾收集器一般都采用分代收集算法,所有java堆又被分为新生代和老年代,新生代中存活的对象比较少,老年代中存活的对象占大部分,垃圾回收这部分内容在后续的文章中将会描述。

另外java堆物理上可以分配在不连续的内存空间中。当没有足够的内存分配实例或数组,并且无法再扩展时,就会抛出OutOfMemoryError。

方法区

方法区和堆一样也是线程共享的区域,用于存放已经被虚拟机加载的类信息,常量,静态变量等。它在java虚拟机规范中被描述为java堆的一个逻辑部分,而且对它的限制也比较宽松,例如可以分配在不连续的内存空间上,大小可以扩展也可以固定(不同虚拟机实现不一样)。有时,方法区又被称作永久代,但是进入到此区域的数据一样会被回收。这个区域的内存回收主要针对常量池的回收和类卸载。不过这个部分的回收限制比较多,所以回收的效率比较低。它也会抛出OutOfMemoryError。

运行时常量池

运行时常量池时方法区的一部分。它用于存放编译期间生成各种字面量和符号引用,在类加载后进入方法区的运行时常量池。java虚拟机对Class文件的格式又严格的规定,每个字节用于存放那种数据都符合规范时才能被虚拟机认可,装载和执行,这部分内容在后续文章也会有描述。

运行时常量池还具有动态性,并非只有在编译期间生成的常量才会放入运行时常量池,运行期间也可能将生成的常量放入其中,例如String类的intern()方法。另外它也会抛出OutOfMemoryError

直接内存

直接内存不是java运行时数据去的一部分,也不是虚拟机规范中定义的内存区域,但是它也被频繁的调用,有时也会抛出OutOfMemoryError。在JDK1.4之后引用了一种基于通道和缓冲区的I\O方式,它使用Native函数库直接分配内存,然后通过存储在java堆中的DirectByteBuffer对象作为内存的引用进行操作,避免了java堆和Native堆中来回复制,提高了性能。

直接内存不受java堆内存大小的限制,但是也会受设备总内存大小以及处理器寻址空间的限制。

时间: 2024-11-02 08:51:05

Java的内存区域的相关文章

Java虚拟机内存区域详解

众所周知,Java程序运行于Java虚拟机(JVM)上,那么,JVM运行的时候内存是如何分配的呢?程序中各部分变量都存储在内存的哪个部分,又如何访问,下面,就让我来给大家讲解Java虚拟机内存区域. 为什么需要了解Java虚拟机内存区域 相对于C++程序员,因为虚拟机的自动内存管理机制的存在,Java程序员很多时候并不需要去担心内存的泄露和内存溢出的问题.但是正是因为把内存的控制权交给了JVM,一旦出现内存泄露和溢出的问题,如果不了解虚拟机怎么使用内存,就很难排查错误. 内存泄露:一些对象在使用

java虚拟机内存区域的划分以及作用详解

序言 为什么有时候学着学着会突然之间觉得一切度是那么无趣,男的每个月也有那么几天难道?哈哈,不然是什么,我还是要坚持,可以做少一点,但是不能什么度不做.总会过去的,加油 --WH 一.运行时数据区 什么叫运行时数据区呢,看下图就知道了,今天的重点就围绕这张图讲. 1.程序计数器(寄存器) 当前线程所执行的字节码行号指示器 字节码解释器工作依赖计数器控制完成 通过执行线程行号记录,让线程轮流切换各条线程之间计数器互不影响 线程私有,生命周期与线程相同,随JVM启动而生,JVM关闭而死 线程执行Ja

Java虚拟机内存区域堆(heap)的管理

在上一节中Java 出现内存溢出的定位以及解决方案 中对于Java虚拟机栈以及方法区的内存出现的异常以及处理方式进行了解析,由于Java虚拟机对于堆的管理十分复杂,并且Java虚拟机中最基本的内存区域,所以单独提出一节进行分析. 先来解释一下对象存活?? 什么样的对象是已经死了的对象,须要垃圾回收器进行回收.这个概念至关重要.由于它影响到垃圾回收器对于哪一个对象进行回收.能够从GCRoot訪问到的对象是存活的对象,那么以外的对象就是已死的对象. GCRoot:包含四种 1)Java虚拟机栈中存放

《深入理解Java虚拟机》笔记 第二章 Java虚拟机内存区域

? ? 这句话感觉道出了GC的本质 ? ? ? ? ? ? 1.程序计数器(Program Counter Register) ? ? 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改为这个计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成. ? ? 由于Java虚拟机的多线程是通过线程轮流切换CPU时间片的方式来实现的,所以在任何一个时刻,一个处理器(对于多核处理

Java 虚拟机内存区域划分详解(1)

一.概述 对于 C 和 C++程序开发的开发人员来说,在内存管理领域,程序员对内存拥有绝对的使用权,但是也要主要到正确的使用和清理内存,这就要求程序员有较高的水平. 而对于 Java 程序员来说,在虚拟机的自动内存管理机制的帮助下,不再需要为每一个 new 操作去写配对的 delete/free 代码,而且不容易出现内存泄漏和内存溢出问题,看起来由虚拟机管理内存一切都很美好.不过,也正是因为 Java 程序员把内存控制的权力交给了 Java 虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚

Java虚拟机内存区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间.根据Java虚拟机规范,包括以下几个运行时数据区. 一.程序计数器 内存空间:较小. 作      用:当前线程所执行的字节码的行号指示器. 特性分析:Java虚拟机的多线程的执行是由线程轮流切换并分配处理器执行时间来完成的.在确定的某个时刻,一个处理器只会执行一条线程中的指令.因此,为了线程切换后能恢复到正确的的执行位置,每条线程都需要一个独立的程序计数器,各个线

java虚拟机内存区域理解

java虚拟机有的区域随着虚拟机进程的启动而存在, 有的区域依赖用户线程的启动和结束而建立和销毁. 程序计数器:为了线程切换后能恢复到正确的执行位置,每个线程都有一个独立的程序计数器.(针对java方法,即栈) 虚拟机栈:为了虚拟机执行java方法,线程创建时就会创建一个栈帧,存储局部变量表.操作数栈.动态链接等. StackOverFlowError:线程请求的栈深度大于虚拟机所允许的深度: OutOfMemoryError:动态扩展是无法申请到足够的内存. 本地方法栈:为了虚拟机使用到Nat

java jvm 内存区域

程序计数器:可以看作是当前线程执行字节码的行号器.每个线程都有一个自己的程序计数器.字节码执行判断 循环等操作是就是改变程序计数器的值来完成操作的. 注意:当前的线程执行的是Native方法的时候,程序计数器的值为空.调用本地方法的时候回重新起一个线程去执行本地方法,当前的线程阻塞到新起的线程执行完毕. JAVA虚拟机栈:java 虚拟机栈也是线程私有的 .java虚拟机栈是java方法执行的内存模型.每个方法在执行的时候都会创建一个栈帧,这个栈帧用于存储局部变量表,操作数栈,动态链表,方法出口

Java 虚拟机-Java内存区域

简要介绍Java的内存区域: 运行时数据区域 HotSpot虚拟机对象 一.概览 二.运行时数据区域 2.1 程序计数器 Program Counter Register,代表当前线程所执行的字节码的行号指示器,操作系统中的PC,这两个是一个概念.执行时就是通过改变这个计数器来选取下一条需要执行的字节码指令.Java支持多线程,所以每个线程有自己独享的PC,类似于操作系统线程表中的一个属性. 2.2 Java虚拟机栈 和PC一样,是线程私有的,和线程的生命周期一样.虚拟机栈描述的是Java方法执