JVM在运行java程序的过程中会把他所管理的内存划分为若干个不同的数据区域。

这些区域都有各自的用途和创建、销毁时间。有些区域随着虚拟机的启动而存在。有些区域则依赖用户线程的启动和结束而建立和销毁。依据《Java虚拟机规范1.7》规定,Java虚拟机所管理的内存分为下面几个区域:

程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存

程序计数器

是一块较小的内存空间。他能够看作是当前线程所运行的字节码的行号指示器。

在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条须要运行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都依靠这个计数器来完毕。

因为Java虚拟机的多线程是通过线程轮流切换并分配处理器运行时间的方式来实现的,在不论什么一个确定的时刻,一个处理器(对于多核处理器仅仅有一个内核)都仅仅会运行一个线程中的指令。

因此,为了线程切换后能恢复到正确的运行位置,每条线程都须要有一个独立的程序计数器。各条线程之间计数器互不影响,独立存储。我们称这类内存区域为“线程私有”内存。

Java虚拟机栈

Java虚拟机栈也是线程私有的。他的生命周期与线程同样。虚拟机栈描写叙述的是Java方法运行的内存模型:每个方法在运行的同一时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出入口等。

每个方法从调用到运行完毕过程。就相应着一个栈帧在虚拟机中入栈到出栈的过程。

常常有人将Java内存分为堆内存(Heap)和栈内存(Stack),这样的分法是比較粗略的,java的内存区域远比这个复杂。

局部变量表存放了编译期可知的各种数据类型(boolean,byte,char,shot,int,float,long,double),对象引用类型(reference类型,他不同于对象本身,可能是一个指向对象起始地址的引用指针。也可能是一个代表对象的句柄或者其它与此对象关联的位置)和returnAddress类型(指向了一条字节码指令的地址)。

当中64位长度的lang和double类型的数据会占用2个局部变量空间(slot),其余数据类型仅仅占用1个。局部变量表所需的内存空间在编译期间完毕分配。当进入一个方法时。这种方法须要在帧中分配多大的局部变量空间是全然确定的。在方法运行期间不会改变局部变量表的大小。

在java虚拟机规范中,对于这个区域规定了两种异常状况:假设线程请求的栈深度大于虚拟机所同意的深度,将抛出StackOverflowException异常;假设虚拟机能够动态扩展。假设扩展到无法申请足够的内存。就会抛出OutMemoryError异常。

本地方法栈

虚拟机栈是为虚拟机运行Java方法也就是字节码服务的。而本地方法栈则为虚拟机用的Native方法服务。与虚拟机栈一样。本地方法栈也会抛出StackOverflowException和OutMemoryError异常。

Java堆

对于大多数应用来说。Java堆是Java虚拟机所管理的内存最大的一块,Java堆是被全部线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,差点儿全部的对象实例都要在这里分配内存,全部的对象实例以及数组都要在堆上分配,随着编译器的发展全部的对象都在对上分配变得不是那么绝对了。

Java堆是垃圾收集器管理的主要区域。因此非常多时候被称作GC堆。

从内存回收的角度来看:因为如今收集器基本都採用分代收集算法,所以Java堆还能够细分为:新生代和老年代。再仔细一点有Eden空间、From Survivor空间、To Survivor空间等。从内存的分配角度来看,线程共享的java堆可能划分出多个线程私有的分配缓冲区。

只是不管怎样划分都与存放内容无关。不管哪个区域存储的依旧是实例对象。进一步划分的目的是为了更好的回收内存,或者更快的回收内存。

依据Java虚拟机的规定,Java堆能够处于物理上不连续的内存空间,仅仅要逻辑上连续的就可以。

方法区

方法区与Java堆一样。是各个线程共享的区域,他用于存储已被虚拟机载入的类信息。常量,静态变量。即时编译器编译后的代码等数据。尽管java虚拟机规范把方法区描写叙述为堆的一个逻辑部分,可是他有别名——非堆,为了与java堆区分开来。

对于习惯在Hotspot虚拟机上开发、部署的开发人员来说,非常多人愿意把方法区称为永久代,本质上两者并不等价。

依据java虚拟机规范当方法区无法满足内存分配需求时将抛出OutOfMemoryError异常。

运行时常量池

是方法区的一部分,Class文件除了有类的版本号、字段、方法、接口等描写叙述信息外,另一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类载入后进入方法区的运行时常量中存放。

他也是方法区的一部分,无法满足内存分配需求时将抛出OutOfMemoryError异常。

直接内存

不是虚拟机运行时数据区一部分,也不是java虚拟机规范中定义的内存区域。可是这部分内存也被频繁的使用,并且可能导致OutOfMemoryError异常。直接内存的分配不会受到java堆大小的限制,可是,既然是内存。肯定还是会受到本机内存的限制。运维在配置虚拟机參数时,会依据实际内存设置-Xmx等參数信息,但常常忽略直接内存。使得内存区域总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。

深入理解JVM:JVM执行时数据区域分类的更多相关文章

  1. JVM学习-运行时数据区域

    目录 前言 运行时数据区 程序计数器 Java虚拟机栈 局部变量表 基础数据类型 对象引用 returnAddress 操作数栈 动态链接 方法返回地址 Java堆 方法区 类型信息 字段描述符 方法 ...

  2. JVM<一>----------运行时数据区域

    参考:1.JVM Specification: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5 2.< ...

  3. java内存结构(执行时数据区域)

    java虚拟机规范规定的java虚拟机内存事实上就是java虚拟机执行时数据区,其架构例如以下: 当中方法区和堆是由全部线程共享的数据区. Java虚拟机栈.本地方法栈和程序计数器是线程隔离的数据区. ...

  4. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

  5. 深入理解Java虚拟机-JVM运行时数据区域

    一.运行时数据区域 1.程序计数器 程序计数器( Program Counter Register) 是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器. Java虚拟机的多线程是 ...

  6. 深入理解JAVA虚拟机之JVM性能篇---基础知识点(运行时数据区域)

    一. 运行数据区域划分 各个数据区域功能如下: 1. 程序计数器: 较小的一块内存空间,可以看做是当前线程所执行的字节码的行号指示器,每条线程都有一个独立的程序计数器,各条线程之间计数器互不影响,独立 ...

  7. JVM学习笔记:Java运行时数据区域

    JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私 ...

  8. JVM 内存区域 (运行时数据区域)

    JVM 内存区域 (运行时数据区域) 链接:https://www.jianshu.com/p/ec479baf4d06 运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内 ...

  9. JVM之基础概念(运行时数据区域、TLAB、逃逸分析、分层编译)

    运行时数据区域 JDK8 之前的内存布局 JDK8 之后的 JVM 内存布局 JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8 开始使用元空间(Metaspace),以前永 ...

随机推荐

  1. 桶排序Bucket sort(转)

    补充说明三点 1,桶排序是稳定的 2,桶排序是常见排序里最快的一种,比快排还要快…大多数情况下 3,桶排序非常快,但是同时也非常耗空间,基本上是最耗空间的一种排序算法 我自己的理解哈,可能与网上说的有 ...

  2. Windows开发

    1. 介绍 这里简单介绍了Windows应用程序开发的基础知识 2. 基础 Windows下的应用程序有控制台程序和Win32窗口程序,这里讲的是Win32窗口程序 Windows提供了相关静态库(L ...

  3. 在 IntelliJ IDEA 中配置 JSF 开发环境的入门详解

    JSF 作为 JavaEE 官方标准,在了解并掌握其基本开发技术后,对于功能要求较高.业务流程复杂的各种现代 Web 应用程序开发将会成为非常合适且强大的高效率开发利器.JSF 的开发环境搭建涉及到在 ...

  4. AC日记——[Sdoi2010]星际竞速 bzoj 1927

    1927 思路: 连边,拆点: 每个点拆成i,i+n,都向t连边: i到t表示高速模式,i+n到t表示跳跃模式: 然后读入路径,如果u>v,则交换u,v: u向v+n连边: spfa跑最小费用: ...

  5. 判断scrollView的滑动方向

    第一种方式: float lastContentOffset; - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { las ...

  6. Java多线程之Thread、Runnable、Callable及线程池

    一.多线程 线程是指进程中的一个执行流程,一个进程中可以有多个线程.如java.exe进程中可以运行很多线程.进程是运行中的程序,是内存等资源的集合,线程是属于某个进程的,进程中的多个线程共享进程中的 ...

  7. NewCode

    1.[数论]给你N,求不大于N的最大完全平方数. #include<bits/stdc++.h> #define FOR(i,a,b) for(int i=(a),_b=(b);i< ...

  8. Codeforces 761E Dasha and Puzzle(构造)

    题目链接 Dasha and Puzzle 对于无解的情况:若存在一个点入度大于4,那么直接判断无解. 从根结点出发(假设根结点的深度为0), 深度为0的节点到深度为1的节点的这些边长度为2^30, ...

  9. Algorithm | Sort

    Bubble sort Bubble sort, sometimes incorrectly referred to as sinking sort, is a simple sorting algo ...

  10. 转:IAdaptable & IAdapterFactory

    IAdaptable & IAdapterFactory在Eclipse中使用IAdaptable接口的方式有两种 在Eclipse中使用IAdaptable接口的方式有两种1:某个类希望提供 ...