jvm的内存区域简介

1.内存区域划分

jvm在执行java程序过程中会将管理的内存划分成若干不同的数据区域,他们分别是程序计数器,堆,方法区,虚拟机栈,本地方法栈。

1.1指令计数器

指令计数器是线程私有的,每个线程都有独立的指令计数器,计数器记录着虚拟机正在执行的字节码的指令地址,分支,循环,跳转,异常处理和线程恢复等操作都依赖这个计数器完成,如果线程执行的native方法,则这个计数器为空。

1.2虚拟机栈

虚拟机栈是线程私有的,主要用于存放局部变量表,操作栈,动态链接,方法出口等信息,由于每个方法被执行都会创建对应的线帧,方法被调用到直至完成调用的过程,实际对应线帧在操作栈中入栈和出栈的过程。在java虚拟机规范中,对这个区域规定了两种异常情况:如果线程请求的栈深度大于规定的深度,则抛出StackOverFlowError异常;如果虚拟机栈的动态扩展到了无法申请的足够内存时候将抛出OutOfMemberError异常。

1.3本地方法栈

本地方法栈和虚拟栈的功能相似,包括上述2个异常情况也一样,区别在于虚拟机栈是为虚拟机执行的java服务,而本地方法栈是为虚拟机使用的Native方法服务。

1.4堆

堆是内存中最大的区域,并且它是所有线程共享的区域。它的唯一作用就是存放对象实例,根据jvm规范的规范,它的内存空间可以使不连续的,只要在逻辑上连续的即可。

1.5 方法区

方法区和堆一样,是被所有线程共享的运行时区域,它用于存放被虚拟机加载的累信息,常量,静态变量,即时编译后的代码等数据,跟堆的情况一样,当方法区无法满足内存分配需求时,也会抛出OutOfMemberError的异常。

运行时常量池也属于方法区的一部分。class文件除了有版本,字段,方法,接口等描述信息外,其中还有信息是常量池,用于存放编译后的各种字面量和符号引用,这部分将在类加载后存放到方法区的常量池中。另外java语言并非要求常量一定一定在编译期间产生,即是并非预置入的class文件常量池的内存才能进入方法区的运行时常量池,运行期间同样也能进入。

1.6直接内存

直接内存并不属于虚拟机运行时的数据区的一部分, 也不是java虚拟机规范中定义的内存区域,但这部分内存被频繁使用到,并且也会爆outofmemoryError异常。

在java jdk1.4中加入了NIO类,引入了基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以直接使用Native函数分配堆外的内存,然后通过存储在java堆中DirectByteBuffer对象作为这块内存的引用直接操作,这样避免了java堆和Native堆来回复制的问题,提升了行性能。

1.7对象访问方式

java虚拟机规定了一个对象变量指向一个对象的引用,并没有定义这个引用以何种方式去定位,以及访问到java堆的具体位置,所以不同的虚拟机实现对象访问的方式略有不同,大概主流的分为:句柄和直接指针。

使用句柄访问方式,java堆会划出一个内存区域作为句柄池,对象的变量存储的就是句柄池的地址,而句柄池中就存放了对象实例的数据以及对象类型信息的地址信息。若使用直接访问方式,对象变量中存储的直接是对象实例的数据以及对象类型信息的地址信息。

两种访问方式各有优势,句柄访问的优势在于对象变量可存储稳定的地址,当对象移动时,只需改变句柄池的地址,变量本身无需修改。直接访问的优势明显在于访问速度快,sun HotSpot就是采用第二种对象访问方式。

时间: 2024-10-24 06:04:50

jvm的内存区域简介的相关文章

JVM的内存区域划分以及垃圾回收机制详解

在我们写Java代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉.因为JVM中有垃圾自动回收机制.在之前的博客中我们聊过Objective-C中的MRC(手动引用计数)以及ARC(自动引用计数)的内存管理方式,下方会对其进行回顾.而目前的JVM的内存回收机制则不是使用的引用计数,而是主要使用的"复制式回收"和"自适应回收". 当然除了上面是这两种算法外,还有其他是算法,下方也将会对其进行介绍.本篇博客,我们先简单聊一下JVM的区域划分,

【java】JVM的内存区域划分

学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的呢? 由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分.在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程: 如上图所示,首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加

jvm java内存区域的介绍

jvm虚拟机在运行时需要用到的内存区域.广泛一点就是堆和栈,其实不然,堆和栈只是相对比较笼统的说法,真正区分有如下几个 先上图一: 总的就是 java的内存模型 内存模型又分堆内存(heap)和方法区(有时也称为non-heap)和栈 堆又分新生代(Young)和老年代(old/Tenured) 新生代又分默认比例为8:1:1的eden空间.from survivor空间.to survivor空间 当进行垃圾回收时,eden.survivor from 存活得对象会复制到servivor to

JVM的内存区域划分

说到Java内存区域,可能很多人第一反应是“堆栈”.首先堆栈不是一个概念,而是两个概念,堆和栈是两块不同的内存区域,简单理解的话,堆是用来存放对象而栈是用来执行程序的.其次,堆内存和栈内存的这种划分方式比较粗糙,这种划分方式只能说明大多数程序员最关注的.与对象内存分配关系最密切的内存区域是这两块,Java内存区域的划分实际上远比这复杂.对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去配对delete/free代码,不容易出现内存泄露和内存溢出问题.但是,也正

JVM的内存区域划分,对象实例化分析

一.JVM程序具体执行过程 由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分.在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程:                                     如上图所示,Java源代码文件(.java后缀)经过Java编译器编译成为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行.在整个程序执行过程中,JVM会用一

深入理解jvm之内存区域与内存溢出

文章目录 1. Java内存区域与内存溢出异常 1.1. 运行时数据区域 1.1.1. 程序计数器 1.1.2. java虚拟机栈 1.1.3. 本地方法栈 1.1.4. Java堆(Java Heap) 1.1.5. 方法区 1.1.6. 运行时常量池 1.1.7. 直接内存 1.2. HotSpot虚拟机 1.2.1. 对象的创建 1.2.2. 对象的访问定位 1.3. OOM异常的解决思路 1.4. 参考 Java内存区域与内存溢出异常 运行时数据区域 程序计数器 当前线程所执行的字节码的

JVM——Java内存区域

                                        JVM 一.概念 虚拟机:通过软件模拟的具有完整硬件功能的运行在一个完全隔离环境中的完整操作系统. JVM:软件虚拟Java字节码指令集. HoSpot是Java默认的虚拟机. 二.Java内存区域与内存溢出异常 Java虚拟机所管理的内存包括如下几个运行时数据区域: (1)线程私有区域(随线程的创建与销毁而创建与销毁):程序计数器.虚拟机栈.本地方法栈. (2)线程共有区域:Java堆.方法区.运行时常量池. 1.

Java虚拟机(JVM)内存区域

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

JVM——Java内存区域相关3

一. 垃圾收集算法 1. 标记-清除算法 缺点:1.效率低,标记和清除两个过程的效率都不高: 2.空间问题,标记清除后会产生大量的不连续内存碎片. 2. 复制算法 将内存分成三块:一块较大的Eden和两块较小的Survivor空间.每次使用Eden和其中一块Survivor,回收后将Eden和Survivor中还存活着的对象一次性的复制到另外一块Survivor空间上.如果复制过程中Survivor的空间不够用时,需要依赖老年代进行分配担保. 3. 标记-整理算法 和标记-清理算法类似,只不过后