JVM学习-内存泄漏
内存泄漏的理解和分类

- 可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一上对象是否还被引用,对于这种情况下,由于代码的实现不同就会出现很多内存泄漏问题(让JVM误以为此对象还在引用,无法回收,造成内存泄漏)
内存泄漏(memory leak)
- 严格来说,只有对象不会再被程序用到了,但是GC又不能回收他们的情况,叫内存泄漏
- 对象X引用对象Y,X的生命周期比Y的生命周期长
- 那么当Y生命周期结束的时候,X依然引用着Y,这时候,垃圾回收期是不会回收对象Y的
- 如果对象X还引用着生命周期比较短的A,B,C,对象A对引用着对象a,b,c,这样可能造成大量无用的对象不能被回收,进而占据了内存资源,造成内存泄漏,直到内存溢出
- 申请了内存用完了不释放,如一共有1024M内存,分配了512M的内存一直不回收,那么可用内存只有512M,仿佛泄露了一部分,通俗讲内存泄漏就是【占着茅坑不拉shi】
内存溢出(out of memory)
- 申请内存时,没有足够的内存可以使用
- 通俗一点讲,一个厕所三个坑,有两个站着茅坑不走(内存泄漏),剩下一个坑,厕所一示接待压力大,这时一下来了两个人,坑位(内存)不够了,内存泄漏变成内存溢出了
- 内存泄漏和内存溢出的关系,内存泄漏增多,最终导致内存溢出
泄漏分类
- 经常发生:发生内存泄露的代码会被多次执行,每次执行,泄露一块内存
- 偶然发生:在某些特定情况下才会发生
- 一次性:发生内存泄漏的方法只会执行一次
- 隐式泄漏:一直占着内存不释放,直到执行结束,严格的说这个不算内存泄漏,因为最终释放掉了,但如果执行时间特别长,会导致内存耗尽
Java内存泄漏的8种情况
静态集合类
- 静态集合类,如HashMap、LinkedList等,如果这些容器为静态的,那么它们的生命周期与JVM程序一致,则容器中对象在程序结束这前将不能被释放,从而造成内存泄漏,简单而言,长生命周期的对象持有短生命周期对象的引用,尽管生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。
public class MemoryLeak {static List list = new ArrayList();public void oomTests() {Object obj = new Object(); //局部变量,方法执行完成后不能被回收,因为被list所持有(list是静态变量,生命周期同类)list.add(obj);}
}
单例模式
- 单例模式和静态集合导致内存泄漏的原因类似,因为单例的静态特性,它的生命周期和JVM的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。
内部类持有外部类
- 内部类持有外部类,如果一个外部类的实例对象的方法返回一个内部类的实例对象
- 这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏
各种连接,如数据库连接,网络连接和IO连接等
- 各种连接,如数据库连接,网络连接和IO连接等
- 在对数据库进行操作的过程中,首先要建立与数据库连接,当不再使用时,需要调用close方法来释放与数据库连接,只有连接被关闭后,垃圾回收器才会回收对应的对象
- 否则,在访问数据库的过程中,对Connection,Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏
public static void main(String[] args) {try {Connection conn = null;Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("url","username","password");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("....")} catch(Exception e) { //异常日志} finally {//①关闭结果集 Statement//②关闭声明的对象 ResultSet//③关闭连接 Connection}
}
变量不合适作用域
- 变量不合理的作用域,一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏,另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的定义
public class UsingRandom {private String msg;public void receiveMsg() {msg = readFromNet(); //从网络中接收数据保存到msg中saveDB(); //将msg保存到数据库中}
}
- 上面伪代码,通过readFromNet方法把接收到的消息保存到变量msg中,然后调用saveDB方法把msg内存保存到数据库,此时msg已经没用了,由于msg的生命周期与对象的生命周期相同,此时msg不能回收,因此造成内存泄漏
- 实际msg变量可以放在receiveMsg方法内部 ,当方法用完,那么msg的生命周期就结束了,此时就可以回收了,另一种方法,使用完msg后,将msg=null,此时垃圾回收器也会回收msg内存空间
改变哈希值
- 当一个对象被存储进HashSet集合中后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,即使用在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏
- 这也是String设置成不可变类型的原因,可以放心把String存入HashSet,或把String当成HashMap的key值
- 当我们需要把自定义的类保存到散列表时,需要保证对象的hashCode不可变
public class ChangeHashCode1 {public static void main(String[] args) {HashSet<Point> hs = new HashSet<>();Point cc = new Point();cc.setX(10); //hashCode = 41hs.add(cc);cc.setX(20); //hashCode = 51System.out.println("hs.remove = " + hs.remove(cc)); // falsehs.add(cc);System.out.println("hs.size = " + hs.size()); //2}
}
class Point {int x;public int getX() {return x;}public void setX(int x) {this.x = x;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;return result;}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null) return false;if (getClass() != obj.getClass()) return false;Point other = (Point) obj;if (x != other.x) return false;return true;}
}
//执行结果
hs.remove = false
hs.size = 2
缓存泄漏
- 一旦对象引用放入缓存中,很容易遗忘,比如,之前项目在一次上线的时候,应用启动奇慢直至夯死,因为代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。
- 对于这个问题,可以使用WeakHashMap代表缓存,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值。
public class MapTest {static Map wMap = new WeakHashMap();static Map map = new HashMap();public static void main(String[] args) {init();testWeakHashMap();testHashMap();}public static void init() {String ref1 = new String("object1");String ref2 = new String("object2");String ref3 = new String("object3");String ref4 = new String("object4");wMap.put(ref1,"cacheObject1");wMap.put(ref2,"cacheObject2");map.put(ref3,"cacheObject3");map.put(ref4,"cacheObject4");System.out.println("String引用ref1,ref2,ref3,ref4消失");}public static void testWeakHashMap(){System.out.println("WeakHashMap GC前");for (Object o : wMap.entrySet()) {System.out.println(o);}try {System.gc();TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("WeakHashMap GC后");for (Object o : wMap.entrySet()) {System.out.println(o);}}public static void testHashMap() {System.out.println("HashMap GC前");for (Object o : map.entrySet()) {System.out.println(o);}try {System.gc();TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("HashMap GC后");for (Object o : map.entrySet()) {System.out.println(o);}}
}
//执行结果
String引用ref1,ref2,ref3,ref4消失
WeakHashMap GC前
object2=cacheObject2
object1=cacheObject1
WeakHashMap GC后
HashMap GC前
object4=cacheObject4
object3=cacheObject3
HashMap GC后
object4=cacheObject4
object3=cacheObject3
监听器和回调
- 如果客户端在你实现API注册回调,却没有显示的取消,就会产生积聚,需要确保回调被当作垃圾回收的最佳方法是只保存它的弱引用,保存成WeakHashMap的键
相关文章:
JVM学习-内存泄漏
内存泄漏的理解和分类 可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一上对象是否还被引用,对于这种情况下,由于代码的实现不同就会出现很多内存泄漏问题(让JVM误以为此对象还在引用,无法回收,造成内存泄…...
Go微服务: 分布式之通过本地消息实现最终一致性和最大努力通知方案
通过本地消息实现最终一致性 1 )概述 我们的业务场景是可以允许我们一段时间有不一致的消息的状态的,并没有说必须特别高的这个消息的一致性比如说在TCC这个架构中,如果采用了消息的最终一致性,整体架构设计要轻松好多即便我们库…...
BC C language
题目汇总 No.1 打印有规律的字符(牛牛的字符菱形) 代码展示 #include<stdio.h> int main() {char ch0;scanf("%c",&ch);for(int i0;i<5;i){for(int j0;j<5;j){if((i0||i4)&&j2)printf("%c", ch);else if ((i 1||i3) &&…...
算法训练营第四十九天 | LeetCode 139单词拆分
LeetCode 139 单词拆分 基本还是完全背包的思路,不过用了三重循环,第三重循环是用于判断当前字符串尾部指定长度字符是否和列表中某一字符串相同,是的话可以将当前dp[j]或上当前下标减去该单词长度后的下标值。 代码如下: clas…...
阿里云一键登录号码认证服务
阿里云文档:号码认证SDK_号码认证服务(PNVS)-阿里云帮助中心 对于后端大概流程 前端App会传一个token过来 后端通过下面方法解析 如果解析可以获得号码,说明号码认证成功,如果无法正确解析则认证失败 /*** actoken来换取电话号码* param token app端用户授权actok…...
【UML用户指南】-05-对基本结构建模-类
目录 1、名称(name) 2、属性 (attribute) 3、操作(operation) 4、对属性和操作的组织 4.1、衍型 4.2、职责 (responsibility) 4.3、其他特征 4.4、对简单类型建模 5、结构良…...
【C++ 初阶】引用 () 实际的一些用法、常引用问题 详解!
文章目录 1. 常引用的背景2. 字符 a 与 整形 97 是相同的,但是具体是怎么比较的呢 ? 1. 常引用的背景 注意: 🐧① 权限可以平移、可以缩小,但是权限 不可以放大。 🐧 类型转换中间会产生临时变量 2. 字…...
adb dump当前可见的窗口
1、窗口信息 adb shell dumpsys window windows > w.txt2、dump当前可见的窗口activity windows系统 adb shell dumpsys activity | findStr mFocusmac系统 adb shell dumpsys activity | grep mFocus3、dump当前处于栈顶的activity windows系统 adb shell dumpsys activi…...
Java Web学习笔记27——对话框、表单组件
常见组件对话框: Dialog对话框:在保留当前页面状态下,告知用户并承载相关操作。 dialogTableVisible: false 默认是不可见的。 在按钮属性中设置为true的意思,点击按钮的时候,才会true,对话框才会显示。 …...
使用vue3+ts封装一个Slider滑块组件
创建一个名为 Slider.vue 的文件 <template><div class"slider-container"><inputtype"range":value"value"input"handleInput"change"handleChange"/><div class"slider-value">{{ val…...
关于科技的总结与思考
文章目录 互联网时代有趣的数字数据驱动大数据的两个特性数据保护互联网免费模式的再探讨平台互联网的意义人工智能伦理的思考语言理性人梅特卡夫定律冲浪的神奇之处AR的恐怖之处叙词表、受控词表和大众分类法六度/十九度的解读知识图谱是真正的仿生智能幂次法则和优先连接现代…...
2024年几款优秀的SQL IDE优缺点分析
SQL 工具在数据库管理、查询优化和数据分析中扮演着重要角色。 以下是常见的 SQL 工具及其优缺点。 1. SQLynx 优点: 智能代码补全和建议:采用AI技术提供高级代码补全、智能建议和自动错误检测,大幅提高编写和调试SQL查询的效率。跨平台和…...
vue前端实现页面禁止缩放 前端适配问题处理 前端项目多端适配解决方案
在前端项目中,如果一个系统页面可以缩放可能会导致多种异常情况,这些异常情况涉及到页面布局、元素尺寸、事件触发、响应式设计和用户体验等方面。 1.布局错乱:页面元素在缩放后可能会出现错位、重叠或部分隐藏的情况,导致页面布局混乱,影响用户对页面内容的理解和操作。这…...
反射型xss靶场练习
反射型xss危害小,这里使用的xss靶场是常用的xss靶场:xss-labs。 当我们完成弹窗后就通过该关卡,说该关卡存在xss的一个漏洞并且可以解析js代码。 第一关: 这里没有过滤我们输入的代码:直接将js代码放在js代码中&a…...
vue3 【实战】封装 “心跳“ 组件
需求描述 在控制台每秒打印一个“hello” 代码实现 <script setup> import { onMounted, onBeforeUnmount, ref } from "vue";const timer ref(0);onMounted(() > {function fn() {console.log("hello");timer.value setTimeout(fn, 1000);}tim…...
k8s网络问题以及容器跨宿主机通信原理
【0】资源配置文件 [rootmcwk8s03 mcwtest]# ls mcwdeploy.yaml [rootmcwk8s03 mcwtest]# cat mcwdeploy.yaml apiVersion: apps/v1 kind: Deployment metadata:labels:app: mcwpythonname: mcwtest-deploy spec:replicas: 1selector:matchLabels:app: mcwpythontemplate:met…...
BM25算法以及变种算法简介
深入理解TF-IDF、BM25算法与BM25变种:揭秘信息检索的核心原理与应用 原文链接: https://xie.infoq.cn/article/8b7232877d0d4327a6943e8ac BM25算法以及变种算法简介 Okapi BM25,一般简称 BM25 算法,在 20 世纪 70 年代到 80 年代…...
D455相机RGB与深度图像对齐,缓解相机无效区域的问题
前言 上一次我们介绍了深度相机D455的使用:intel深度相机D455的使用-CSDN博客,我们也看到了相机检测到的无效区域。 在使用Intel深度相机D455时,我们经常会遇到深度图中的无效区域。这些无效区域可能由于黑色物体、光滑表面、透明物体以及视…...
2024 cicsn ezbuf
文章目录 参考protobuf逆向学习复原结构思路exp 参考 https://www.y4ng.cn/posts/pwn/protobuf/#ciscn-2024-ezbuf protobuf 当时压根不知道用了protobuf这个玩意,提取工具也没提取出来,还是做题做太少了,很多关键性的结构都没看出来是pro…...
地面站Mission planner
官方教程; Mission Planner地面站介绍 | Autopilot (gitbook.io) Mission Planner 功能/屏幕 — Mission Planner 文档 (ardupilot.org) 安卓或者windows软件下载地址: 地面站连接及使用 plane (cuav.net) 在完全装机后再进行各干器件的校准,没有组…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...
数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...
