JVM调优(一)
- 什么时候会有内存泄漏,怎么排查?
答:
首先内存泄漏是堆中的一些对象不会再被使用了,但是无法被垃圾收集器回收,如果不进行处理,最终会导致抛出 java.lang.OutOfMemoryError
异常。
内存泄露:
- 不需要使用的对象被其他对象不正确的引用,导致无法回收。
- 对象生命周期过长
内存泄漏的8中情况:
-
大量使用静态集合类(
HashMap、LinkedList
等),静态变量的生命周期和JVM程序一致,在程序结束之前,静态变量不会被释放,导致内存泄漏。(属于生命周期过长) -
单例模式的静态特性,也会导致生命周期过长,如果单例对象持有外部对象的引用,会导致外部对象不会被回收。
-
内部类持有外部类:每个非静态内部类都会持有外部类的隐式引用,假如
a
为非静态内部类,b
为a
的外部类,如果b
包含了大量对象的引用,非常占用内存空间,那么如果我们创建了非静态内部类a
,此时即使b
对象不再被使用了,也无法回收,占用内存空间,导致内存泄漏。解决办法:如果内部类不需要访问外部类的成员信息,可以考虑转换为静态内部类。
-
各种连接(数据库连接、网络连接和IO连接)未及时关闭,导致大量对象无法回收,造成内存泄漏。
-
变量不合理的作用域:一个变量的定义的作用范围大于其适用范围,很有可能造成内存泄露。
-
改变哈希值:
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。
否则,对象修改后的哈希值与最初存入HashSet集合时的哈希值就不同了,这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致HashSet集合中无法单独删除当前对象,造成内存泄漏
为什么改变哈希值之后找不到对象?因为根据存入时的哈希值去寻找放入的位置,而改变哈希值之后,再去查找就按照新的哈希值所对应的位置去查找,肯定找不到。
这也是 String 为什么被设置成了不可变类型,我们可以放心的把 String 存入 HashSet,或者把String当作 HashMap 的 key 值。
public class ChangeHashCodeTest {public static void main(String[] args) {HashSet<Point> set = new HashSet<>();Point cc = new Point();cc.setX(10); // hashCode = 10set.add(cc);cc.setX(20); // hashCode = 20System.out.println("set remove = " + set.remove(cc));set.add(cc);System.out.println("set.size = " + set.size());/*** 输出:* set remove = false* set.size = 2*/} } class Point {int x;public int getX() {return x;}public void setX(int x) {this.x = x;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Point point = (Point) o;return x == point.x;}@Override public int hashCode() {return x;} }
-
缓存泄露:
一旦把对象引用放入到缓存中,他就很容易遗忘。比如:之前项目在一次上线的时候,应用启动奇慢,就是因为代码会加载一个表的数据到缓存中,测试环境只有几百条数据,而生产环境有几百万的数据。
对于这个问题,可以使用WeakHashMap代表缓存,此Map的特点是:当除了自身有key的引用外,此key没有其他引用,那么此map会自动丢弃此值。
-
ThreadLocal
ThreadLocal的实现中,每个Thread维护一个ThreadLocalMap映射表,key是ThreadLocal实例本身,value是真正需要存储的Object。
ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用来引用它,那么系统GC时,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value。
如果当前线程迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
如何解决此问题?
第一,使用ThreadLocal提供的remove方法,可对当前线程中的value值进行移除;
第二,不要使用ThreadLocal.set(null) 的方式清除value,它实际上并没有清除值,而是查找与当前线程关联的Map并将键值对分别设置为当前线程和null。
第三,最好将ThreadLocal视为需要在finally块中关闭的资源,以确保即使在发生异常的情况下也始终关闭该资源。
try {threadLocal.set(System.nanoTime()); } finally {threadLocal.remove(); }
排查内存泄漏:
可以查看泄露对象
到GC Roots
的引用链,找到泄露对象在哪里被引用导致无法被回收
- JVM常见配置
堆设置
-Xms3550m 初始堆大小
-Xmx3550m 最大堆大小
-XX:NewSize=1024 设置年轻代大小
-XX:NewRatio=4 设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=8 设置年轻代中Eden区与一个Survivor区的比值,默认为8
-XX:MaxPermSize=256m 设置持久代大小
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数.并行收集线程数.
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比.公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式.适用于单CPU情况.
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数.并行收集线程数.
- JVM的堆配置过大的副作用有哪些?
答:JVM的堆内存配置过大,可能要面临的问题有:
- 回收大块堆内存而导致的长时间的时间停顿。
- 如果因为程序设计失误,将大对象从磁盘读取到内存中,可能会导致大对象在分配时直接进入老年代,没有在 Minor GC 中被清理掉。这样会导致频繁的发生 Full GC,给用户的体验是程序每个几分钟就停顿十几秒,非常卡顿。
扩展:JVM的堆配置过小的副作用有哪些?
- Minor GC 过于频繁
- 如果出现堆内存溢出
java.lang.OutOfMemoryError Java heap space
,该如何解决?
答:解决思路如下:
- 首先需要拿到
堆转储快照
进行分析,查看导致 OOM 的对象是否有必要存在,并且分析清除是因为哪些对象导致了 OOM - 如果是内存泄漏导致 OOM,可以查看
泄露对象
到GC Roots
的引用链,找到泄露对象在哪里被引用导致无法被回收 - 如果不是内存泄漏,那么说明内存中的对象都是存活的,导致 OOM,这时应该检查虚拟机的堆内存设置是否有向上调整的空间。并且检查是否存在
对象生命周期过长
、存储结构不合理
的情况,减少程序运行中的内存消耗。
扩展说明:因为存储结构不合理导致堆内存溢出(来自于《深入理解Java虚拟机第3版》)
举例:使用 HashMap<Long, Long>
存储大量的数据,会导致浪费大量的空间,因为 HashMap 的空间效率使用太低。
对于一个 HashMap<Long, Long>
来说,有效数据只有 Key、Value 的两个 long 型数据,占 16字节,long 数据被包装为 java.lang.Long 对象后,就分别具有 8 字节的 Mark Word、8字节的 Klass 指针、8字节的 long 型数值。两个 Long 对象组成 Map.Entry 之后,又多了 16 字节的对象头、8字节的 next 字段、4字节的 int 型的 hash 字段、4字节的空白填充(为了对齐)还有 HashMap 中对这个 Entry 的 8 字节的引用,这样实际占用的内存为:(Long(24byte) * 2) + Entry(32byte) + HashMap Ref(8byte)=88byte
,空间效率仅仅为 16byte / 88byte = 18%。
- 写代码时候有没有什么方式尽量减少Full GC的概率?
答:
- 避免一次性加载大量数据加载到内存,比如excel导入导出,jdbc数据库查询
- 避免大对象的代码处理业务链流程过长,比如aop中获取到了对象参数,大对象捕获到了,导致对象生命周期变长了,没及时释放。
- 禁止使用system.gc方法
- 避免在使用threalocal后,未主动调用remove方法,尽量避免大对象的使用,以及频繁的创建和销毁。更要避免全局锁的竞争等。
相关文章:
JVM调优(一)
什么时候会有内存泄漏,怎么排查? 答: 首先内存泄漏是堆中的一些对象不会再被使用了,但是无法被垃圾收集器回收,如果不进行处理,最终会导致抛出 java.lang.OutOfMemoryError 异常。 内存泄露: …...

Parallels Desktop 19中文-- PD19最新安装
Parallels Desktop 19可以让我们在Mac电脑上运行Windows和其他操作系统,而无需重启计算机。这款软件的稳定性较高,能够在Mac上同时运行多个操作系统,如Windows、Linux等,而无需重启电脑。它可以让用户无缝地在不同操作系统之间切换…...
【c++】向webrtc学比较1:AheadOf、IsNewerTimestamp
webrtc源码分析-rtp序列号新旧比较 大神文章分析的非常到位。大神分析:AheadOrAt(a, b)是判断a是否比b新的核心,其原理是这样的:rfc1982规定了序列号递增间隔不能超过取值范围的1/2(这是自己理解的),那么要判断a是否比b新,只要判断b到a的递增是否在1/2即可,递增超过1/2,…...

华为云云耀云服务器L实例评测|企业项目最佳实践之docker部署及应用(七)
华为云云耀云服务器L实例评测|企业项目最佳实践系列: 华为云云耀云服务器L实例评测|企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测|企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测࿵…...

MAC上使用Wireshark常见问题
文章目录 介绍正文启动异常-Permission denied解决方法 过滤协议和地址指定源地址和目的地址调整 time format 介绍 简单记录Wireshark在日常使用过程中的遇到的小case。 正文 Wireshark相较于tcpdump使用较为简单,交互也更为友好。 点击Start即可启动抓包 启动…...
在C++中++a和a++有什么区别?
2023年10月16日,周一中午 a和a在语义上的区别 a是先进行运算(增加1),然后返回新值。 a是先返回原值,然后进行运算(增加1)。 a和a在效率上的区别 a直接返回新值,不需要临时变量保存原值。 而a需要先返回原值,然后再进行增加1的操作。这需要使用一个临时变量来保存…...

NewStarCTF2023公开赛道-压缩包们
题目提示是压缩包 用010editor打开,不见PK头,补上50 4B 03 04 14 00 00 00 将文件改成.zip后缀,打开,解压出flag.zip 尝试解压,报错 发现一串base64编码 SSBsaWtlIHNpeC1kaWdpdCBudW1iZXJzIGJlY2F1c2UgdGhleSBhcmUgd…...
oracle数据库增加表空间数据文件
查询数据文件:select * from dba_data_files order by file_name; 增加:alter tablespace 数据库名 add datafile data size 34359721984;...
【08】基础知识:React中收集表单数据(非受控组件和受控组件)
一、概念 非受控组件: 页面中所有输入类的 DOM,现用现取。 给组件绑定 ref 属性,在需要时通过 ref 获取相应值。 受控组件: 页面中所有输入类的 DOM,随着输入,将内容维护到状态 state中,当…...

数据结构之堆排序和前,中,后,层序遍历,链式二叉树
首先我们要知道升序我们要建小堆,降序建大堆,这与我们的大多人直觉相违背。 因为我们大多数人认为应该将堆顶的数据输出,但如果这样就会导致堆顶出堆以后,堆结构会被破坏,显然我们不能这样。 所有我们反其道而行&…...

多线程中ThreadPoolExecutor.map()中传递多个参数
with concurrent.futures.ThreadPoolExecutor(max_threads) as executor:results executor.map(get_captcha_image, ip_addrs, [img_url] * len(ip_addrs)) #要传入多个参数时,每个参数都得是固定相同长度的可迭代对象# 收集结果for result in results:print(resul…...

linux centos7 环境下 no such file or directory
目录 1.问题描述2.主要原因2.1修改后代码2.2修改前代码 总结参考 1.问题描述 预览excel文件时无法找到对应的html文件 2.主要原因 异常原因:代码获取的是系统的tmp文件,但是linux环境环境中心tmp目录是没有权限的,所以不能获取系统的根目录…...
Nginx 反向代理 SSL 证书绑定域名
配置 Nginx 反向代理和 SSL 泛域名证书绑定域名 Nginx 是一个功能强大的 Web 服务器和反向代理服务器,可以用于将客户端请求转发到后端服务器,并提供安全的 HTTPS 连接。本文将介绍如何配置 Nginx 反向代理,并使用 SSL 泛域名证书绑定域名&a…...
SpringBoot 集成 JMS 与 IBMMQ 代码示例教程
文章目录 前言一、集成 JMS 与 IBMMQ1、pom 依赖2、yml 配置3、Properties 配置类4、Factory 连接工厂类5、配置连接认证6、配置缓存连接工厂7、配置事务管理器8、配置JMS模板9、消息发送与接收 总结 前言 SpringBoot 集成 IBMMQ,实现两个服务间的消息通信。 一、集…...

大模型之Prompt研究和技巧
大模型之Prompt研究和技巧 大模型之Prompt编写简介组成技术Zero-ShotFew-shotCOTCOT-SCTOTGoTReAct 大模型之Prompt编写 简介 Prompt是是给 AI **模型的指令,**一个简短的文本输入,用于引导AI模型生成特定的回答或执行特定任务。 Prompt是你与语言模型沟…...

掌握Golang匿名函数
一个全面的指南,以理解和使用Golang中的匿名函数 Golang以其简单和高效而闻名,赋予开发人员各种编程范式。其中一项增强代码模块化和灵活性的功能就是匿名函数。在这篇正式的博客文章中,我们将踏上探索Golang匿名函数深度的旅程。通过真实世…...
HarmonyOS云开发基础认证---练习题二
【判断题】 2/2 Serverless是云计算下一代的默认计算范式。 正确(True) 【判断题】 2/2 接入认证服务后,用户每次收到验证码短信都需要开发者买单。 错误(False) 【判断题】 2/2 认证服务手机号码登录需要填写国家码。 正确(True) 【判断题】 2/2 在Cloud Functi…...
ffmpeg视频解码器的配置选项含义
lowres的含义 lowres是AVCodecContext结构体中的一个成员变量,用于指定编解码器的降低分辨率级别。 在某些情况下,为了加快编解码的速度或减少计算资源的消耗,可以通过设置lowres参数来降低编解码器的分辨率级别。这将导致编解码器在处理视…...
enter ubuntu boot option in virt-manager
在全屏模型下,启动过程中按下F8或者Ctrl F8。 参考:https://serverfault.com/questions/463024/how-do-i-access-the-f8-bootmenu-while-booting-a-windows-2008r2-kvm-guest-vm...
电商运营该如何做 AB 测试
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 近年,电商行业进入了一个新的发展阶段,一方面电商市场规模持续扩大,另一方面直播电商、即时零售、社区团购等新兴电商业态在疫情…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...