十二.吊打面试官系列-JVM优化-深入JVM内存模型

JVM内存模型

1.JVM的组成

整个JVM组成由 :运行时数据区 , 类加载子系统 , 执行引擎 , 本地方法库 几部分组成
在这里插入图片描述
上面是Java7的内存模型,Java8以后做了一些调整,把方法区变成了元空间,元空间不在JVM中,而使用直接内存(计算机内存)

  1. 运行时数据区

    见名知意,运行时数据区是Java虚拟机在执行Java程序时,用于存储和管理运行时数据的内存区域,运行时数据区由: 方法区,虚拟机栈,本地方法栈,程序计数器,堆 五部分组成,其中堆和方法区是线程共享的,其他区域是线程隔离的,也就是线程私有,比如:程序计数器在每个线程执行的时候都有一个私有的程序计数器

  2. 类加载子系统

    类加载器子系统的主要作用是负责从文件系统或网络中加载.class文件,并将其加载到JVM中。加载后的类信息存放在方法区(或JDK 8及以后版本的元空间)中,具体的执行则交给执行引擎去操作

  3. 执行引擎

    JVM(Java Virtual Machine)执行引擎是JVM的核心组件之一,它负责将编译后的字节码(Bytecode)解释成可执行的机器指令。而JIT(Just-In-Time)编译器则是执行引擎中的一个重要部分,用于提高Java程序的执行效率。

    JVM执行引擎的主要任务是将字节码转换为特定平台上的本地机器指令,以便在JVM上执行。它主要包括解释器(Interpreter)和JIT编译器两部分。

    解释器是JVM执行引擎的基本组件之一,它采用逐行解释的方式执行字节码。当JVM启动时,解释器会根据预定义的规范对字节码进行解释,将每条字节码指令“翻译”为对应平台的本地机器指令并执行。然而,由于解释执行的方式效率较低,因此JVM还引入了JIT编译器来优化性能。

  4. JIT编译器

    JIT编译器是JVM执行引擎中的另一个重要组件,它可以在程序运行时将频繁执行的字节码编译为本地机器码,从而提高执行效率。JIT编译器通过动态编译技术,将热点代码(即频繁执行的代码)优化为本地机器码,并存储在代码缓存区中。在后续的执行中,JVM可以直接从代码缓存区中加载机器码并执行,而无需再次解释字节码。这种方式可以显著提高Java程序的执行速度

  5. 本地方法库接口

    本地方法库接口(Native Method Interface,简称JNI),它允许Java代码与其他语言写的代码进行交互。JNI是Java虚拟机(JVM)提供的一组函数和协议,用于Java应用程序与本地应用程序(如C、C++编写的程序)进行交互。本地方法库就是C,C++编写的一些代码库,比如: xxx.dll文件,在Java中很多功能底层就是C++来实现的。

下面我们针对这些区域详细来说明

2.程序计数器

程序计数器是线程私有的,虽然名字叫计数器,但主要用途还是用来确定指令的执行顺序,比如循环,分支,跳转,异常捕获等。它记录了当前线程执行的字节码指令的地址。JVM对于多线程的实现是通过轮流切换线程实现的,所以为了保证每个线程都能按正确顺序执行,将程序计数器作为线程私有.程序计数器是唯一一个JVM没有规定任何OOM的区块.(out of memory)

程序计数器是一块非常小的内存空间,可以看做是当前线程执行字节码的行号指示器,每个线程都有一个独立的程序计数器,因此程序计数器是线程私有的一块空间,此外,程序计数器是Java虚拟机规定的唯一不会发生内存溢出的区域

3.方法区(元空间)

方法区主要用于存储虚拟机加载的类信息、常量、静态变量,以及编译器编译后的代码等数据。在jdk1.7及其之前,方法区是堆的一个“逻辑部分”(一片连续的堆空间),但为了与堆做区分,方法区还有个名字叫“非堆”,也有人用“永久代”(HotSpot对方法区的实现方法)来表示方法区。

jdk1.7已经开始准备“去永久代”的规划,jdk1.7的HotSpot中,已经把原本放在方法区中的静态变量、字符串常量池等移到堆内存中,(常量池除字符串常量池还有class常量池等),这里只是把字符串常量池移到堆内存中;在jdk1.8中,方法区已经不存在,原方法区中存储的类信息、编译后的代码数据等已经移动到了元空间(MetaSpace)中,元空间并没有处于堆内存上,而是直接占用的本地内存(NativeMemory)。元空间的大小仅受本地内存限制
在这里插入图片描述
JVM在后续版本中去掉永久代(PermGen)的原因主要有以下几点:

  • 避免内存溢出(OOM)问题:永久代存储的是类信息、常量、静态常量等信息,因此存储空间不容易界定,容易发生内存溢出问题(如常见的java.lang.OutOfMemoryError: PermGen space异常)。在Java 8中,采用了元空间(Metaspace)代替永久代,元空间使用的是直接系统内存,可以动态地扩展和收缩,从而避免了永久代空间不足导致的内存溢出问题。
  • 提高垃圾回收效率:相对于新生代回收效率(通常为70~95%),永久代的垃圾收集效率较低。这主要是因为永久区的回收机制相对新生代来说更为复杂,要求条件更多。去掉永久代后,采用元空间可以更好地管理类的元数据,提高垃圾回收的效率。
  • 统一内存管理:去掉永久代也是为了更好地融合HotSpot JVM与其他JVM(如JRockit VM),因为JRockit VM并没有永久代的概念。这样做可以使得JVM的内存管理更加统一和标准化。
  • 避免内存泄漏:永久代中的某些数据(如类加载器)可能在不再需要时仍然被引用,导致内存泄漏。采用元空间后,可以更好地管理这些数据,避免内存泄漏问题。

需要注意的是,虽然永久代已经被去掉,但方法区(Method Area)的概念仍然存在。方法区主要用于存储类的信息、常量池、方法数据、方法代码等。在Java 8及以后的版本中,方法区的实现由元空间来完成。Java8内存模型如下
在这里插入图片描述

4.虚拟机栈

Java虚拟机栈也是线程私有的,每个方法执行都会创建一个栈帧,局部变量就存放在栈帧中,还有一些其他的动态链接之类的.

虚拟机会为每个线程分配一个虚拟机栈,每个虚拟机栈中都有若干个栈帧,每个栈帧中存储了局部变量表、操作数栈、动态链接、返回地址等。一个栈帧就对应Java代码中的一个方法,当线程执行到一个方法时,就代表这个方法对应的栈帧已经进入虚拟机栈并且处于栈顶的位置,每一个Java方法从被调用到执行结束,就对应了一个栈帧从入栈到出栈的过程
在这里插入图片描述

  • 栈帧(方法执行形成栈帧):栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构,线程私有。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用至执行完成的过程,都对应着一个栈帧在虚拟机栈里从入栈到出栈的过程,栈帧随着方法调用而创建,随着方法结束而销毁

  • 局部变量表(储存方法参数和局部变量):局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。局部变量表的容量以变量槽(Variable Slot)为最小单位,Java虚拟机规范并没有定义一个槽所应该占用内存空间的大小,但是规定了一个槽应该可以存放一个32位以内的数据类型。

  • 操作数栈(用于计算的临时数据存储区):操作数栈(Operand Stack)也常称为操作栈,它是一个后入先出栈(LIFO),当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。

  • 动态链接(用来转化方法的内存地址直接引用的):在一个class文件中,一个方法要调用其他方法, 需要将这些方法的符号引用转化为其在内存地址中的直接引用,而符号引用存在于方法区中的运行时常量池。

  • 返回地址:方法的返回出口,一般就是调用该方法的上一个方法的地址。

下面是一个类中的方法执行的详细流程:以Hello.class 为例

  1. 首先当使用到Hello的时候比如:new Hello(),类加载子系统会把Hello.class 加载到JVM中,存储到元空间,并且会把 new Hello 对象实例存储到堆中
  2. 程序是通过执行引擎去执行的,它通过驱动线程来执行Hello,线程会分得一个私有的虚拟机栈,每个方法执行都会形成栈帧进行压栈。
  3. 随着方法的调用结束,后被调用的方法就先出栈,最先被调用的方法最后出栈,随着方法全部执行完成,栈帧释放,线程结束。
  4. 如果方法中有对象的引用,那么方法结束后局部变量也被释放,那堆中的对象实例就没有引用关系将被识别为垃圾,等待垃圾回收器回收
    在这里插入图片描述

5.本地方法栈

本地方法栈与虚拟机栈的区别是,虚拟机栈执行的是Java方法,本地方法栈执行的是本地方法(Native Method),其他基本上一致,在HotSpot中直接把本地方法栈和虚拟机栈合二为一,这里暂时不做过多叙述。

6.堆内存

堆和方法区一样(确切来说JVM规范中方法区就是堆的一个逻辑分区),就是一个所有线程共享的,存放对象的区域,也是GC的主要区域.其中的分区分为新生代(YoungGeneration),老年代(OldGeneration).新生代中又可以细分为一个Eden,两个Survivor区(From,To).Eden中存放的是通过new 或者newInstance方法创建出来的对象

绝大多数都是很短命的.正常情况下经历一次gc之后,存活的对象会转入到其中一个Survivor区,然后再经历默认15次的gc,就转入到老年代.这是常规状态下,在Survivor区已经满了的情况下,JVM会依据担保机制将一些对象直接放入老年代。`
在这里插入图片描述
文章到此结束,码字很辛苦,如果对你有所帮助请给个好评。下一章:深入分析class字节码文件结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/628790.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Blender雕刻建模流程

1.构形 先构造一个大致相像的外形 可使用的方法包含 -多边形:表面细分,布尔 -曲线:曲线倒角 -融球(使用较少) -曲面(使用较少) 构形之后的准备 -应用缩放 -应用修改器 -曲线转网格 1.1…

【BOSS直聘爬取系统功能介绍】

完整代码关注公众号 : 爬取网站:BOSS直聘:https://www.zhipin.com/ 难点 1. boss直聘不论什么岗位都只会展示10页数据,就算在网页里加到了11,内容也会和10一样。 2.多次访问会有验证码需要登录,这部分需…

3SRB2516-ASEMI适配大功率充电桩3SRB2516

编辑:ll 3SRB2516-ASEMI适配大功率充电桩3SRB2516 型号:3SRB2516 品牌:ASEMI 封装:SGBJ-5 正向电流(Id):25A 反向耐压(VRRM):1600V 正向浪涌电流&…

【3dmax笔记】028:倒角的使用方法

一、倒角描述 在3dmax中创建倒角效果可以通过多种方法实现,以下是几种常见的方法: 使用倒角修改器。首先创建一个图形(如矩形和圆),然后对齐它们,将它们转化为可编辑样条线,并附加在一起,选择要倒角的边缘,然后使用倒角修改器来调整高度、轮廓等参数。使用倒角剖面修…

听劝!普通人千万别随意入门网络安全

一、什么是网络安全 网络安全是一种综合性的概念,涵盖了保护计算机系统、网络基础设施和数据免受未经授权的访问、攻击、损害或盗窃的一系列措施和技术。经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”…

校园防欺凌平台

校园霸凌事件很难被发现,发现者又可能迫于威胁而不敢告发,被霸凌者又因各种原因而选择忍耐,所以,如果能够在发生校园霸凌的时候,做出及时的预警,也许能够拯救挽回无数个家庭。本平台结合防欺凌设备&#xf…

【js刷题:数据结构链表之设计链表】

设计链表 一、题目二、题解 一、题目 二、题解 // 定义节点类,每个节点都有一个值和一个指向下一个节点的引用 class LinkNode{constructor(val,next){ // 构造函数,接收节点值和下一个节点的引用this.valval // 节点的值this.nextnext // 指…

查看Linux服务器的硬盘占用情况

查看Linux服务器的硬盘占用情况 一、查看各分区的使用情况和磁盘挂载1、查看磁盘分区使用和磁盘挂载2、结果解释(1)列名解释(2)各系统解释 二、查看一个目录及其所有子目录中文件的总占用大小1、查看指定目录的总大小2、列出目录下…

山东齐鲁文化名人颜廷利:汉语自媒体里面的真正文字智慧

在这个数字技术日新月异的时代,大数据和人工智能等技术的兴起已经深刻地改变了信息的传播方式。特别是随着自媒体的兴起,传统的物质形态的报刊杂志已迅速转变为无形的知识与智慧的流动,这种转变不仅改变了信息的传递手段,更释放出…

GIT基础02 多机器协作等命令

前言 首先我们知道git给我们提供了分支管理的功能 我们一般使用master分支作为线上环境,master分支一般是一个稳定的分支 我们通常是会创建一个其他分支进行开发,这样不会影响线上的机器运行 如果没有git提供这样的分支功能,就无法做到这一套了 指令学习 假设软件出现问题咋办…

SWAT模型高阶应用暨SWAT模型无资料地区建模、不确定分析及气候、土地利用变化对水资源与面源污染影响分析

原文链接:SWAT模型高阶应用暨SWAT模型无资料地区建模、不确定分析及气候、土地利用变化对水资源与面源污染影响分析https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247604401&idx4&snd2d39846dce07bee765c820de1cf92f3&chksmfa821956cdf5904…

长期的图片活码怎么做?在线制作图片活码的方法

现在通过扫描二维码来查看内容的方式,在日常生活中越来越常见,其中扫码看图就是很常用的一种方式。在很多的公共场所或者宣传单页上,扫码后即可查看相关的图片信息,从而获取我们需要的内容,那么在电脑上将图片生成二维…

Pencils Protocol Season 2 收官在即,Season 3 携系列重磅权益来袭

此前Scroll生态LaunchPad &聚合收益平台Pencils Protocol(原Penpad),推出了首个资产即其生态代币PDD的Launch,Season 2活动主要是用户通过质押ETH代币、组件战队等方式,来获得Point奖励,并以该Point为依…

高低温试验箱工厂分享:设备如何保养更节约成本

高低温试验箱在现代产业中起到重要的作用,能够帮助企业进行产品质量和性能的测试,而且这种设备也是一种常见的用于模拟各种极端温度环境的设备。所以这种在特殊环境下使用的设备,维护和保养是关键,正确的保养和维护可以延长设备的…

Spring初学入门(跟学笔记)

一、Spring概述 Spring是一款主流的Java EE轻量级开源框架。 Spring的核心模块:IoC(控制反转,指把创建对象过程交给Spring管理 )、AOP(面向切面编程,在不修改源代码的基础上增强代码功能) 二、…

LeetCode刷题笔记第1800题:最大升序子数组和

LeetCode刷题笔记第1800题:最大升序子数组和 题目: 想法: 遍历数组的同时记录当前最大升序子数组和,最终返回最大升序子数组和 class Solution:def maxAscendingSum(self, nums: List[int]) -> int:result 0i 0n len(num…

istio资源字段参考文档

virtual service: Istio / Virtual ServiceConfiguration affecting label/content routing, sni routing, etc.https://istio.io/latest/docs/reference/config/networking/virtual-service/

网站开发初学者指南:2024年最新解读

在信息交流迅速的时代,网页承载着大量的信息,无论你知道还是不知道,所以你知道什么是网站开发吗?学习网站开发需要什么基本技能?本文将从网站开发阶段、网站开发技能、网站开发类型等角度进行分析,帮助您更…

Vue.js 详细介绍

文章目录 一、Vue.js 简介1.1 什么是 Vue.js?1.2 Vue.js 的特点 二、快速上手 Vue.js2.1 安装 Vue.js使用 CDN使用 npm 或 yarn 2.2 创建一个 Vue 实例2.3 Vue.js 项目结构 三、Vue.js 核心概念3.1 数据绑定3.2 指令(Directives)3.3 组件&…

IDEA不能创建新项目和新模块

问题: IDEA不管是创建新项目还是新模块都创建不成功,会报如下图错误 解决方案: 在电脑设置里搜索 “防火墙和网络保护” ,打开如下图所示 找到你所安装的IDEA,更改设置,选中IDEA 最后,确定&am…