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.mzph.cn/news/21064.shtml

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

相关文章

【Linux命令200例】which用于查找指定命令所在路径

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜…

文件的写入 和 读取

文件的写入 需要包含的头文件 #include <unistd.h> 相关的API函数 ssize_t write(int fd, const void *buf, size_t count); 参数说明 int fd &#xff1a;文件描述符const void *buf &#xff1a;一个无类型的指针buf&#xff0c;是一个缓冲区size_t count&#xf…

22.Netty源码之解码器

highlight: arduino-light 抽象解码类 https://mp.weixin.qq.com/s/526p5f9fgtZu7yYq5j7LiQ 解码器 Netty 常用解码器类型&#xff1a; ByteToMessageDecoder/ReplayingDecoder 将字节流解码为消息对象&#xff1b;MessageToMessageDecoder 将一种消息类型解码为另外一种消息类…

Pytorch深度学习-----神经网络之Sequential的详细使用及实战详解

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…

数据结构——单链表OJ题(第二弹)

单链表OJ题 前言一、返回链表开始入环的第一个节点思路一思路二 二、返回链表的深度拷贝总结 前言 此次练习题有两道&#xff01; 有点小难度&#xff0c;但相信难不住大家的&#xff01; 我也会给出两道OJ题的链接&#xff0c;大家也赶快去试一试吧 一、返回链表开始入环的第…

【网络基础进阶之路】基于MGRE多点协议的实战详解

PS&#xff1a;本要求基于华为的eNSP模拟软件进行 具体要求&#xff1a; 完成步骤&#xff1a; 1、根据上述要求&#xff0c;对各路由器进行地址安排&#xff0c;如下图。 2、进入各路由器&#xff0c;对每个端口进行地址设置。 R1路由器设置&#xff1a; ISP路由器设置&…

淘宝资源采集(从零开始学习淘宝数据爬取)

1. 为什么要进行淘宝数据爬取&#xff1f; 淘宝数据爬取是指通过自动化程序从淘宝网站上获取数据的过程。这些数据可以包括商品信息、销售数据、评论等等。淘宝数据爬取可以帮助您了解市场趋势、优化您的产品选择以及提高销售额。 淘宝作为全球的电商平台&#xff0c;每天都有…

flutter:占位视图(骨架屏、shimmer)

前言 有时候打开美团&#xff0c;在刚加载数据时会显示一个占位视图&#xff0c;如下&#xff1a; 那么这个是如何实现的呢&#xff1f;我们可以使用shimmer来开发该功能 实现 官方文档 https://pub-web.flutter-io.cn/packages/shimmer 安装 flutter pub add shimmer示例…

2023年08月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年08月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

使用Vscode编辑keil工程

一、需要安装的插件 1. Keil Assistant 2. C/C 3. 中文配置&#xff1a; 二、插件配置 1. Keil Assistant 添加Keil的安装路径 接下来就可以使用vscode编辑Keil的工程了&#xff0c;调试编译和下载程序需要返回到Keil中进行操作。 三、Vscode常用快捷键 可以自定义进行配置…

【雷达通信】非相干多视处理(CSA)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

echarts绘制关系图

效果图&#xff1a; 代码&#xff1a; <template><div id"serveGraph" style"height: 100%; width: 100%; z-index: 88;"></div> </template> <script> import { defineComponent,reactive,toRefs,onMounted,watch } from …

MFC、Qt、WPF?该用哪个?

MFC、Qt和WPF都是流行的框架和工具&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序。选择哪个框架取决于你的具体需求和偏好。MFC&#xff08;Microsoft Foundation Class&#xff09;是微软提供的框架&#xff0c;使用C编写&#xff0c;主要用于Windows…

Vue2:基础入门

Vue2&#xff1a;基础入门1 Date: April 10, 2023 Sum: vue简介、vue的基本使用、vue的指令、修饰符、过滤器&#xff08;废&#xff09;、小黑的书架、记事本 Tags: * 目标&#xff1a; 能够知道 vue 的基本使用步骤 掌握插值表达式和 v-bind 指令的用法 能够掌握如何使用…

右值引用带来的效率提升(C++11)

文章目录 一.左值引用和右值引用二.C11区分左值和右值的语法设计意义--对象的移动构造和移动赋值场景分析1:C11之前C11之后 场景分析2:函数std::move右值引用的广泛使用 三.引用折叠 一.左值引用和右值引用 左值:可以取到地址的对象(可以出现在赋值符号的左边),对左值的引用称…

【Linux】计算机网络的背景和协议分层

文章目录 网络发展协议何为协议网络协议协议分层OSI七层模型TCP/IP五层模型&#xff08;四层&#xff09; 基本通信流程mac地址和ip地址网络通信本质 网络发展 从一开始计算机作为一台台单机使用&#xff0c;到现在网络飞速发展&#xff0c;从局域网Lan建立起局域网&#xff0…

go逆向符号恢复

前言 之前一直没怎么重视&#xff0c;结果发现每次遇到go的题都是一筹莫展&#xff0c;刷几道题练习一下吧 准备 go语言写的程序一般都被strip去掉符号了&#xff0c;而且ida没有相关的签名文件&#xff0c;没办法完成函数名的识别与字符串的定位&#xff0c;所以第一步通常…

时序数据异常检测算法

引言 异常检测的场景很多&#xff0c;例如&#xff1a;硬件的故障检测、流量的异常点的检测等场景。针对时间序列类数据的异常检测算法也有很多&#xff0c;业界比较流行的比如普通的统计学习方法–3σ原则和箱线图识别数据离群点&#xff0c;它利用检测点偏移量来检测出异常。…

【八】mybatis 日志模块设计

mybatis 日志模块设计 简介&#xff1a;闲来无事阅读一下mybatis的日志模块设计&#xff0c;学习一下优秀开源框架的设计思路&#xff0c;提升自己的编码能力 模块设计 在Mybatis内部定义了4个级别&#xff1a;Error:错误 、warn:警告、debug:调试、trance&#xff0c;日志优…

HDFS架构刨析

HDFS架构刨析 概述HDFS架构图整体概述主角色&#xff1a;namenodefsimage内存元数据镜像文件edits log&#xff08;Journal&#xff09;编辑日志 从角色&#xff1a;datanode主角色辅助角色&#xff1a;secondarynamenode 重要特性主从架构分块存储机制副本机制namespace元数据…