JVM(一)—— 运行时内存结构

  JVM 在执行 Java 程序的过程中会把它所管理的物理内存划分成不同的内存区域,每一个区域都存放着不同的数据。每个区域也都有不同的用途,以及创建和销毁的时机,根据虚拟机规定,可以获得这样的 JVM 内存结构。

1  程序计数器

  程序计数器(Program Counter Register)是一块比较小的内存区域,可以看作是当前线程所执行的字节码的行号指示器。就是用于存放当前线程接下来将要执行的字节码指令、分支、循环、跳转、异常等信息。在任何时候,一个处理器只能执行一个线程中的指令,为了能让 CPU 时间片轮转切换上下文之后顺利回到正确的执行位置,每条线程都有自己的独立的程序计数器,这样各个线程之间就互不影响,因此这块区域被JVM设计为线程私有的。

  此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。

2  Java 虚拟机栈

  与程序计数器一样,Java 虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,与线程的生命周期相同。虚拟机栈描述 Java方法执行的内存模型:每个方法在执行的同时都会创建一个独特的数据结构:栈帧(Stack Frame)。它主要用来存储局部变量表、操作数栈、动态链接、方法出口等信息。方法的调用就对应着栈帧在虚拟机栈中的压栈与出栈过程。

  每一个线程在创建的时候,JVM 都会为其创建对应的虚拟机栈,同等大小的虚拟机栈如果局部变量表等内存信息越小,则被压入的栈帧就会越多,反之被压入的栈帧就会越少,一般可以将栈帧内存的大小称为宽度,栈帧的数量称为虚拟机栈的深度。可以把一个虚拟机栈想象成为面积固定的长方形,宽就是栈帧内保存的信息的大小,长就是栈帧的数量,也就是虚拟机栈的深度,当宽变小了,那么长就变大了,所以可以压入更多的栈帧(当然一般虚拟机栈的内存大小是指出动态扩展的)。如果某一时刻一个线程请求的栈深度大于虚拟机所允许的栈深度,则会抛出 StackOverFlowError 异常;如果虚拟机可以动态扩展,扩展时无法申请到足够的内存,就会抛出 OutOfMemoryError 异常。

3  本地方法栈

  本地方法栈(Native Method Stack)和虚拟机栈所发挥的作用很相似,都是线程私有的,都可以抛出 StackOverFlowError 异常 和 OutOfMemoryError 异常。他们之间的区别就是虚拟机栈为虚拟机执行 Java 方法(字节码)服务;本地方法栈则为虚拟机使用的 Native 方法服务。Java 中提供了调用本地方法的本地接口(Java Native Interface),是一些 C/C++ 程序,在线程的执行过程中,会经常碰到调用 JNI 方法的情况,比如网络通信、文件操作的底层等。

4  Java 堆

  堆内存是 JVM 所管理的内存中最大的一块(从我画的情况来看,看的出来对吧)。堆内存是被所有线程所共享的一块内存区域,在虚拟机启动的时候创建。堆和栈是我们在刚接触编程的时候最容易遇到,也是醉容易搞混的两个概念,他们有的时候可以代表数据结构中的堆(就是可以实现最小二叉堆的那个)和栈(就是 FILO 那个),有的时候是表示内存的结构,所以千万不要搞混了。经常有人把 Java 内存分为堆内存和栈内存,就是指的这里的Java堆内存和虚拟机栈内存。但这种分法是比较粗糙的,所以我们还是需要学习更加细腻的分法呀。

  堆内存被用来存放对象的实例和数组对象,就是 new 出来的那些对象。

  此外,堆内存还是垃圾收集器管理的主要区域,具体的垃圾回收内容我们后面再仔细研读研读。因此很多时候也被称为“GC堆”(Garbage Collected Heap)。从垃圾回收的角度看,现在的垃圾收集器基本都会采用分代收集算法,所以堆内存还可以被分为:新生代和老年代,更细致的可以分为 Eden 区、From Survivor 空间、To Surviver 空间等。

  当在堆中没有内存完成分配实例,并且堆也无法完成扩展时,将会抛出 OutOfMemoryError 异常。

5  方法区

  方法区(Method Area)和堆内存一样,是所以线程共享的内存,主要用来存储已被 JVM 加载的类信息、常量、静态变量、即时编译器(Just In Time,JIT)编译后的代码等数据。在 HotSpot 虚拟机里,垃圾收集分代收集扩展到了方法区。HotSpot 的垃圾收集器可以像管理 Java 堆一样管理这部分内存,但是对于其他虚拟机来讲,可以不实现这样,甚至可以选择不进行垃圾回收。

  运行时常量池(Runtime Constant Pool)是方法区的一部分。用来存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的允许时常量池中存放。既然有内容,那肯定也需要被 GC了,回收的主要目标也就是针对常量池的回收以及对类型的卸载。但是这个区的回收效果比较难以让人满意,容易因为此区域内存没有完全回收而造成内存泄漏。

  同样,根据 Java 虚拟机规定,当方法区无法满足内存分配需求时,将会抛出 OutOfMemoryError 异常。

原文地址:https://www.cnblogs.com/dogeLife/p/11361230.html

时间: 2024-10-05 02:49:48

JVM(一)—— 运行时内存结构的相关文章

[转]JVM运行时内存结构

目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的JVM参数 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会

JVM 运行时内存结构

  1.JVM内存模型       JVM运行时内存=共享内存区+线程内存区 1).共享内存区       共享内存区=持久带+堆       持久带=方法区+其他       堆=Old Space+Young Space       Young Space=Eden+S0+S1 (1)持久带       JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等.可通过-XX:PermSize和-XX:MaxPermSize来指定持久带初始化

JVM运行时内存结构

连接:http://my.oschina.net/sunchp/blog/369707 1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持久带=方法区+其他 堆=Old Space+Young Space Young Space=Eden+S0+S1 (1)持久带 JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等. 可通过-XX:PermSize和-XX:MaxPermSize来指

JVM运行时内存结构学习

学习JVM运行模型比较重要,先看一幅图片: 运行时数据区(内存结构) :  1.方法区(Method Area)类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在这里定义.简单来说,所有定义的方法的信息都保存在该区域,静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在方法区中, 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是为了和Java的堆区分开 . 2.堆(Heap)虚拟机启动时自动分配创建,用于

JAVA-JVM 运行时内存结构(Run-Time Data Areas)

Java 虚拟机定义了在程序执行期间使用的各种运行时数据区域. 其中一些数据区域是在 Java 虚拟机启动时创建的,仅在Java虚拟机退出时销毁. 其他数据区域是每个线程.线程数据区域是在线程退出时创建和销毁线程时创建的. 一.运行时数据区划分(JDK8) 1.The pc Register(PC 寄存器.程序计数器) 2.Java Virtual Machine Stacks(Java 虚拟机栈.Java 栈) 3.Native Method Stacks(本地方法栈,C栈) 4.Heap(堆

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

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

jvm(运行时数据区域)

以上是jvm在运行时内存的数据分区图例(各个分区简介): 1.程序计数器:           在jvm中一块很小的区域,主要作用就是记录当前线程执行字节码的行号指示器.           在单核的多线程中,cpu会在不同线程之间切换,为了切换回来时正确的回到当前线程的执行位置,           每个线程都有自己单独的程序计数器,之间互不影响,独立运行,同时这块区域也是在java虚拟机           规范中唯一没有规定任何OutOfMemoryError情况的区域. 2.虚拟机栈:

Java 进阶(一) JVM运行时内存模型

1.JVM运行时数据区域的划分 a.程序计数器(Program Counter Register) 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.每个线程拥有独立的一个计数器,如果当前执行的是Native方法,则计数器值为空. b.JVM栈(Java Virtual Machine Stack) 描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stacks Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息. 每一个方法从调用直至执行完成

jvm运行时内存解析

一.jvm的概念 在了解jvm的概念之前,我们先来了解java平台的逻辑结构,图片来自<深入java虚拟机> 从图中我们可以看到jdk包含了jre,java语言和java开发工具和Api,jre包含了java运行的基础类库和java虚拟机,java虚拟机支撑着java程序的运行. jvm(java virtual machine)翻译为java虚拟机,从字面上来理解,jvm就是一个虚拟的机器,其实类似于一个操作系统,通过软件去虚拟出一个虚拟机,帮助我们管理计算机的内存和调用计算机的硬件等等.而