(一)JVM整体内存结构及简单介绍

内存结构图

在这里插入图片描述

类加载器(Class Loader)

    类加载器的作用是负责将类的字节码文件加载到 Java 虚拟机中。

程序计数器(Program Counter Register)

    程序计数器是线程私有的区域,它占用了很小的内存空间。它可以看作是当前线程所执行的字节码的行号指示器。
    字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令, 它是程序控制流的指示器, 分支、 循环、 跳转、 异常处理、 线程恢复等基础功能都需要依赖这个计数器来完成。
    程序计数器是唯一没有规定任何OutOfMemoryError情况的区域。

虚拟机栈(JVM Stack)

    虚拟机栈也是线程私有的区域,栈的内存要远远小于堆内存,栈实际上是一个队列, 遵循 FILO的原则(后进先出)。
    当每个Java函数被执行的时候,虚拟机都会同步创建一个栈帧,压入栈中,该栈帧就用于存储当前这个函数中的一些数据(比如:对象的引用,函数体的地址,函数的参数,局部变量,临时变量等信息)。每一个方法被调用直至执行完毕的过程, 就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
    在HotSpot虚拟机中,栈的容量大小是不可以在运行时动态扩展的。当栈的空间不够时(比如函数无限的递归导致一直压栈,导致栈的容量占满),将抛出StackOverFlowError异常。
    栈帧是方法运行期很重要的基础数据结构,后续会深入探讨。

本地方法栈(Native Method Stack)

    本地方法栈也是线程私有的区域,与虚拟机栈类似,但是它主要是为虚拟机使用到的 Native 方法服务,任何本地方法接口都会使用某种本地方法栈。
    当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

Java堆(Heap)

    堆内存是虚拟机所管理的内存中最大的一块,Java堆是线程共享的区域。他的作用就是用来存放对象的实例,在《Java虚拟机规范》 中对Java堆的描述是: “所有的对象实例以及数组都应当在堆上分配“。
    Java堆既可以被实现成固定大小的, 也可以是可扩展的。当堆内存不足时,会抛出OutOfMemoryError异常。
    在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。所以我们常听到的对JVM的优化,也大部分是针对此区域。所以,这部分后续会深入探讨。

方法区(Method Area)

    方法区也是被线程共享的区域。在方法区中,存储了被虚拟机加载过的类型信息(比如类的名称、方法信息、字段信息),静态变量、常量以及即时编译器编译后的代码缓存等数据。
    在《Java虚拟机规范中》,方法区被定义为堆的一个逻辑部分,但在内存上来说,他并不属于堆。方法区是一个概念定义,真正的实现,在不同的虚拟机上都不尽相同,以HotSpot虚拟机为例,在JDK8以前,他的具体实现叫永久代。而在JDK8以后,HotSpot虚拟机的方法区改为元空间来实现。

执行引擎(Execution Engine)

    通过类装载器装载的,被分配到JVM的运行时数据区的字节码会被执行引擎执行。
    JVM中的执行引擎在执行java代码的时候,一般有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择。

本地方法接口(Native Interface)

    由JAVA代码调用非JAVA代码之间的接口。该接口通常被 native 修饰。接口的实现往往由非Java语言实现,比如C,C++,C#等。

通过以上的分析,可以暂时得出一个更进一步的JVM结构图,如下:
在这里插入图片描述
对JVM内存区域先简单了解到这里。其中最重要的就是类加载系统,虚拟机栈, 方法区,和堆内存,后续会对每一项进行深入的探讨。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM(Java虚拟机)内存结构是Java程序运行的基础,它主要由以下五个部分组成:堆(Heap)、方法区(Method Area)、程序计数器(Program Counter Register)、虚拟机栈(Java Virtual Machine Stacks)和本地方法栈(Native Method Stack)。 1. 堆(Heap) 堆是Java虚拟机中最大的一块内存区域,也是Java程序中最主要的内存区域,用于存放Java程序中的对象实例以及数组。堆内存是所有线程共享的,因此在多线程环境下,需要考虑线程安全问题。 堆内存又分为新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)。其中,新生代用于存放新创建的对象,老年代用于存放长时间存活的对象,而永久代用于存放常量池和类信息等,它的大小是固定的。 2. 方法区(Method Area) 方法区也称为永久代,用于存放Java类和其静态成员变量、常量、方法等信息。方法区同样是所有线程共享的,但是它的大小是固定的,并且不会被自动回收。如果方法区的空间不足,那么就会抛出OutOfMemoryError异常。 3. 程序计数器(Program Counter Register) 程序计数器是一块较小的内存区域,用于存储当前线程执行的字节码指令的地址。每个线程都有自己的程序计数器,它们是独立的,互不干扰。程序计数器的作用是保证线程执行指令的顺序和正确性。 4. 虚拟机栈(Java Virtual Machine Stacks) 虚拟机栈也是线程私有的,用于存放Java方法执行的局部变量、操作数栈、方法出口等信息。每个方法在执行时都会创建一个栈帧,栈帧包含了方法的参数、局部变量以及执行完毕后返回结果的地址等信息。如果虚拟机栈的空间不足,那么就会抛出StackOverflowError异常,如果虚拟机栈的空间已经用尽,那么就会抛出OutOfMemoryError异常。 5. 本地方法栈(Native Method Stack) 本地方法栈与虚拟机栈类似,但是它用于存放Java程序调用本地方法(Native Method)时的参数、局部变量等信息。本地方法栈同样是线程私有的,如果本地方法栈的空间不足,那么就会抛出StackOverflowError异常,如果本地方法栈的空间已经用尽,那么就会抛出OutOfMemoryError异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值