JVM总结笔记

news2024/11/16 9:39:38

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.coloradmin.cn/o/817998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【自用记录】常见的第三方接口加密签名方式(ASCll码字典序、URL键值对、 SHA-256加密、MD5加密)

案例1: 案例2: 以上第三方接口都用类似的加密签名方式,两者有类似的部分: 方案1的: $kdata = array(parkId=>$parkId,ts => $ts,serviceCode=>getParkingPaymentList,reqId => $reqId,plateNo => $car_code,//车牌 可为空pageIndex => 1,//第几页page…

15. Spring AOP 的实现原理 代理模式

目录 1. 代理模式 2. 静态代理 3. 动态代理 3.1 JDK 动态代理 3.2 CGLIB 动态代理 4. JDK 动态代理和 CGLIB 动态代理对比 5. Spring代理选择 6. Spring AOP 实现原理 6.1 织入 7. JDK 动态代理实现 8. CGLIB 动态代理实现 9. 总结 1. 代理模式 代理模式&#xf…

<Git/Gerrit>版本控制Git以及代码评审Gerrit常见的开发操作

下载安装,环境变量配置直接百度; 1.代码拉取: 操作步骤:在正确配置完git的条件下:在本地文件夹下:右键–Git Bash -Here: 出现如下弹窗: 在黑窗口输入:代码拉取路径(一般都是把命令和路径在外面写好,直接粘贴(在窗口右键,Paste,回车)) 代码…

linux系统磁盘性能监视工具iostat

目录 一、iostat介绍 二、命令格式 三、命令参数 四、参考命令:iostat -c -x -k -d 1 (一)输出CPU 属性值 (二)CPU参数分析 (三)磁盘每一列的含义 (四)磁盘参数分…

AI生成式视频技术来临:Runway Gen-2文本生成视频

Runway Gen-2的官方网站提供了一种文本生成视频的工具。以下是对该工具的介绍: 文本生成视频:Runway Gen-2是一个创新的在线工具,可以将文本转化为视频。用户只需输入文本描述或句子,Runway Gen-2就能自动生成相应的视频内容。这…

uni-ajax网络请求库使用

uni-ajax网络请求库使用 uni-ajax是什么 uni-ajax是基于 Promise 的轻量级 uni-app 网络请求库,具有开箱即用、轻量高效、灵活开发 特点。 下面是安装和使用教程 安装该请求库到项目中 npm install uni-ajax编辑工具类request.js // ajax.js// 引入 uni-ajax 模块 import ajax…

【最短路算法】SPFA

引入 在计算机科学的世界里,算法就像是星空中的繁星,各自闪烁着智慧的光芒。它们沉默而坚定,像是一群不语的哲人,默默地解答着世界的问题。 算法的步骤,如同优美的诗行,让复杂的问题在流转的字符中得以释…

PHP8的常量-PHP8知识详解

常量和变量是构成PHP程序的基础,在PHP8中常量的这一节中,主要讲到了定义常量和预定义常量两大知识点。 一、定义常量 定义常量也叫声明常量。在PHP8中,常量就是一个标识符(名字),一旦定义(声明&…

ansible-playbook编写 lnmp 剧本

ansible-playbook编写 lnmp 剧本 vim /opt/lnmp/lnmp.yaml执行剧本 ansible-playbook lnmp.yaml

WebDAV之π-Disk派盘 + DEVONthink

DEVONthink是由一家来自德国的老牌软件开发商发布的「知识管理」软件,运行于 Mac/iOS 平台。官方自己定位为全方位(中文环境下略有遗憾)帮助你实现知识管理,可以称之为“模块级”应用了。 DEVONthink还支持各种云服务同步,文件管理您的终极文件管理应用、文件、图片与连接远…

Android Ble蓝牙App(一)扫描

Ble蓝牙App(一)扫描 前言正文一、基本配置二、扫描准备三、扫描页面① 增加UI布局② 点击监听③ 扫描处理④ 广播处理 四、权限处理五、扫描结果① 列表适配器② 扫描结果处理③ 接收结果 六、源码 前言 关于低功耗的蓝牙介绍我已经做过很多了&#xff0…

基于SHARC+®单核的ADSP-21567KBCZ6、ADSP-21566BBCZ4、ADSP-21566KBCZ4高性能DSP处理器产品

ADSP-2156x 处理器的速度高达 1 GHz,属于 SHARC 系列产品。ADSP-2156x 处理器基于 SHARC 单核。ADSP-2156x SHARC 处理器是 SIMD SHARC 系列数字信号处理器 (DSP) 中的一款产品,采用 ADI 的超级哈佛架构。这些 32 位/40 位/64 位浮点处理器已针对高性能音…

Practice3|922. 按奇偶排序数组 II、143. 重排链表

922. 按奇偶排序数组 II 1.题目: 给定一个非负整数数组 nums, nums 中一半整数是 奇数 ,一半整数是 偶数 。 对数组进行排序,以便当 nums[i] 为奇数时,i 也是 奇数 ;当 nums[i] 为偶数时, i…

将临时表的所有数据添加到另一张表的某个字段

临时表 目标表 SmsCatagory smsCatagory new SmsCatagory(); smsCatagory.setGasStationId(); smsCatagory.setType(); ...... sendTaskService.batchInsertByTemp(smsCatagory);xml&#xff1a; <insert id"batchInsertByTemp">INSERT INTO cs_sms_cata…

[每日习题]进制转换 参数解析——牛客习题

hello,大家好&#xff0c;这里是bang___bang_&#xff0c;本篇记录2道牛客习题&#xff0c;进制转换&#xff08;简单&#xff09;&#xff0c;参数解析&#xff08;中等&#xff09;&#xff0c;如有需要&#xff0c;希望能有所帮助&#xff01; 目录 1️⃣进制转换 2️⃣参…

safe敏捷项目管理,safe框架简介

一、SAFe简介 SAFe是ScaledAgile Framework的简称&#xff0c;由DeanLeffingwell创建&#xff0c;SAFe&#xff08;Scaled Agile Framework&#xff09;是全球运用最广泛的大规模敏捷框架。 SAFe融合了精益、敏捷和DevOps&#xff0c;它是一个知识库&#xff0c;囊括了大量已…

【面试】某公司记录一次面试题

文章目录 框架类1. Spring boot与 spring 架相比&#xff0c;好在哪里?2. Spring boot以及 Spring MVC 常用注解(如requestingMapping&#xff0c;responseBody 等)3. 常用的java 设计模式&#xff0c;spring 中用到哪些设计模式4. SpringIOC是什么&#xff0c;如何理解5. AOP…

v-model绑定checkbox无法动态更新视图

在vue2中使用v-model绑定checkbox <input type"checkbox" v-model"isChecked" :valueisChecked change"handleCheckboxChange" />监听change事件&#xff0c;并在change事件中做一些特殊处理&#xff0c;比如用户在登录时有没有阅读过隐私…

C语言文件io操作

一、fopen 在C语言中&#xff0c;操作文件之前应该先打开文件。使用<stdio.h>头文件中的fopen()函数可以打开文件&#xff0c;因为FILE也是结构体&#xff0c;我们通过返回一个文件指针就可以对文件进行操作。在用完fopen之后要记得关闭该文件流。 用法&#xff1a; F…

小目标检测(3)——msgqueue多线程通信和多线程互斥编程

文章目录 引言正文代码的执行和线程使用std::mutex进行编程mutex基本用法std::lock_guard的使用std::unique_lock的使用 condition_variable的使用wait函数的使用condition_variable的整体代码 多线程编程的基本语句 总结引用 引言 在学习老师给的目标检测的代码过程中&#xf…