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】进入官方交流群 近年,电商行业进入了一个新的发展阶段,一方面电商市场规模持续扩大,另一方面直播电商、即时零售、社区团购等新兴电商业态在疫情…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
