JVM基础学习---2、总体机制中不重要的部分、方法区、虚拟机栈

简介: JVM基础学习---2、总体机制中不重要的部分、方法区、虚拟机栈

1、总体机制中不重要的部分

1.1 本地接口 Native Interface

本地接口的作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序。因为 Java 诞生的时候是 C/C++ 横行的时候,要想立足,必须有能力调用 C/C++。于是就在内存中专门开辟了一块区域处理标记为 native 的代码,它的具体做法是 Native Method Stack 中登记 native 方法,在Execution Engine 执行时加载 native libraies。

目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过 Java 程序驱动打印机或者 Java 系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用 Socket 通信,也可以使用 Web Service 等等,不多做介绍。

1.2 本地方法栈 Native Method Stack

专门负责在本地方法运行时,提供栈空间,存放本地方法每一次执行时创建的栈帧。它的具体做法是在 Native Method Stack 中登记 native 方法,在 Execution Engine 执行时加载本地方法库。

native方法举例:

public static native void yield();

栈:stack

堆:heap

如果抛开JVM内存结构,单独来看栈和堆其实是没有区别的,都是只先进后出的数据结构。

1.3 程序计数器

也叫PC寄存器(Program Counter Register)。用于保存程序执行过程,下一条即将执行的指令的地址。也就是说能够保存程序当前已经执行到的位置。这个位置由执行引擎读取下一条指令,是一个非常小的内存空间,从内存空间使用优化这个角度来看:几乎可以忽略不记。

1.4 执行引擎 Execution Engine

63225bc215714040b379ea6000e8f68b.png

作用:用于执行字节码文件中的指令。

执行指令的具体技术:

解释执行:第一代JVM

即时编译:JIT,第二代JVM。

自适应优化:目前Sun的Hotspot JVM采用这种技术。吸取了第一代JVM和第二代JVM的经验,在一开始的时候对代码进行解释执行, 同时使用一个后台线程监控代码的执行。如果一段代码经常被调用,那么就对这段代码进行编译,编译为本地代码,并进行执行优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行。

芯片级直接执行:内嵌在芯片上,用本地方法执行Java字节码。

1.5 直接内存

fe9f3beb4b7c41c9929613bfa1941f49.png

1、作用

在特定场景提高性能

2、应用场景

直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。 本机直接内存的分配不会受到 Java 堆大小的限制,受到本机总内存大小限制。 配置虚拟机参数时,不要忽略直接内存防止出现 OutOfMemoryError 异常。

3、直接内存和堆内存比较

直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显。直接内存I/O读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显。

2、方法区

2.1 概念

  • 标准层面:方法区(Method Area)
  • 具体实现层面:
  • <=1.6 永久代(PermGen)
  • =1.7永久代依然存在,但是已经开始提出:去永久代。
  • =1.8元空间(Meta Space)。

2.2 概念的辨析

  • 从方法区角度来说
  • 方法区的具体实现:JDK<=1.7时,使用永久代作为方法区
  • 方法区的具体实现:JDK>=1.8时,使用元空间作为方法区。
  • 从堆空间角度来说
  • 新生代:从标准和实现层面都确定属于堆
  • 老年代:从标准和实现层面都确定属于堆。
  • 永久代
  • 名义上属于堆
  • 实现上不属于堆,它另外有一个名字:非堆(Non-heap)
  • 339703881cbd405b939de973933ca471.png

2.3 方法区存放内容

类信息:类中定义的构造器、接口的定义

静态变量(类变量):private static String some;

常量:public static final String SYS_MEDDAGE=“hello”

运行时常量池:“a”、“abc”

类中静态方法的代码

2.4 类加载机制和方法区的关系

类加载到JVM内存后,类的静态储存结构转化为方法区的运行时数据结构

类加载后,会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区中这个类的各种数据的访问入口。

类的字节码文件中有存放静态数据的常量池,类加载到内存后,字节码文件中的常量池会映射到方法区中的常量池。

说明:即使多个线程执行的是同一个方法,也并不是都拥挤到方法区去找方法代码。而是取得一份方法中代码指令的拷贝。

3、虚拟机栈

3.1 总体结构

5d1f6dfb6a75474a91d47c90fce40167.png

3.2 栈帧

方法的每一次调用都会产生一个栈帧,线程中每一次调用一个方法,就会在虚拟机栈中开辟一块空间保存栈帧。

方法本次执行完成,本次执行对应的栈帧就会被释放。

整个线程要调用的所以方法都执行完成,则整个线程空间释放。

1、栈帧储存的数据

方法在本次执行过程中所用到的局部变量、动态链接、方法出口等信息。栈帧中主要保存三类数据:

本地变量(Local Variables):也叫局部变量,输入参数和输出参数以及方法内的变量。

栈操作(Operate Stack):记录出栈、入栈操作

栈帧数据(Frame Data):包括类文件、方法等等

2、栈帧的结构

局部变量表:方法执行时的参数、方法体内声明的局部变量

操作数栈:存储中间运算结果,是一个临时储存空间。

栈数据区:保存访问常量池指针,异常处理表

3、栈帧工作机制

当一个方法 A 被调用时就产生了一个栈帧 F1,并被压入到栈中,

A 方法又调用了 B 方法,于是产生栈帧 F2 也被压入栈,

B 方法又调用了 C 方法,于是产生栈帧 F3 也被压入栈,

……

C 方法执行完毕后,弹出 F3 栈帧;

B 方法执行完毕后,弹出 F2 栈帧;

A 方法执行完毕后,弹出 F1栈帧;

……

遵循“先进后出”的原则

9dbd4ea33860454a974aa8b13c01099b.png

图示在一个栈中有两个栈帧:

栈帧 2 是最先被调用的方法,先入栈,

然后方法 2 又调用了方法 1,栈帧 1 处于栈顶的位置,

栈帧 2 处于栈底,执行完毕后,依次弹出栈帧 1 和栈帧 2,

线程结束,栈释放。

每执行一个方法都会产生一个栈帧,保存到栈的顶部,顶部栈就是当前方法,该方法执行完毕后会自动将此栈帧出栈。

两组配套概念:

①串行,同步操作,按顺序执行,前一个操作不执行完后面操作就要等待

②并行,异步操作,由操作系统和CPU调度,不同操作之间不需要互相等待


相关文章
|
20天前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
|
1月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
25天前
|
存储 缓存 Java
JVM中的方法区
这篇文章介绍了JVM中方法区的概念和作用,包括它所存储的内容(类型信息、常量、静态变量、编译后的代码缓存),常量池与运行时常量池的功能,以及方法区与栈、堆的交互关系。
JVM中的方法区
|
1月前
|
监控 算法 Java
深入理解Java虚拟机:JVM调优与性能提升
本文旨在为Java开发者提供一条清晰的路径,以深入掌握Java虚拟机(JVM)的内部机制和性能调优技巧。通过具体案例分析,我们将探讨如何识别性能瓶颈、选择合适的工具进行监控与调试,以及实施有效的优化策略,最终达到提高应用程序性能的目的。文章不仅关注理论,更注重实践应用,帮助读者在面对复杂的Java应用时能够游刃有余。
42 0
|
18天前
|
存储 算法 Oracle
不好意思!耽误你的十分钟,JVM内存布局还给你
先赞后看,南哥助你Java进阶一大半在2006年加州旧金山的JavaOne大会上,一个由顶级Java开发者组成的周年性研讨会,公司突然宣布将开放Java的源代码。于是,下一年顶级项目OpenJDK诞生。Java生态发展被打开了新的大门,Java 7的G1垃圾回收器、Java 8的Lambda表达式和流API…大家好,我是南哥。一个Java学习与进阶的领路人,相信对你通关面试、拿下Offer进入心心念念的公司有所帮助。
不好意思!耽误你的十分钟,JVM内存布局还给你
|
26天前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
26天前
|
存储 Java 程序员
JVM自动内存管理之运行时内存区
这篇文章详细解释了JVM运行时数据区的各个组成部分及其作用,有助于理解Java程序运行时的内存布局和管理机制。
JVM自动内存管理之运行时内存区
|
25天前
|
存储 安全 Java
JVM内存结构
这篇文章详细介绍了Java虚拟机(JVM)的内存结构,包括类的加载过程、类加载器的双亲委派机制、沙箱安全机制、程序计数器、Java栈、Java堆、本地方法和本地方法栈等关键组件及其作用。
JVM内存结构
|
2月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
|
2月前
|
存储 缓存 算法
(五)JVM成神路之对象内存布局、分配过程、从生至死历程、强弱软虚引用全面剖析
在上篇文章中曾详细谈到了JVM的内存区域,其中也曾提及了:Java程序运行过程中,绝大部分创建的对象都会被分配在堆空间内。而本篇文章则会站在对象实例的角度,阐述一个Java对象从生到死的历程、Java对象在内存中的布局以及对象引用类型。