JVM总结笔记

JVM

    • JVM是什么?
    • JVM 的主要组成部分
    • JVM工作流程
    • JVM内存模型
    • 直接内存与堆内存的区别:
    • 堆栈的区别
    • Java会存在内存泄漏吗?
    • 简述Java垃圾回收机制
    • 垃圾收集算法
    • 轻GC(Minor GC)和重GC(Full GC)
    • 新生代gc流程
    • JVM优化与JVM调优

JVM是什么?

JVM是Java Virtual Machine(Java虚拟机)的缩写。

虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
简单来说JVM是用来解析和运行Java程序的。

JVM 的主要组成部分

JVM包含两个子系统和两个组件,两个子系统为Class loader(类加载子系统)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。

  • Class loader(类加载子系统):根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area。
  • Execution engine(执行引擎):执行classes中的指令。
  • Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。
  • Runtime data area(运行时数据区域):这就是我们常说的JVM的内存。

JVM工作流程

  1. 通过编译器把 Java 代码转换成字节码
  2. 类加载器(ClassLoader)再把字节码加载到内存中,将其放在运行时数据区(Runtime data area)的方法区内
  3. 字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令
    4.底层系统指令由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
    image-20220621233821401
    image-20220621234016296

JVM内存模型

  • 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
  • Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表基本类型是值、引用类型是句柄或者指针)、操作数栈保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间)、动态链接方法出口等信息(8大基本类型 + 对象引用 + 实例方法);
  • 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
  • Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;从内存回收角度来看java堆可分为:新生代(Young)和老生代(Old)。新生代 ( Young ) 又被划分为三个区域:Eden(伊甸园区)、From Survivor(幸存区2)、To Survivor(幸存区1)。
  • 方法区(Methed Area):用于存储已被虚拟机加载的类信息常量池静态变量(static)、方法信息(修饰符、方法名、返回值、参数等)、即时编译后的代码等数据。

直接内存与堆内存的区别:

直接内存申请空间耗费很高的性能,堆内存申请空间耗费比较低
直接内存的IO读写的性能要优于堆内存,在多次读写操作的情况相差非常明显

堆栈的区别

堆因为是不连续的,所以分配的内存是在运行期确认的,因此大小不固定。一般堆大小远远大于栈。

栈是连续的,所以分配的内存大小要在编译期就确认,大小是固定的。

存放的内容不同

堆存放:对象的实例和数组。因此该区更关注的是数据的存储

栈存放:局部变量,操作数栈,返回结果。该区更关注的是程序方法的执行。

Java会存在内存泄漏吗?

内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。理论上来说,Java是有GC垃圾回收机制的,不再被使用的对象,会被GC自动回收掉,自动从内存中清除。

但是,即使这样,Java也还是存在着内存泄漏的情况,java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。泄漏积少成多,内存泄漏 会导致 内存溢出。

内存溢出(OOM) 是指 程序在申请内存时,没有足够的内存空间供其使用,出现内存溢出。

解决:①设置JVM的堆参数( -Xmx:JVM最大内存 -Xms:启动初始内存 -Xmn:新生代大小 -Xss:每个线程虚拟机栈及堆栈的大小 ) 例如:-Xms1024m -Xmx1024m -Xmn512m -Xss5m

​ ②分析内存,看一下那个地方出现了问题(专业工具:Jprofiler,MAT)分析Dump内存文件, 快速定位内存泄漏,怎么查找dump文件,直接找到文件的文件夹打开获得大的对象。

简述Java垃圾回收机制

垃圾回收机制简称GC。在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

Java中的垃圾回收是根据可达性分析算法引用计数算法来判断对象是否存活的。

System.gc(); // 手动回收垃圾

垃圾收集算法

  • 标记清除算法:首先标记所有需要回收的对象,在标记完成后回收所有被标记的对象。
    优点:算法比较简单
    缺点:会产生大量不连续的内存碎片,而且效率不高

  • 复制算法
    这种算法会将内存划分为两个相等的块,每次只使用其中一块。当这块内存不够使用时,就将还存活的对象复制到另一块内存中,然后把这块内存一次清理掉。年轻区主要用复制算法,幸存区复制,一般都是from复制到to,谁空谁是to,适用与对象存活度较低。
    优点:效率比较高,也避免了内存碎片。
    缺点:因为另一半内存一直是空的,比较浪费空间。

  • 标记-整理算法

    标记-清除算法的升级版,也叫标记-压缩算法。在完成标记阶段后,不是直接对可回收对象进行清理,而是让存活对象向着一端移动,然后清理掉边界以外的内存。

    优点:避免了内存碎片和内存利用效率低。
    缺点:增加了一个移动的成本。

  • 分代收集算法
    年轻代:存活率低-复制算法
    老年代:区域大存活率高-标记清除+标记整理算法混合实现

轻GC(Minor GC)和重GC(Full GC)

Minor GC:当新对象去伊甸园区(Eden)申请内存失败的时候,就会进行Minor GC,对伊甸园区(Eden)回收非存活对象,而没有被回收的对象,会进入幸存区(Survivor),这种GC只发生在伊甸园区(Eden),不会影响到老年区。因为新对象分配内存大部分都在伊甸园区(Eden),所以伊甸园区(Eden)GC比较频繁。

注意:在GC之后,还存活的对象,进入幸存区(Survivor),谁空谁是to,可以交换位置,当一个对象经历了15次GC(可以配置次数:-XX:+MaxTenuringThreshold=15),还存活,就进入老年区。

Full GC

清理整个堆,因为Full GC需要对整个堆进行回收,所以比Minor GC慢,因为我们要尽可能的减少Full GC的次数。我们所说的JVM调优,很大一部分就是对Full GC的优化。

会造成 Full GC:

  • 老年区满了:年轻区的对象转入或创建大对象才会满。
  • 方法区满了(jdk8及之后版本):系统中要加载的类过多。
  • System.gc() 被显示调用
  • 通过Minor GC后进入老年代的平均大小大于老年代的可用内存:第一次Minor GC之后,有2MB的对象转入老年区,然后在下一次Minor GC的时候就会判断老年区的空间是否有2MB,如果没有就进行Full GC。

新生代gc流程

  1. 刚刚新建的对象在Eden中,经历一次Minor GC,Eden中存活对象就会被移动到幸存区1,Eden被清空。

  2. 等Eden区再满了,触发Minor GC,Eden和幸存区1中存活的对象又会被复制到幸存区2中(这个过程非常重要,因为这种复制算法保证了幸存区2中来自幸存区1和Eden两部分的存活对象占用了连续的空间,避免碎片化)

  3. 幸存区1和Eden被清空,然后下一轮幸存区1与幸存区2互换角色,如此循环,经历15次GC,还存活对象,放进入老年区

JVM优化与JVM调优

JVM优化:JVM本身自带的编译时、运行时的优化机制,各个jdk版本会有些不同,不需要程序员干涉,程序员学习了解即可;

JVM调优(JVM性能调优)是程序员设置虚拟机参数(不直接使用默认参数)满足自己的需求,是程序员的一项工作技能。

JVM性能调优的目标:使用较小的内存占用来获得较高的吞吐量(计算型)或者较低的延迟(交互型)。
规则

我们要对Java堆分配策略进行优化,合理规划Java堆容量、年轻代、老年代比例,使自动内存分配和回收高效进行,这里关注内存回收,即GC操作。

第一条要求GC整个垃圾收集过程,消耗的时间尽量小就必须要一个更小的堆,

第二条要求GC整个垃圾收集过程,次数尽量少,必须保证一个更大的堆

注意,第一条要求和第二条要求是互斥的,不能同时满足,我们要把握一个适度适中的原则,一个相对大小的堆。

第三条要求老年代的空间比例尽量大一些,这样Full GC的次数就会比较少,周期比较长,要平均相隔比较长的一段时间才有一个Full GC,即Full GC一定不要太频繁。

即第一条和第二条要求是一个大小适中的堆,第三条要求这个堆中老年代的空间容量比例尽量高一些。

技巧

新生代中Eden:Survivor默认是8:1,一般不改动,JVM调优集中在新生代和老年代大小比例,新生代和老年代默认比例是1:2。

JVM性能调优原则(优先代码调优,参数调优作为补充)

  1. 在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。

  2. 初始堆值和最大堆内存内存越大,吞吐量就越高,但是也要根据自己电脑(服务器)的实际内存来比较。

  3. 最好使用并行收集器,因为并行收集器速度比串行吞吐量高,速度快。当然,服务器一定要是多线程的

  4. 减少GC对老年代的回收。设置生代带垃圾对象最大年龄,进量不要有大量连续内存空间的java对象,因为会直接到老年代,内存不够就会执行GC

代码调优经验

  1. 避免创建过大的对象及数组:过大的对象或数组在新生代没有足够空间容纳时会直接进入老年代,如果是短命的大对象,会提前出发Full GC。
  2. 避免同时加载大量数据,如一次从数据库中取出大量数据,或者一次从Excel中读取大量记录,可以分批读取,用完尽快清空引用。
  3. 对象引用及时置null,当集合中有对象的引用,这些对象使用完之后要尽快把集合中的引用清空,这些无用对象尽快回收避免进入老年代。
  4. 尽量避免长时间等待外部资源(数据库、网络、设备资源等),缩小对象的生命周期,避免进入老年代,如果不能及时返回结果可以适当采用异步处理的方式等

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

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

相关文章

第五章 Opencv图像处理框架实战 5-3 图像阈值与平滑处理

图像阈值 ret, dst cv2.threshold(src, thresh, maxval, type) src: 输入图,只能输入单通道图像,通常来说为灰度图 dst: 输出图 thresh: 阈值 maxval: 当像素值超过了阈值(或者小于阈值&am…

字符串性能优化

String 对象作为 Java 语言中重要的数据类型,是内存中占据空间最大的一个对象。高效地 使用字符串,可以提升系统的整体性能。 来一到题来引出这个话题 通过三种不同的方式创建了三个对象,再依次两两匹配,每组被匹配的两个对象是否…

分布式开源监控Zabbix实战

Zabbix作为一个分布式开源监控软件,在传统的监控领域有着先天的优势,具备灵活的数据采集、自定义的告警策略、丰富的图表展示以及高可用性和扩展性。本文简要介绍Zabbix的特性、整体架构和工作流程,以及安装部署的过程,并结合实战…

word里的页码问题

封面不需要页码怎么办 一份文档写完,如果需要页码,第一页是封面,封面不需要页码怎么办? 解决:打开页眉页脚,然后把首页不同勾选上,这一页就没有页码了。 目录页与正文页码格式不同怎么办 目录…

JIT 与 C#热更

JIT与AOT 一般程序运行有两种方式,静态编译与动态编译。 AOT: Ahead Of Time,预先(静态)编译 静态编译的程序,需要在执行之前全部翻译为机器码,运行前会使得程序安装时间相对较长,但程序运行的时候&#…

网络安全策略应包含哪些?

网络安全策略是保护组织免受网络威胁的关键措施。良好的网络安全策略可以确保数据和系统的保密性、完整性和可用性。以下是一个典型的网络安全策略应包含的几个重要方面: 1. 强化密码策略:采用强密码,要求定期更换密码,并使用多因…

【MySQL】mysql | linux | 离线安装mysqldump

一、说明 1、项目要求离线安装mysqldump 2、数据库服务已经使用docker进行安装,但是其他项目依赖mysqldump,所以需要在宿主机上安装mysqldum 二、解决方案 1、下载依赖 https://downloads.mysql.com/archives/community/ 2、下载内容 mysql-community-c…

【MyBatis】 框架原理

目录 10.3【MyBatis】 框架原理 10.3.1 【MyBatis】 整体架构 10.3.2 【MyBatis】 运行原理 10.4 【MyBatis】 核心组件的生命周期 10.4.1 SqlSessionFactoryBuilder 10.4.2 SqlSessionFactory 10.4.3 SqlSession 10.4.4 Mapper Instances 与 Hibernate 框架相比&#…

目标检测中 anchor base和anchor free

目标检测中两种不同anchor的生成 趋势:anchor free越来越受到实时性检测的青睐,,,

【LeetCode】不同路径Ⅱ

不同路径Ⅱ 题目描述算法流程编程代码 链接: 不同路径Ⅱ 题目描述 算法流程 编程代码 class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& ob) {int m ob.size();int n ob[0].size();vector<vector<int>>dp(m1,vecto…

Spring | Bean 作用域和生命周期

一、通过一个案例来看 Bean 作用域的问题 Spring 是用来读取和存储 Bean&#xff0c;因此在 Spring 中 Bean 是最核心的操作资源&#xff0c;所以接下来我们深入学习⼀下 Bean 对象 假设现在有⼀个公共的 Bean&#xff0c;提供给 A 用户和 B 用户使用&#xff0c;然而在使用的…

【嵌入式学习笔记】嵌入式入门2——中断(外部中断)

1.什么是中断 打断CPU执行正常的程序&#xff0c;转而处理紧急程序&#xff0c;然后返回原暂停的程序继续运行&#xff0c;就叫中断 1.1.中断的作用与意义 作用1&#xff1a;实时控制在确定时间内对相应事件作出响应——定时器中断作用2&#xff1a;故障处理检测到故障&…

基于linux下的高并发服务器开发(第四章)- 多进程实现并发服务器(回射服务器)

1. socket // 套接字通信分两部分&#xff1a; - 服务器端&#xff1a;被动接受连接&#xff0c;一般不会主动发起连接 - 客户端&#xff1a;主动向服务器发起连接 2.字节序转换函数 当格式化的数据在两台使用不同字节序的主机之间直接传递时&#xff0c;接收端必然错误…

无涯教程-jQuery - Spinner组件函数

Widget Spinner 函数可与JqueryUI中的窗口小部件一起使用。Spinner提供了一种从一组中选择一个值的快速方法。 Spinner - 语法 $( "#menu" ).selectmenu(); Spinner - 示例 以下是显示Spinner用法的简单示例- <!doctype html> <html lang"en"…

CentOS 项目发出一篇奇怪的博文

导读最近&#xff0c;在红帽限制其 RHEL 源代码的访问之后&#xff0c;整个社区围绕这件事发生了很多事情。 CentOS 项目发出一篇奇怪的博文 周五&#xff0c;CentOS 项目董事会发出了一篇模糊不清的简短博文&#xff0c;文中称&#xff0c;“发展社区并让人们更容易做出贡献…

代码随想录算法训练营第五天| 242. 有效的字母异位词,349. 两个数组的交集,202快乐数,1. 两数之和

哈希表 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用来快速判断…

29.利用fminbnd 求解 最大容积问题(matlab程序)

1.简述 用于求某个给定函数的最小值点。 使用方法是&#xff1a; xfminbnd(func,x1,x2) func是函数句柄&#xff0c;然后x1和x2就是函数的区间&#xff0c;得到的结果就是使func取最小值的x值 当然也可以使用[x,fv]fminbnd(func,x1,x2)的方式&#xff0c;这个时候fv就是函数…

Web3.0:已经开启的互联网革命!

1 痛点 2 web发展形态 只读、封闭式、协作式。 3 一个高度联系、全球统一的数字经济体 去中心化架构通过计算几余打破数据垄断&#xff0c;同时实现数字确权大量的功能依靠智能合约自动实现&#xff0c;运转效率大大提升DAO大量涌现&#xff0c;全球范围实现资源配置 4 特…

MAC电脑设置charles,连接手机的步骤说明(个人实际操作)

目录 一、charles web端设置 1. 安装charles之后&#xff0c;先安装证书 2. 设置 Proxy-Proxy Settings 3. 设置 SSL Proxying 二、手机的设置 1. 安卓 2. ios 资料获取方法 一、charles web端设置 1. 安装charles之后&#xff0c;先安装证书 Help-SSL Proxying-Inst…

我的第一个前端(VS code ,Node , lite-server简易服务器,npm 运行)

第一种方式&#xff1a;使用Visual Studio Code创建并运行 第一个前端项目的步骤&#xff0c;如下&#xff1a; 1. 下载和安装Visual Studio Code&#xff1a; 访问Visual Studio Code官方网站&#xff08;Visual Studio Code - Code Editing. Redefined&#xff09;并根据你…