当前位置: 首页 > news >正文

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. 尽量避免长时间等待外部资源(数据库、网络、设备资源等),缩小对象的生命周期,避免进入老年代,如果不能及时返回结果可以适当采用异步处理的方式等

相关文章:

JVM总结笔记

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

C++ 缓存再排序,解决多线程处理后的乱序问题,不知道思路对不对[挠下巴]

C 缓存再排序&#xff0c;解决多线程处理后的乱序问题&#xff0c;不知道思路对不对[挠下巴] 使用map默认会根据key排序的原理作缓存&#xff0c;队列满了依次推出&#xff0c;抛弃掉过时的数据 #include <functional> #include <iostream> #include <map> #…...

华为数通HCIA-地址分类及子网划分

ip地址&#xff08;逻辑地址&#xff09; 作用&#xff1a;唯一标识一张网卡 特点&#xff1a;设备天生没有&#xff0c;需要人为配置&#xff0c;可以随时修改 格式&#xff1a;点分十进制 大小&#xff1a;32bit 组成&#xff1a;网络位主机位 网络位&#xff1a;用于标…...

Linux第七章之gdb与makefile使用

一、Linux调试器-gdb使用 1.1背景 程序的发布方式有两种&#xff0c;debug模式和release模式Linux gcc/g出来的二进制程序&#xff0c;默认是release模式要使用gdb调试&#xff0c;必须在源代码生成二进制程序的时候, 加上-g 选项&#xff3b;重要&#xff3d; 1.2开始使用 …...

Mycat-Balance使用指南

MyCAT Balance是一个Java NIO的高性能负载均衡器&#xff0c;可以替代普通的硬件的交换机或其LVS类似的复杂机制&#xff0c;实现MyCAT集群的负载均衡。 MyCAT Balance的配置文件在conf目录下&#xff0c;frontend-conf.为前端配置&#xff0c;包括绑定的端口等&#xff0c;js…...

玩转顺序表——【数据结构】

在C语言学习中&#xff0c;我们经常会遇见增删查改等一系列操作&#xff0c;而这些操作全都与线性表关联&#xff0c;没有线性表将会对这些操作完成的十分艰难&#xff01;那今天就让我们来了解一下顺序表如何增删查改&#xff01;&#xff01;&#xff01; 目录 1.线性表 2…...

SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)通信区别

SSE&#xff08;Server-Sent Events&#xff0c;服务器推送事件&#xff09;和sockets&#xff08;套接字&#xff09;都是用于实现实时通信的技术&#xff0c;但它们具有不同的特点和应用场景。 SSE 的优点&#xff1a; 简单易用&#xff1a;SSE 是基于HTTP协议的一种实时通…...

【设计模式——学习笔记】23种设计模式——代理模式Proxy(原理讲解+应用场景介绍+案例介绍+Java代码实现)

介绍 基础介绍 代理模式为一个对象提供一个代理对象&#xff0c;以控制对这个对象的访问。即通过代理对象访问目标对象&#xff0c;这样做的好处是&#xff1a;可以在不修改目标对象代码的基础上&#xff0c;增强额外的功能操作&#xff0c;即扩展目标对象的功能被代理的对象…...

大学英语四新视野 课后习题+答案翻译 Unit1~Unit8

Unit 1 Text A: Words in use 2022年6月16日 20:57 1 As the gender barriers crumbled, the number of women working as lawyers, doctors, or bankers began to increase significantly from the mid-20th century. 随着性别障碍的消除&#xff0c;从20世纪中期开始&am…...

Java入门指南:Java语言优势及其特点

目录 1. Java语言简介及发展概述 2. Java语言的优势 2.1 可移植性 2.2 面向对象 2.3 安全性 2.4 大量类库 3. Java语言与C/C的区别 4. 初识Java程序入口之main方法 5. 注释、标识符、关键字 5.1 注释 5.2 标识符 5.3 关键字 1. Java语言简介及发展概述 Java是一种面…...

Jenkins 节点该如何管理?

Jenkins 拥有分布式构建(在 Jenkins 的配置中叫做节点)&#xff0c;分布式构建能够让同一套代码在不同的环境(如&#xff1a;Windows 和 Linux 系统)中编译、测试等 Jenkins 的任务可以分布在不同的节点上运行 节点上需要配置 Java 运行时环境&#xff0c;JDK 版本大于 1.5 节…...

hugging face下载数据集

开始直接执行这个&#xff0c;下载下来的图片打不开 git clone https://huggingface.co/datasets/diffusers/dog-example 解决办法&#xff1a; 安装git lfs 1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash 2. sudo apt…...

解决Django报错 : No module named ‘MySQLdb‘

Django的版本是2.0&#xff0c;Python的版本号是3.6.4 在models.py创建好了模型类之后使用命令&#xff1a;python manage.py makemigrations 进行迁移&#xff0c;但是突然报错&#xff1a;ImportError:No module named MySQLdb 查询了相关资料发现python2.x版本是支持mysql…...

【Docker】Docker的优势、与虚拟机技术的区别、三个重要概念和架构及工作原理详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 作者简介&#xff1a; 辭七七&#xf…...

【论文笔记】RCM-Fusion: Radar-Camera Multi-Level Fusion for 3D Object Detection

原文链接&#xff1a;https://arxiv.org/abs/2307.10249 1. 引言 目前的一些雷达-相机融合3D目标检测方法进行实例级的融合&#xff0c;从相机图像生成3D提案&#xff0c;并与雷达点云相关联以修正提案。但这种方法没有在最初阶段使用雷达&#xff0c;依赖于相机3D检测器&…...

STM32-风速传感器(ADC)

目录 0 说明 1 传感器介绍 2 代码说明 2.1 ADC.c 2.2 adc.h 2.3 main.c 0 说明 本篇文章主要是说明怎么使用STM32单片机读取风速传感器采集到的数据&#xff0c;读取方式是ADC&#xff0c;并且附带着STM32所需要的全部代码&#xff0c;所使用的风速传感器如下图所示。 附&am…...

【conda】配置国内镜像源

【conda】配置国内镜像源 1、官方2、国内常用镜像3、配置查看当前conda配置设置搜索是显示通道地址 4、清除缓存5、恢复默认全部删除指定删除 1、官方 https://docs.conda.io/projects/conda/en/latest/configuration.html 2、国内常用镜像 https://developer.aliyun.com/mi…...

python森林生物量(蓄积量)数据处理到随机森林估算全流程

python森林生物量&#xff08;蓄积量&#xff09;估算全流程 一.哨兵2号获取/处理/提取数据1.1 影像处理与下载采用云概率影像去云采用6S模型对1C级产品进行大气校正geemap下载数据到本地NDVI 1.2 各种参数计算&#xff08;生物物理变量、植被指数等&#xff09;LAI&#xff1a…...

使用Freemarker模版导出xls文件使用excel打开提示文件损坏

本文是通过一步步的还原事件的发生并解决的一个过程记录&#xff0c;如果想知道如何解决的可以直接跳转文章末尾结论部分 提示一下&#xff0c;关注一下 Table 标签中的 ss:ExpandedRowCount 属性 解决的问题 在项目中使用freemarker的xml模板导出xls格式的Excel文件时&#xf…...

初识Linux

今天简单了解了关于操作系统的发展史&#xff0c;学习了在Linux中如何远程连接云服务器的指令&#xff0c;以及在Linux中创建多个用户的指令。 1. ssh root 服务器远程地址 作用是用来连接XShell与云服务器&#xff0c;输入该指令后会自动生成输入密码的窗口&#xff0c;如…...

python——案例六:清空列表用clear()方法实现

案例六&#xff1a;清空列表用clear()方法实现LIST[0,1,2,3,4,5] print(清空前&#xff1a;,LIST) LIST.clear() print(清空后&#xff1a;,LIST)...

测试|Selenium之WebDriver常见API使用

测试|Selenium之WebDriver常见API使用 文章目录 测试|Selenium之WebDriver常见API使用1.定位对象&#xff08;findElement&#xff09;css定位xpath定位css选择器语法&#xff1a;xpath语法:校验结果 2.操作对象鼠标点击对象在对象上模拟按键输入clear清除对象输入的文本内容su…...

手把手教你uniapp和小程序分包

分包目的在于提高小程序的体积&#xff0c;多一个包就多2M&#xff0c;最多20M 常规的分包&#xff1a; 小程序一打开首先加载主包&#xff0c;然后再加载分包 分包可以用主包内的资源&#xff0c;主包不可以使用分包的资源 分包A不可以使用分包B里面的内容 分包可以使用a…...

Java中的代理模式

Java中的代理模式 1. 静态代理2. JDK动态代理3. CGLib动态代理 1. 静态代理 接口 public interface ICeo {void meeting(String name) throws InterruptedException; }目标类 public class Ceo implements ICeo{public void meeting(String name) throws InterruptedExcepti…...

LeetCode每日一题——1331.数组序号转换

题目传送门 题目描述 给你一个整数数组 arr &#xff0c;请你将数组中的每个元素替换为它们排序后的序号。 序号代表了一个元素有多大。序号编号的规则如下&#xff1a; 序号从 1 开始编号。一个元素越大&#xff0c;那么序号越大。如果两个元素相等&#xff0c;那么它们的…...

2、Tomcat介绍(下)

组件分类 在Apache Tomcat中&#xff0c;有几个顶级组件&#xff0c;它们是Tomcat的核心组件&#xff0c;负责整个服务器的运行和管理。这些顶级组件包括&#xff1a; Server(服务器)&#xff1a;Tomcat的server.xml配置文件中的<Server>元素代表整个Tomcat服务器实例。每…...

JAVA 正则表达式(heima)

JAVA 正则表达式&#xff08;heima&#xff09; public class RegexDemo01 {/** 正则表达式介绍&#xff1a;本质来说就是一个字符串&#xff0c;字符串中可以指定规则&#xff0c;来对其他字符串进行校验。* public boolean matches(String regex):根据传入的正则表达式&#…...

布瑞特单圈绝对值旋转编码器串口数据读取

布瑞特单圈绝对值旋转编码器串口数据读取 数据手册&#xff1a;http://briter.net/col.jsp?id109 (2.1版本RS485说明书通信协议 单圈.pdf) 绝对式编码器为布瑞特BRT38-ROM16384-RT1&#xff0c;采用RS485通信。 该绝对式编码器共有5根线&#xff1a;红、黄、黑、绿、白 由…...

Linux第六章之vim与gcc使用

一、Linux编辑器-vim使用 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff0c;也…...

【Golang】Golang进阶系列教程--为什么说 Go 语言字符串是不可变的?

文章目录 前言推荐阅读 前言 最近有读者留言说&#xff0c;平时在写代码的过程中&#xff0c;是会对字符串进行修改的&#xff0c;但网上都说 Go 语言字符串是不可变的&#xff0c;这是为什么呢&#xff1f; 这个问题本身并不困难&#xff0c;但对于新手来说确实容易产生困惑…...