JVM问题

1. jvm运行时区域划分及每个区域的作用

堆、方法区(元空间)、虚拟机栈、本地方法栈、程序计数器在这里插入图片描述

2. 堆内存分配策略:新生代,老年代,gc时机

• 对象优先分配在Eden区,如果Eden区没有足够的空间进行分配时,虚拟机执行一次MinorGC。而那些无需回收的存活对象,将会进到 Survivor 的 From 区(From 区内存不足时,直接进入 Old 区)。
• 大对象直接进入老年代(需要大量连续内存空间的对象)。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。
• 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄(Age Count)计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,直到达到阀值(默认15次),对象进入老年区。
• (动态对象年龄判定:程序从年龄最小的对象开始累加,如果累加的对象大小,大于幸存区的一半,则将当前的对象 age 作为新的阈值,年龄大于此阈值的对象则直接进入老年代)
• 每次进行Minor GC或者大对象直接进入老年区时,JVM会计算所需空间大小如小于老年区的剩余值大小,则进行一次Full GC。

3. 创建一个对象的步骤

类加载检查 —> 分配内存 —> 初始化零值 —> 设置对象头 —> 执行init方法.
①类加载检查:
虚拟机遇到 new 指令时,首先去检查是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类
是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
②分配内存:
在类加载检查通过后,接下来虚拟机将为新生对象分配内存,分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择
那种分配方式由Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
③初始化零值:
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值,这一步操作保证了对象的实例字段在 Java 代
码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
④设置对象头:
初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是那个类的实例、如何才能找到类的元数据
信息、对象的哈希吗、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态
的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
⑤执行 init 方法:
从虚拟机的视⻆来看,一个新的对象已经产生了,但从Java 程序的视⻆来看, 方法还没有执行,所有的字段都还为
零。所以一般来说(除循环依赖),执行 new 指令之后会接着执行 方法,这样一个真正可用的对象才算产生出来。

4. 对象引用:强引用、软引用、弱引用、虚引用(了解)

5. jvm类加载过程
在这里插入图片描述

①加载阶段
1.通过一个类的全限定名来获取定义此类的二进制字节流。
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3.在Java堆中生成一个代表这个类的java.lang.class对象,作为方法区这些数据的访问入口。
②验证阶段
1.文件格式验证(是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理)
2.元数据验证(对字节码描述的信息进行语意分析,以保证其描述的信息符合Java语言规范要求)
3.字节码验证(保证被校验类的方法在运行时不会做出危害虚拟机安全的行为)
4.符号引用验证(虚拟机将符号引用转化为直接引用时,解析阶段中发生)
③准备阶段
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段。将对象初始化为“零”值
④解析阶段
解析阶段时虚拟机将常量池内的符号引用替换为直接引用的过程。
字符串常量池:堆上,默认class文件的静态常量池
v运行时常量池:在方法区,属于元空间
⑤初始化阶段
初始化阶段时加载过程的最后一步,而这一阶段也是真正意义上开始执行类中定义的Java程序代码。

6. 双亲委派机制

每一个类都有一个对应它的类加载器。系统中的 ClassLoder 在协同工作的时候会默认使用 双亲委派模型 。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。
为什么使用双亲委派机制?:此机制保证JDK核心类的优先加载;使得Java程序的稳定运行,可以避免类的重复加载,也保证了 Java 的核心 API不被篡改。如果不用没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的Object 类。
在这里插入图片描述

7. 破坏双亲委派机制:tomcat的类加载机制(了解)

WebAppClassLoader 加载类的时候,故意打破了JVM 双亲委派机制,绕开了 AppClassLoader,直接先使用 ExtClassLoader 来加载类。
步骤:

  1. 先在本地cache查找该类是否已经加载过,看看 Tomcat 有没有加载过这个类。
  2. 如果Tomcat 没有加载过这个类,则从系统类加载器的cache中查找是否加载过。
  3. 如果没有加载过这个类,尝试用ExtClassLoader类加载器类加载,重点来了,这里并没有首先使用 AppClassLoader 来加载类。这个Tomcat 的 WebAPPClassLoader 违背了双亲委派机制,直接使用了 ExtClassLoader来加载类。这里注意 ExtClassLoader 双亲委派依然有效,ExtClassLoader 就会使用 Bootstrap ClassLoader来对类进行加载,保证了 Jre 里面的核心类不会被重复加载。 比如在 Web 中加载一个 Object 类。WebAppClassLoader → ExtClassLoader → Bootstrap ClassLoader,这个加载链,就保证了 Object 不会被重复加
    载。
  4. 如果BoostrapClassLoader,没有加载成功,就会调用自己的findClass方法由自己来对类进行加载,findClass
    加载类的地址是自己本 web 应用下的 class。
  5. 加载依然失败,才使用 AppClassLoader 继续加载。
  6. 都没有加载成功的话,抛出异常。

8. Jvm垃圾回收:存活算法

引用计数法
给对象添加一个引用计数器,每当由一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
优点:实现简单,判定效率也很高
缺点:他很难解决对象之间相互循环引用的问题,基本上被抛弃
可达性分析法
通过一系列的成为“GC Roots”(活动线程相关的各种引用,虚拟机栈帧引用,静态变量引用,JNI引用)的对象作为起始点,从这些节点ReferenceChains开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC ROOTS没有任何引用链相连时,则证明此对象时不可用的;
两次标记过程
对象被回收之前,该对象的finalize()方法会被调用;两次标记,即第一次标记不在“关系网”中的对象。第二次的话
就要先判断该对象有没有实现finalize()方法了,如果没有实现就直接判断该对象可回收;如果实现了就会先放在一个

9. Jvm垃圾回收:回收算法
垃圾回收算法:复制算法、标记清除、标记整理、分代收集

复制算法:(young)
将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收;
优点:实现简单,内存效率高,不易产生碎片
缺点:内存压缩了一半,倘若存活对象多,Copying 算法的效率会大大降低
标记清除:(cms)
标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象
缺点:效率低,标记清除后会产生大量不连续的碎片,需要预留空间给分配阶段的浮动垃圾
标记整理:(old)
标记过程仍然与“标记-清除”算法一样,再让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存;解
决了产生大量不连续碎片问题
分代收集
根据各个年代的特点选择合适的垃圾收集算法。
新生代采用复制算法,新生代每次垃圾回收都要回收大部分对象,存活对象较少,即要复制的操作比较少,一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。
老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

10 Jvm垃圾回收:垃圾收集器

Serial
Serial 是一个单线程的收集器,它不但只会使用一个 CPU 或一条线程去完成垃圾收集工作,并且在进行垃圾收集
的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。适合用于客户端垃圾收集器。
Parnew
ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法,除了使用多线程进行垃圾收集之外,其余
的行为和 Serial 收集器完全一样,ParNew 垃圾收集器在垃圾收集过程中同样也要暂停所有其他的工作线程。
JDK5:parallel Scavenge+(Serial old/parallel old)关注吞吐量
parallel Scavenge:(关注吞吐量)
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验);高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。
Serial old
Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。主要有两个用途:在 JDK1.5 之前版本中与新生代的 Parallel Scavenge 收集器搭配使用。
作为年老代中使用 CMS 收集器的后备垃圾收集方案。
parallel old
Parallel Scavenge收集器的老年代版本。使用多线程和“标记-整理”算法。
JDK8-CMS:(关注最短垃圾回收停顿时间)
CMS收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。
CMS 工作机制相比其他的垃圾收集器来说更复杂,整个过程分为以下 4 个阶段:
初始标记:只是标记一下 GC Roots 能直接关联的对象,速度很快,STW。
并发标记:进行 ReferenceChains跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
重新标记:为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,STW。
并发清除:清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作,所以总体上来看CMS收集器的内存回收和用户线程是一起并发地执行。
优点:并发收集、低停顿
缺点:对CPU资源敏感;无法处理浮动垃圾;使用“标记清除”算法,会导致大量空间碎片产生。
JDK9-G1:(精准控制停顿时间,避免垃圾碎片
是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器.以极高概率满足GC停顿时间要求的
同时,还具备高吞吐量性能特征;相比与 CMS 收集器,G1 收集器两个最突出的改进是:
【1】基于标记-整理算法,不产生内存碎片。
【2】可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。
G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收集效率。
初始标记:Stop The World,仅使用一条初始标记线程对GC Roots关联的对象进行标记
并发标记:使用一条标记线程与用户线程并发执行。此过程进行可达性分析,速度很慢
最终标记:Stop The World,使用多条标记线程并发执行
筛选回收:回收废弃对象,此时也要 Stop The World,并使用多条筛选回收线程并发执行
JDK11-ZGC:(在不关注容量的情况获取最小停顿时间5TB/10ms)着色笔技术:加快标记过程
读屏障:解决GC和应用之间并发导致的STW问题
• 支持 TB 级堆内存(最大 4T, JDK13 最大16TB)
• 最大 GC 停顿 10ms
• 对吞吐量影响最大,不超过 15%

9. jvm性能调优:一些常见问题、常用工具、命令

常用命令:jps、jinfo、jstat、jstack、jmap
jps:查看java进程及相关信息
jinfo:查看JVM参数
jstat:查看JVM运行时的状态信息,包括内存状态、垃圾回收
jstack:查看JVM线程快照,jstack命令可以定位线程出现长时间卡顿的原因,例如死锁,死循环
jmap:可以用来查看内存信息 (配合jhat使用)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三种方式创建对象的几种方式及new实例化时做了什么?

创建对象的几种方式 利用对象字面量创建对象 const obj {}2.利用 new Object创建对象 const obj new Object()3.使用 构造函数实例化对象 function Fn(name) {this.name name} const obj new Fn(张三) console.log(obj.name); //张三为什么要用构造函数的形式&#xff1…

STM32--综述

文章目录 前言STM32简介STM32F103C8T6系统结构Keil软件安装注意事项新建工程操作流程 前言 本专栏将学习B站江协科技的STM32入门教程,通过自身理解和对老师的总结所写的博客专栏。 STM32简介 STM32是意法半导体(STMicroelectronics)公司推…

实施高级存储功能

实施高级存储功能 使用Stratis管理分层存储 Stratis 适用于Linux的本地存储管理解决方案。旨在提供更便利的方式执行存储的初始配置,对存储配置进行修改,并使用高级存储功能。 Stratis以管理物理存储设备池的服务形式运行,并透明地为新创…

Popconfirm气泡确认框(antd-design组件库)简单使用

1.Popconfirm气泡确认框 点击元素,弹出气泡式的确认框。 2.何时使用 目标元素的操作需要用户进一步的确认时,在目标元素附近弹出浮层提示,询问用户。 和 confirm 弹出的全屏居中模态对话框相比,交互形式更轻量。 组件代码来自&…

kubernetes 集群搭建(二进制方式)

使用二进制方式搭建Kubernetes集群,可以更加灵活、自由地定制和配置Kubernetes。同时,它还可以实现更高的性能和更小的资源占用。 对于我这个初学者来说: 更加直观地看到Kubernetes的各个组件,了解它们之间的关系和作用。在搭建…

火车头标题伪原创【php源码】

大家好,给大家分享一下python怎么读取文件中的数据,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 火车头采集ai伪原创插件截图: python是一门非常火爆且相对易学的编程语言,应用在各种场景。许多人想学…

GO学习之 网络通信(Net/Http)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、 文章目录 GO系列前言一、H…

微信小程序tab加列表demo

一、效果 代码复制即可使用,记得把图标替换成个人工程项目图片。 微信小程序开发经常会遇到各种各样的页面组合,本demo为list列表与tab组合,代码如下: 二、json代码 {"usingComponents": {},"navigationStyle&q…

在java中操作redis_Data

1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.配置Redis数据源 redis:host: ${sky.redis.host}port: ${sky.redis.port}password: ${sk…

基于Windows手动编译openssl和直接安装openssl

零、环境 win10-64位 VS2019 一、手动编译 前言&#xff1a;对于一般的开发人员而言&#xff0c;在 openssl 上下载已经编译好的 openssl 库&#xff0c;然后直接拿去用即可&#xff0c;&#xff0c;不用手动编译&#xff0c;{见下文直接安装}。。。对于一些开发人员&#…

【C#学习笔记】装箱和拆箱

文章目录 装箱和拆箱性能消耗装箱拆箱 比较var&#xff0c;object&#xff0c;dynamic&#xff0c;\<T\>varobject\<T\> 泛型dynamic 装箱和拆箱 在讲引用类型object的时候&#xff0c;我们说它是万能的&#xff0c;却没说它万能在哪里。 除了object为每一种变量…

Huggingface使用

文章目录 前置安装Huggingface介绍NLP模块分类transformer流程模块使用详细讲解tokennizermodeldatasetsTrainer Huggingface使用网页直接体验API调用本地调用(pipline)本地调用&#xff08;非pipline&#xff09; 前置安装 anaconda安装 使用conda创建一个新环境并安装pytorc…

针对高可靠性和高性能优化的1200V碳化硅沟道MOSFET

目录 标题&#xff1a;1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance摘要信息解释研究了什么文章创新点文章的研究方法文章的结论 标题&#xff1a;1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance 摘要 本文详…

fishing之第二篇Gophish钓鱼平台搭建

文章目录 一、Gophish介绍二、Gophish部署三、Gophish配置0x01 功能介绍0x02 Sending Profiles(钓鱼邮箱发送配置)0x03 Email Templates(钓鱼邮件模板)0x04 Landing Pages(伪造钓鱼页面)0x05 Users & Groups(用户和组)0x06 Campaigns(钓鱼测试)0x07 Dashboard(仪…

ESP32-C2开发板 ESP8684芯片 兼容ESP32-C3开发

C2是一个芯片采用4毫米x 4毫米封装&#xff0c;与272 kB内存。它运行框架&#xff0c;例如ESP-Jumpstart和ESP造雨者&#xff0c;同时它也运行ESP-IDF。ESP-IDF是Espressif面向嵌入式物联网设备的开源实时操作系统&#xff0c;受到了全球用户的信赖。它由支持Espressif以及所有…

Markdown系列之Flowchat流程图

一.欢迎来到我的酒馆 介绍Markdown的Flowchart流程图语法。 目录 一.欢迎来到我的酒馆二.什么是Flowchart三.更进一步 二.什么是Flowchart 2.1 Flowchart是一款基于javascript的工具&#xff0c;使用它可以用代码创建简单的流程图。具体信息可以查看flowchart官网&#xff1a;…

百度秋招攻略,百度网申笔试面试详解

百度秋招简介 作为行业巨头&#xff0c;百度向社会提供的岗位一直都是非常吃香的&#xff0c;每年也都有很多考生密切关注&#xff0c;百度发布的招聘广告&#xff0c;以尽可能的让自己进入这家企业工作&#xff0c;实现自己的人生价值。那么百度每年的秋招时间是多久&#xf…

【JavaSE】面向对象编程思想之多态(图文详解)

目录 1. 多态的概念 2. 多态实现条件 3. 重写 4. 向上转型和向下转型 4.1 向上转型 4.2 向下转型 5. 多态的优缺点 6. 避免在构造方法中调用重写的方法 1. 多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&a…

Linux学习笔记

Linux学习笔记 目录 一&#xff0e; 操作系统的发展历史与linux二&#xff0e; 安装VMWare三&#xff0e; 安装和配置CentOS 7四&#xff0e; Linux操作系统目录结构五&#xff0e; Linux命令 一&#xff0e; 操作系统的发展历史与linux 概述   操作系统产生与发展经历了人工…

VS2022程序集说明汉化

下载本地化的 .NET IntelliSense 文件 https://dotnet.microsoft.com/zh-cn/download/intellisense 目前本地化的 IntelliSense 文件不再可用。 可用的最新版本是 .NET 5。 建议使用英语 IntelliSense 文件。 .NET6的汉化需要自己动手&#xff1a; 教程可以参照下方&#xff1a…