Java虚拟机在执行Java程序时,会把它管理的内存划分为若干个不同的数据区。这些区域有不同的特性,起不同的作用。它们有各自的创建时间,销毁时间。有的区域随着进程的启动而创建,随着进程结束而销毁,有的则始终贯穿虚拟机整个生命周期。
Java虚拟机运行时内存区域主要分为七部分,分别是:程序计数器,Java虚拟机栈,本地方法栈,方法区,Java堆,运行时常量池,直接内存。
如上图所示(图片来源于网络):
蓝色区域包裹的部分为运行时几个数据区域:
白色的部分为线程私有的,既随着线程的启动而创建。每个线程都拥有各自的一份内存区域。它们是: JAVA栈(JAVA STACK),本地方法栈(NATIVE METHOD STACK),和程序计数器(PROGRAM COUNTER REGISTER)。
黄色部分是线程共享的,所有的线程共享该区域的内容。他们是:方法区(METHOD AREA),堆(HEAP)。
我们分别来介绍这些区域。
(1)程序计数器
程序计数器(program counter register)
学过计算机组成原理的都知道计算机处理器中的程序计数器。当处理器执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。
处理器的程序计数器是指寄存器,而java程序计数器是指一小块内存空间。java代码编译字节码之后,虚拟机会一行一行的解释字节码,并翻印成本地代码。这个程序计数器盛放的就是当前线程所执行字节码的行号的指示器。在虚拟机概念模型中,字节码解释器工作室就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理等都依赖于它。
Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,因此为了线程切换后还能恢复执行位置,每条线程都需要一个独立的程序计数器。
如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是Java Native方法,这个计数器值为空。
而且程序计数器是Java虚拟机中没有规定任何OutOfMemoryError的区域。
(2)虚拟机栈
Java虚拟机栈(VM Stack)也是线程私有的,因此它的生命周期也和线程相同。它存放的是Java方法执行时的数据,既描述的是Java方法执行的内存模型:每个方法开始执行的时候,都会创建一个栈帧(Stack Frame)用于储存局部变量表、栈操作数、动态链接、方法出口等信息。每个方法从调用到执行完成就对应一个栈帧在虚拟机栈中入栈到出栈的过程。经常有人把Java内存分为堆内存和栈内存,这种是比较粗糙的分法,很大原因是大多数程序‘猿’最关注的,与对象内存分配最密切的区域就是堆和栈。局部变量表存放的是编译器可知的各种基本数据类型(boolean 、byte、int、long、char、short、float、double)、对象引用(reference类型)和returnAddress类型(它指向了一条字节码指令的地址)。其中64bit长度的long和double会占用两个局部变量空间(Slot),其余的数据类型只占用一个。局部变量表所需的内存空间是在编译时期确定的,在方法运行期间不会改变局部变量表的大小。在Java虚拟机规范中,对这部分区域规定了两种异常: 1、当一个线程的栈深度大于虚拟机所允许的深度的时候,将会抛出StackOverflowError异常; 2、如果当创建一个新的线程时无法申请到足够的内存,则会抛出OutOfMemeryError异常。
(3)本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是十分相似的,他们之间的区别不过是虚拟机栈为Java方法字节码服务,而本地方法栈则为Native方法服务。在虚拟机规范中对本地方法使用的语言和使用方法与数据结构没有强制规定,因此具体的虚拟机可以自由实现它。Sun HotSpot虚拟机把本地方法栈和虚拟机栈合二为一。和虚拟机栈一样,本地方法栈也会抛出OutOfMemoryError 和 StackOverflowError异常。
接下来我们介绍的都是所有线程共享的区域了。
(4)堆
堆(heap)是虚拟机中最大的一块内存区域了,被所有线程共享,在虚拟机启动时创建。它的目的便是存放对象实例。
堆是垃圾收集器管理的主要区域,因此 很多时候也被成为‘GC’堆(Garbage Collected Heap)。
从垃圾回收的角度来讲,现在的收集器包括HotSpot都采用分代收集算法,所以堆又可以分为:新生代(Young)和老年代(Tenured),再细致一点,新生代又可分为Eden、From Survivor空间和To Survivor空间。
从内存分配的角度来讲,又可以分为若干个线程私有的分配缓冲区(Thread Local Allocation Buffer ,TLAB)。
当堆空间不足切无法扩展,会抛出OutOfMemoryError异常。
(5)方法区
方法去(Method Area)与Java堆一样,是各个线程共享的内存区域,用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
它有个别名叫做非堆Non-Heap。对于HotSpot开发者来说,很多人称它为“永久代”(Permanent Generation),但是两者并不等价,仅仅是因为HotSpot虚拟机设计团队把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以向管理堆一样管理这部分内存。但是因为永久代有“-XX:MaxPermSize的上限,使其更容易内存溢出。因此在JDK1.7的HotSpot中,已经把原本放在永久代的字符串常量池移出去了。
当方法区无法满足内存分配需求的时候,会抛出OutOfMemoryError异常。
(6)常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中出了类的版本、字段、方法、接口等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译器生成的各种字面量和符号引用,这些内容将在类加载后进入方法区存放。
运行时常量池相对于Class文件常量池的另外一个重要特征是具有动态性,运行期间也可能有新的常量池放入持重,比如String.intern()方法。
运行时常量池属于方法区一部分,自然会抛出OutOfMemoryError异常。
(7)直接内存
直接内存(Direct Memory)不属于虚拟机中定义的内存区域,而是堆外内存。
JDK1.4 中新加入了NIO(new Input/Output)类,引入了一种基于通道(Channel)和缓冲区(Buffer)的I/O方式,它可以使用Native函数直接分配堆外内存,然后通过Java堆中的DirectByteBuffer对象作为这快内存的引用进行操作。这样能在一些场景中显著提高新能性能。如果直接内存不足时,会抛出OutOfMemoryError异常。

Java虚拟机内存划分的更多相关文章

  1. java 虚拟机内存划分,类加载过程以及对象的初始化

    涉及关键词: 虚拟机运行时内存 java内存划分 类加载顺序  类加载时机  类加载步骤  对象初始化顺序  构造代码块顺序 构造方法 顺序 内存区域   java内存图  堆 方法区 虚拟机栈 本地 ...

  2. (转)java 虚拟机内存划分

    深入理解java虚拟机(一):java内存区域(内存结构划分)深入理解java虚拟机(二):java内存溢出实战  深入理解java虚拟机(三):String.intern()-字符串常量池深入理解j ...

  3. 重读《深入理解Java虚拟机》一、Java虚拟机内存区域的划分

    一.Java虚拟机内存区域如何划分 1.Java虚拟机内存区域的划分 区域名称 作用(用途) 类型 特点 虚拟机规定异常情况 内存分配与回收 其他说明 1 程序计数器 指示当前正在执行的字节码指令地址 ...

  4. Java虚拟机内存模型及垃圾回收监控调优

    Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...

  5. JAVA虚拟机内存分配与回收机制

    Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现.Java虚拟机有自己想象中的硬件,如处理器.堆栈.寄存器等 ...

  6. Java虚拟机-内存tips

    java虚拟机内存可以分为独占区和共享区. 独占区:虚拟内存栈.本地方法栈.程序计数器. 共享区:方法区.Java堆(用来存放对象实例). 程序计数器 比较小的内存空间,当前线程所执行的字节码的行号指 ...

  7. JVM基础系列第6讲:Java 虚拟机内存结构

    看到这里,我相信大家对于一个 Java 源文件是如何变成字节码文件,以及字节码文件的含义已经非常清楚了.那么接下来就是让 Java 虚拟机运行字节码文件,从而得出我们最终想要的结果了.在这个过程中,J ...

  8. 总结Java虚拟机内存区域模型

    本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用.服务对象以及其中可能产生的问题,作为大家的面试宝典. 首先我们来看一下Java运行时的数据区域,Java虚拟机在执行Java程序 ...

  9. 一文解析总结Java虚拟机内存区域模型

    最近抽空看了一点<深入理解Java虚拟机>,本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用.服务对象以及其中可能产生的问题,作为大家的面试宝典. 首先我们来看一下J ...

随机推荐

  1. css清除select的下拉箭头样式

    <!DOCTYPE html><html>    <head>        <meta charset="UTF-8">      ...

  2. IOC 本质是为了实现 AOP|火影鸣人

    @JFinal 波总在 JFinal 4.8 发布新闻的评论 中给出了下面的表述: IOC 本质是为了实现 AOP 我有点吃惊, 没想到 Java 界的大佬对这两个概念有和我完全不一致的认识. 所以写 ...

  3. UML-为什么要使用层?

    1.内聚职责:使关系分离.减少耦合和依赖,提高潜在复用性. 2.领域层和技术服务层可以是分布式的 3.利于团队开发

  4. Java clone方法的使用

    浅克隆 Person p2 = (Person) p1.clone(); clone()方法使用后得到p2,p2和p1指向不同的地址.但是如果p1中的属性是引用类型,那么不再对这个引用类型进行复制,而 ...

  5. ZJNU 1333 - 第二题 blocks--中高级

    因为放一个就需要判断一次,每一次跑一遍全图bfs显然是不现实的 又因为点只有三种,黑白无 所以可以用并查集优化 添加一个棋子就判断周围四个的组别情况 注意出现的情况与答案关系之间的判别 /* Writ ...

  6. python-day8爬虫基础之数据存储

    数据存储,在爬虫中也是十分的重要,因为我们要把我们想要的数据保存到本地,其中最简单直接的就是保存为文件文本,比如:TXT.JSON.CSV等等,除此之外,我们还可以将其保存到数据库中,常见的数据库类型 ...

  7. docker 一些简略环境搭建及部分链接

    1.center 7  搭建 docker https://www.cnblogs.com/yufeng218/p/8370670.html 2.docker 命令 https://www.cnblo ...

  8. Django_HTML

    一.web开发之HTML 1.1 HTML相关基础 快速生成html的模版方法: 在visual code的新建html文件中输入:!然后tab回车就会出现HTML的模版 双标签: <p> ...

  9. list循环 字典循环 字符串常用方法

    list = ['xiaoli','xiaohua','huali']user = {'zhang':'123','lin':'321','chen':'222'}#list循环for stu in ...

  10. i春秋web作业2.26

    Web安全工程师(入门班) [全国线上入门班53期]课后作业   2020-2-26 DorinXL   1)为什么说js校验是一种不安全的校验方式? js校验不安全,是因为用户很容易通过控制台删除或 ...