jvm之内存结构(代码片段)

高、远 高、远     2022-12-31     173

关键词:

【1】JDK、JRE、JVM的区别和联系

  • JREJava Runtime Environment, Java运行环境)是Java平台,所有的程序都要在JRE下才能够运行。包括JVM和Java核心类库和支持文件。

  • JDKJava Development Kit,Java开发工具包)是用来编译、调试Java程序的开发工具包。包括Java工具(javac/java/jdb等)和Java基础的类库(java API )。

  • JVMJava Virtual Machine, Java虚拟机)是JRE的一部分。JVM主要工作是解释自己的指令集(即字节码)并映射到本地的CPU指令集和OS的系统调用。Java语言是跨平台运行的,不同的操作系统会有不同的JVM映射规则,使之与操作系统无关,完成跨平台性。


【2】我们写的.java文件是怎么执行的 JVM扮演了什么角色?

java文件通过javac编译为class文件,然后通过JVM中的类加载器(ClassLoader)加载到JVM中,最终调用系统完成功能。

其实个人理解说得通俗一点就是,JVM将Class文件翻译为计算机可以直接执行的机器码了。



【3】JVM的内存划分

JVM的内存大概可以分为两个部分线程共享区线程私有区

  • 线程共享区:方法区
  • 线程私有区:虚拟机栈本地方法栈程序计数器
    除此之外,还有还有没经过虚拟化的直接内存,也就是没经过规范化的内存。


各种不同内存区的作用如下:

  1. 程序计数器

内存空间小,线程私有。字节码解释器工作是就是通过改变这个计数器的值来选取下一条需要执行指令的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成。对于多线程的情况下,用于保存现场。此内存区域是唯一 一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。

  1. Java虚拟机栈

线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(StackFrame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。

  1. 本地方法栈

区别于 Java 虚拟机栈的是,Java 虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。也会有 StackOverflowErrorOutOfMemoryError异常。

  1. Java堆

对于绝大多数应用来说,这块区域是 JVM所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组。内部会划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)。可以位于物理上不连续的空间,但是逻辑上要连续。

  1. 方法区

属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。


下面来介绍几个内存区:


一、Java虚拟机栈

一个方法就是一个栈帧
一个方法就是一个栈帧
一个方法就是一个栈帧

  1. 虚拟机栈在JVM运行过程中存储当前线程运行方法所需的数据,指令、返回地址。 Java 虚拟机栈是基于线程的。哪怕你只有一个 main()方法,也是以线程的方式运行的。
  2. 在线程的生命周期中,参与计算的数据会频繁地入栈和出栈,栈的生命周期是和线程一样的。
  3. 栈里的每条数据,就是栈帧。在每个 Java方法被调用的时候,都会创建一个栈帧,并入栈。一旦完成相应的调用,则出栈。所有的栈帧都出栈后,线程也就结束了。
  4. 每个栈帧,都包含四个区域:(局部变量表操作数栈动态连接返回地址)

下面是main()方法调用work()的例子。

  • 局部变量表:顾名思义就是局部变量的表,用于存放我们的局部变量的。首先它是一个32位的长度,主要存放我们的Java的八大基础数据类型,一般32位就可以存放下,如果是64位的就使用高低位占用两个也可以存放下,如果是局部的一些对象,比如我们的Object对象,我们只需要存放它的一个引用地址即可。
  • 操作数据栈:存放我们方法执行的操作数的,它就是一个栈,先进后出的栈结构,操作数栈,就是用来操作的,操作的的元素可以是任意的java数据类型,所以我们知道一个方法刚刚开始的时候,这个方法的操作数栈就是空的,操作数栈运行方法就是JVM一直运行入栈/出栈的操作
  • 动态连接:Java语言特性多态(需要类运行时才能确定具体的方法)。
  • 返回地址:正常返回(调用程序计数器中的地址作为返回)、异常的话(通过异常处理器表<非栈帧中的>来确定)

举个简单的例子
main调用A,A调用B,B调用C

public static void main(String []args)
	A();

public void A()
	B();

public void B()
	C();

public void C()
	//do something 


二、本地方法栈

  • 本地方法栈跟 Java 虚拟机栈的功能类似,Java 虚拟机栈用于管理 Java函数的调用,而本地方法栈则用于管理本地方法的调用。但本地方法并不是用 Java 实现的,而是由 C 语言实现的。
  • 本地方法栈是和虚拟机栈非常相似的一个区域,它服务的对象是native 方法。你甚至可以认为虚拟机栈和本地方法栈是同一个区域。
  • 虚拟机规范无强制规定,各版本虚拟机自由实现 ,HotSpot直接把本地方法栈和虚拟机栈合二为一 。

三、方法区

  • 很多开发者都习惯将方法区称为“永久代”,其实这两者并不是等价的。
  • HotSpot 虚拟机使用永久代来实现方法区,但在其它虚拟机中,例如,OracleJRockitIBM 的 J9 就不存在永久代一说。因此,方法区只是 JVM 中规范的一部分,可以说,在 HotSpot 虚拟机中,设计人员使用了永久代来实现了 JVM 规范的方法区。
  • 方法区主要是用来存放已被虚拟机加载的类相关信息,包括类信息、静态变量、常量、运行时常量池、字符串常量池。
  • JVM 在执行某个类的时候,必须先加载。在加载类(加载、验证、准备、解析、初始化)的时候,JVM 会先加载 class 文件,而在 class 文件中除了有类的版本、字段、方法和接口等描述信息外,还有一项信息是常量池 (Constant Pool Table),用于存放编译期间生成的各种字面量和符号引用。
  • 字面量包括字符串(String a=“b”)、基本类型的常量(final 修饰的变量),符号引用则包括类和方法的全限定名(例如 String 这个类,它的全限定名就是 Java/lang/String)、字段的名称和描述符以及方法的名称和描述符。
  • 而当类加载到内存中后,JVM 就会将 class 文件常量池中的内容存放到运行时的常量池中;在解析阶段,JVM 会把符号引用替换为直接引用(对象的索引值)。
  • 例如,类中的一个字符串常量在 class 文件中时,存放在 class 文件常量池中的;在 JVM 加载完类之后,JVM 会将这个字符串常量放到运行时常量池中,并在解析阶段,指定该字符串对象的索引值。运行时常量池是全局共享的,多个类共用一个运行时常量池,class 文件中常量池多个相同的字符串在运行时常量池只会存在一份。
  • 方法区与堆空间类似,也是一个共享内存区,所以方法区是线程共享的。假如两个线程都试图访问方法区中的同一个类信息,而这个类还没有装入 JVM,那么此时就只允许一个线程去加载它,另一个线程必须等待。在 HotSpot 虚拟机、Java7 版本中已经将永久代的静态变量和运行时常量池转移到了堆中,其余部分则存储在 JVM 的非堆内存中,而 Java8 版本已经将方法区中实现的永久代去掉了,并用元空间(class metadata)代替了之前的永久代,并且元空间的存储位置是本地

四、堆

  • 堆是 JVM 上最大的内存区域,我们申请的几乎所有的对象,都是在这里存储的。我们常说的垃圾回收,操作的对象就是堆。
  • 堆空间一般是程序启动时,就申请了,但是并不一定会全部使用。
  • 随着对象的频繁创建,堆空间占用的越来越多,就需要不定期的对不再使用的对象进行回收。这个在 Java 中,就叫作 GC(Garbage Collection)。
  • 那一个对象创建的时候,到底是在堆上分配,还是在栈上分配呢?这和两个方面有关:对象的类型和在 Java 类中存在的位置。
    Java 的对象可以分为基本数据类型和普通对象。
    对于普通对象来说,JVM 会首先在堆上创建对象,然后在其他地方使用的其实是它的引用。比如,把这个引用保存在虚拟机栈的局部变量表中。
    对于基本数据类型来说(byte、short、int、long、float、double、char),有两种情况。当你在方法体内声明了基本数据类型的对象,它就会在栈上直接分配。其他情况,都是在堆上分配。

音视频开发之旅(52)-java并发编程之内存模型与volatile(代码片段)

目录 JVM内存结构和内存模型并发编程中的三个概念与重排序happens-before原则volatile原理volatile使用场景资料收获一、JVM内存结构和内存模型1.1JVM内存结构图片来自图书《深入理解Java虚拟机》Java虚拟机在运行程序时会把其自动管... 查看详情

jvm之内存与垃圾回收篇虚拟机栈(代码片段)

...样的功能需要更多的指令。有不少Java开发人员一提到Java内存结构,就会非常粗粒度地将JVM中的内存区理解为仅有Java堆(heap)和Java栈(stack)?为什么?首先栈是运行时的单位,而堆是存储的单位。 查看详情

jvm之内存与垃圾回收篇执行引擎(代码片段)

执行引擎执行引擎概述执行引擎属于JVM的下层,里面包括解释器、及时编译器、垃圾回收器执行引擎是Java虚拟机核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理... 查看详情

jvm内存区域之虚拟机栈(代码片段)

文章目录虚拟机栈出栈和入栈栈帧结构局部变量表操作数栈动态链接返回地址/方法出口总结虚拟机栈线程私有,由一个个栈帧组成,每个栈帧对应着一个调用的方法,保存有方法的局部变量等信息。方法被调用时栈... 查看详情

图解jvm内存结构(代码片段)

文章目录JVM内存结构JVM包含哪几部分?在内存中java代码的执行的流程Java内存分布:各组件详细说明1.程序计数器2.Java虚拟机栈3.本地方法栈4.Java堆5.方法区6.运行时常量池7.直接内存总结问题那些区域会发生内存溢出?... 查看详情

jvm内存结构和垃圾回收(代码片段)

JVM内存结构和垃圾回收Java内存管理机制JAVA运行时区域栈内存堆内存的构成永久代JVM结构总结Java8新变化垃圾回收永久代的垃圾回收垃圾收集器前言在做性能测试之前,首先我们需要了解JVM的内存结构和垃圾回收机制。只有了... 查看详情

jvm——内存结构(代码片段)

内存结构程序计数器虚拟机栈本地方法栈堆方法区1.程序计数器1.1定义ProgramCounterRegister程序计数器(寄存器)作用,是记住下一条jvm指令的执行地址特点是线程私有的不会存在内存溢出1.2作用0:getstatic#20//PrintStreamout=System.out;3:asto... 查看详情

jvm入门——jvm内存结构(代码片段)

...r及其子类来完成JVM的类加载  3.类执行:字节码被装入内存,进入JVM虚拟机,被解释器解释执行   注:Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,       查看详情

java虚拟机|jvm适合初学者入门(代码片段)

...4.源代码到机器码的过程5.字节码文件的结构6.Java虚拟机内存结构7.JVM类的加载机制8.JVM垃圾回收机制9.JVM垃圾回收期10.垃圾回收的几种类型11.JVM参数之堆栈空间配置12.JVM参数之查看JVM参数13.JVM参数之追踪类信息14.JVM参数之GC日志配... 查看详情

jvm内存结构(代码片段)

文章目录JVM-内存结构1.程序计数器1-1定义1-2作用1-3特点2.虚拟机栈2-1定义2-2演示2-3常见问题2-4栈内存溢出2-5线程运行诊断3.本地方法栈4.堆4-1定义4-2特点4-3堆内存溢出4-4堆内存诊断5.方法区5-1定义5-2结构5-3方法区内存溢出5-4通过反... 查看详情

java之自动内存管理机制

一、内存分配1.JVM体系结构2.运行时数据区域3.内存分配二、内存回收1.垃圾收集算法2.垃圾收集器三、相关参考一、内存分配JVM体系结构在了解自动内存管理的内存分配之前,我们先看下JVM的体系结构。代码编译的结果是从本地... 查看详情

jvm之gc日志分析与对象内存分配回收策略(代码片段)

GC日志分析与内存分配回收策略一.GC日志分析的引入二.GC的分类与GC日志结构剖析三.JDK1.9以前的日志分析四.JDK1.9以后的日志分析五.对象内存分配回收策略一.GC日志分析的引入🐬GC日志分析的重要性:阅读分析虚拟机和垃... 查看详情

jvm之直接内存(代码片段)

1.直接内存概述不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。直接内存是在Java堆外的、直接向系统申请的内存区间。来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存通常,访... 查看详情

java虚拟机详解02----jvm内存结构(代码片段)

主要内容如下:JVM启动流程JVM基本结构内存模型编译和解释运行的概念 一、JVM启动流程:JVM启动时,是由java命令/javaw命令来启动的。二、JVM基本结构:JVM基本结构图:《深入理解Java虚拟机(第二版)》中的描述是下面这个... 查看详情

深入理解jvm之知识体系(代码片段)

一.JVM知识体系组成1.JVM内存区域(1)组成部分(2)各部分的作用2.JVM内存溢出(1)内存溢出(2)栈溢出(3)内存区域与溢出的关联3.垃圾回收机制(1)对象存活状态判断(2)垃圾收集算法(3)垃圾收集器(4)垃圾回收过程4.类加载(1)类的生命周期(2)类... 查看详情

flink内核原理学习内存模型(代码片段)

Flink内核原理学习之内存模型文章目录Flink内核原理学习之内存模型一、JVM内存管理的缺点二、TaskManager内存模型三、内存数据结构四、网络传输中的内存管理4.1网络IO内存管理4.2反压机制Java、大数据开发学习要点(持续更新... 查看详情

(超详解)jvm-内存结构(代码片段)

文章目录JVM-内存结构1.程序计数器1-1定义1-2作用1-3特点2.虚拟机栈2-1定义2-2演示2-3常见问题2-4栈内存溢出2-5线程运行诊断3.本地方法栈4.堆4-1定义4-2特点4-3堆内存溢出4-4堆内存诊断5.方法区5-1定义5-2结构5-3方法区内存溢出5-4通过反... 查看详情

jvm内存堆栈监控之jmap篇(代码片段)

...得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等jmap(linux下特有,也是很常用的一个命令)观察运行中的jvm物... 查看详情