• 我的订阅
  • 科技

如何避免在 Java 中使用双括号初始化

类别:科技 发布时间:2023-07-12 14:00:00 来源:CSDN

【编者按】本文介绍了一个使用了 Java 的双括号初始化语法导致内存泄漏的案例。作者分析了泄漏的原因,提出了几种解决的方法,并给出了代码示例。

链接:https://blog.p-y.wtf/avoid-java-double-brace-initialization

作者 | Pierre-Yves Ricau责编 | 明明如月

责编 | 夏萌

出品 | CSDN(ID:CSDNnews)

如何避免在 Java 中使用双括号初始化

结论先行

避免像这样,在 Java 中使用双括号初始化:newHashMap< String, String> {{ put( "key", value); }};

内存泄漏追踪

我最近正在 LeakCanary看到了以下内存泄漏追踪信息:┬───│ GC Root: Global variable innativecode │├─ com.bugsnag.android.AnrPlugin instance│ Leaking: UNKNOWN│ ↓ AnrPlugin.client│ ~~~~~~├─ com.bugsnag.android.Client instance│ Leaking: UNKNOWN│ ↓ Client.breadcrumbState│ ~~~~~~~~~~~~~~~├─ com.bugsnag.android.BreadcrumbState instance│ Leaking: UNKNOWN│ ↓ BreadcrumbState.store│ ~~~~~├─ com.bugsnag.android.Breadcrumb[] array│ Leaking: UNKNOWN│ ↓ Breadcrumb[ 494] │ ~~~~~├─ com.bugsnag.android.Breadcrumb instance│ Leaking: UNKNOWN│ ↓ Breadcrumb.impl│ ~~~~├─ com.bugsnag.android.BreadcrumbInternal instance│ Leaking: UNKNOWN│ ↓ BreadcrumbInternal.metadata│ ~~~~~~~~├─ com.example.MainActivity$ 1instance │ Leaking: UNKNOWN│ Anonymous subclass of java.util.HashMap│ ↓ MainActivity$ 1. this$ 0│ ~~~~~~╰→ com.example.MainActivity instanceLeaking: YES (Activity#mDestroyed istrue)

当打开一个内存泄漏追踪日志时,我首先会看底部的对象,了解它的生命周期,这将帮助我理解内存泄漏追踪中的其他对象是否应该有相同的生命周期。

在底部,我们看到:╰→ com.example.MainActivityinstanceLeaking: YES( Activity#mDestroyedistrue)

Activity已经被销毁,应该已被垃圾回收器给回收掉了,但它仍驻留在内存中。

此时,我开始在内存泄漏追踪日志中寻找已知类型,并尝试弄清楚它们是否属于同一个被销毁的范围(=> 正在泄漏)或更高的范围(=> 没有泄漏)。

在顶部,我们看到:├─ com.bugsnag.android.Clientinstance│ Leaking: UNKNOWN

我们的 BugSnag客户端是一个用于分析崩溃报告单例,由于每个应用我们创建一个实例,所以它没有泄漏。├─ com.bugsnag.android.Clientinstance│ Leaking: NO

所以我们现在需要转变焦点,特别关注从最后一个 Leaking: NO到第一个 Leaking: YES的部分:…├─ com.bugsnag.android.Client instance│ Leaking: NO│ ↓ Client.breadcrumbState│ ~~~~~~~~~~~~~~~├─ com.bugsnag.android.BreadcrumbState instance│ Leaking: UNKNOWN│ ↓ BreadcrumbState.store│ ~~~~~├─ com.bugsnag.android.Breadcrumb[] array│ Leaking: UNKNOWN│ ↓ Breadcrumb[494]│ ~~~~~├─ com.bugsnag.android.Breadcrumb instance│ Leaking: UNKNOWN│ ↓ Breadcrumb.impl│ ~~~~├─ com.bugsnag.android.BreadcrumbInternal instance│ Leaking: UNKNOWN│ ↓ BreadcrumbInternal.metadata│ ~~~~~~~~├─ com.example.MainActivity $1instance │ Leaking: UNKNOWN│ Anonymous subclass of java.util.HashMap│ ↓ MainActivity $1.this $0│ ~~~~~~╰→ com.example.MainActivity instanceLeaking: YES (Activity #mDestroyed is true)

BugSnag 客户端保持了一个面包屑的环形缓冲区。这些应该保留在内存中,它们也没有泄漏。

所以让我们跳过上述内容,从下面这里继续分析:├─ com.bugsnag.android.BreadcrumbInternalinstance│ Leaking: NO

我们只需要关注从最后一个 Leaking: NO到第一个Leaking: YES的部分:…├─ com.bugsnag.android.BreadcrumbInternal instance│ Leaking: NO│ ↓ BreadcrumbInternal.metadata│ ~~~~~~~~├─ com.example.MainActivity $1instance │ Leaking: UNKNOWN│ Anonymous subclass of java.util.HashMap│ ↓ MainActivity $1.this $0│ ~~~~~~╰→ com.example.MainActivity instanceLeaking: YES (Activity #mDestroyed is true)BreadcrumbInternal.metadata :内存泄漏追踪通过面包屑实现的元数据字段。

也就是说:记录到 BugSnag 的面包屑之一有一个元数据映射,这是一个 HashMap的匿名子类 ,它保留对外部类的引用,这个外部类就是被销毁的 Activity 。

让我们看看我们在 MainActivity中记录面包屑的地方:voidlogSavingTicket( StringticketId) { Map< String, Object> metadata = newHashMap< String, Object> {{ put( "ticketId", ticketId); }};bugsnagClient.leaveBreadcrumb( "Saving Ticket", metadata, LOG); }

这段代码利用了一个被称为“双括号初始化” 的有趣的 Java 代码块 。它允许你创建一个 HashMap,并通过添加代码到HashMap的匿名子类的构造函数中同时初始化它。newHashMap< String, Object> {{ put( "ticketId", ticketId); }};

Java 的匿名类总是隐式地引用其外部类。

因此,这段代码:voidlogSavingTicket( StringticketId) { Map< String, Object> metadata = newHashMap< String, Object> {{ put( "ticketId", ticketId); }};bugsnagClient.leaveBreadcrumb( "Saving Ticket", metadata, LOG); }

实际上被编译为:classMainActivity$1 extendsHashMap< String, Object> { private final MainActivity this$ 1;

MainActivity$ 1(MainActivity this$ 1, StringticketId) { this.this$ 1= this$ 1; put( "ticketId", ticketId); }}

voidlogSavingTicket( StringticketId) { Map< String, Object> metadata = newMainActivity$ 1( this, ticketId); bugsnagClient.leaveBreadcrumb( "Saving Ticket", metadata, LOG); }

结果,这个 breadcrumb 就一直持有对已销毁的 activity 实例的引用。

总结

尽管使用 Java 的双括号初始化看起来很"炫酷",但它会无故地额外创建类,可能会导致内存泄漏。因此避免在 Java 中使用双括号初始化。

你可以用下面这种更安全的方式来解决这个问题:Map< String, Object> metadata = newHashMap<>; metadata.put( "ticketId", ticketId); bugsnagClient.leaveBreadcrumb( "Saving Ticket", metadata, LOG);

或者利用 Collections.singletonMap进一步简化代码:Map< String, Object> metadata = singletonMap( "ticketId", ticketId); bugsnagClient.leaveBreadcrumb( "Saving Ticket", metadata, LOG);

或者,直接将文件转换为 Kotlin。

你是否在使用 Java 时遇到过内存泄漏的问题?

▶短短 5 天,Python 开发的“Twitter 杀手”Threads 用户过亿,增幅猛超 ChatGPT,马斯克暴怒!

▶ 开源商业化,走出“射手假说”迷雾

▶ ChatGPT 点燃向量数据库赛道,刚刚,Zilliz Cloud 云服务重磅发布! 返回搜狐,查看更多

责任编辑:

以上内容为资讯信息快照,由td.fyun.cc爬虫进行采集并收录,本站未对信息做任何修改,信息内容不代表本站立场。

快照生成时间:2023-07-12 15:45:09

本站信息快照查询为非营利公共服务,如有侵权请联系我们进行删除。

信息原文地址:

微软发布 Visual Studio 2022 17.6更新
...程语言的显示效果,帮助开发人员更好地直观地区分左大括号和右大括号集,以便更轻松地找到缺失的大括号。 新版本中引入了用于C#、C++和Markdown文件的拼写检查器
2023-05-18 11:41:00
当毛衣遇上括号裙,轻松彰显不俗品味
“括号裙”是什么呢?其实就是一种形状像括号的裙子,因为上下两侧和中间相比略窄一些,所以看上去很是形似括号。这种“括号裙”最大的优势就是百搭不挑人,还能够修饰身材曲线,使得整个人看
2023-08-30 19:14:00
英文输入法状态下的大括号键,可以快速调节画笔大小
...调节画笔大小,就能操作瘦脸了。英文输入法状态下的大括号键,可以快速调节画笔大小。其中,左大括号键是缩小,右大括号键是放大。大家把画笔移动到人物脸部边缘,按住鼠标左键往里拖动,
2023-01-08 20:23:00
如何绘制「UML类图」?附内容详解和优质实例分析!
...示默认值下划线:static斜体:抽象 (注意也可以用两个尖括号包裹来表示抽象,比如 —— <>)冒号前是方法名/变量名(根据有无括号区分)
2023-10-26 18:02:00
反复流产或胚停,到底该怎么办?
...。这种情况在临床中很常见,也困扰着很多夫妇。01左中括号什么是复发性流产?左中括号我国通常将3次或3次以上在妊娠28周之前的胎儿丢失称为复发性流产。但许多专家认为,连续发生2
2023-11-09 08:47:00
每天扔掉一半也不降价,中国面包店为何成了奢侈品?为何不打折?
...度。面包店可以尝试将未售出的面包用于开发新产品,如面包屑、面包干等。这样不仅能减少浪费,还能增加产品种类,满足消费者的多样化需求。通过优化生产和库存管理,更精确地预测市场需求
2024-05-27 11:53:00
梦想当“燃” | 浪潮KaiwuDB研发团队:因为高能,让不可能,成为可能
...下这支“高能团队”以志为马,逐梦前行的故事。01左中括号敢想,就有可能左中括号2019年,KaiwuDB初创团队敏锐地捕捉到了软件服务市场的新趋势。随着数字经济纳入国家战略,
2023-08-24 11:18:00
面包屑导航什么时候不能用?
本篇文章将详细介绍面包屑导航的应用场景及其在B端设计的应用,能给产品设计的伙伴们提供一些参考思路,希望能对你有所启发。在我们的日常互联网使用过程中,面包屑导航无处不在。从电商网站
2023-07-09 18:00:00
小米YU7 Max实车上路!车漆质感细腻、全新括号转向灯亮了
...车车漆质感细腻,转向灯采用全新样式,面积较小,呈现括号形状,位于贯穿式尾灯的两端。对于这一设计,有网友认为,“括号”转向灯的设计与整车外观并不是太协调,还有改进空间。相比之下
2025-01-25 16:05:00
更多关于科技的资讯:
82岁老人换了新手机,但不熟悉操作,结果误开通多项收费业务。3月11日,老人收到扣费短信后向网格员求助,顺利取消了扣费服务
2026-03-11 17:36:00
中新经纬3月11日电 (董湘依)近年来,中国文化“新三样”(网文、网剧、网游)在海外迅速走红。全国两会期间,全国政协委员
2026-03-11 19:27:00
中新经纬3月11日电 题:“养龙虾”火出圈 ,算力变成稀缺资源作者 薛洪言 星图金融研究院常务副院长、苏商银行特约研究员2026年的早春
2026-03-11 19:28:00
河北新闻网讯(闫丽颖、唐福刚)近日,开滦股份范各庄矿聚焦“物理隔离+智能管控”核心需求,创新应用一套具备智能闭锁、声光报警
2026-03-11 19:51:00
中国联通eSIM尝鲜季再添新力
3月11日上午,中国联通eSIM尝鲜季——三星国内首款eSIM手机Galaxy S26系列首销仪式在西单北营业厅隆重举行
2026-03-11 14:14:00
大皖新闻讯 家里空调、冰箱等家电出故障,找维修却怕遇上“小病大修”“坐地起价”。别愁,专为安徽消费者打造的家电维修“放心平台”来了
2026-03-11 14:55:00
近日,备受瞩目的2025年度“吴文俊人工智能科学技术奖”获奖名单正式揭晓。罗普特(股票代码:688619.SH)作为主要完成单位参与的《面向海上安防的通感算一体化大数据智能处理关键技术及产业化》项目
2026-03-11 15:01:00
新华保险“空中柜面”让保单服务零距离
鲁网3月11日讯“您好,欢迎使用新华保险空中柜面服务!”当客户通过手机视频联系接通后台柜员时,这一句温暖的问候便会准时响起
2026-03-11 16:35:00
新华社记者 曾晋“你‘养龙虾’了吗?”这句略显无厘头的有趣问话,说的可是最近科技圈的一件大事。此“龙虾”并非餐桌上的美味
2026-03-11 16:02:00
长白时评评论员 丁铁巴基斯坦独立新闻社日前报道,曾是大型农场专属的现代农业机械化,正因中国农机驶入全球田间地头被改写,手工耕作的辛劳正被高效的机械作业替代
2026-03-11 11:32:00
降噪新科技,轻松听清晰,潜能发展更可期----科利耳Nucleus™ 8以创新聆听赋能成长
在移动互联高度发达的当下,听损人士的生活场景愈发多元:孩子们在游乐场嬉戏,笑声与广播声交织;学生们在校园里讨论,声音此起彼伏
2026-03-11 13:01:00
海湾深化转型,打造第二增长曲线
2025年,海湾安全技术有限公司(以下简称"海湾")迈入发展新阶段,在消防行业深度变革的浪潮中交出了一份亮眼的答卷。新年伊始
2026-03-11 13:02:00
八马以科技为翼,武夷山超级工厂破解茶行业非标发展桎梏
中国茶行业千年发展,却长期受困于“非标”痛点,品质参差、产能有限成为行业升级的最大阻碍。而作为“高端中国茶第一股”的八马茶业
2026-03-11 13:04:00
实现社保一站式便民服务厦门“汇智办”让缴费人“会自办”东南网3月11日讯(海峡导报记者 孙春燕 通讯员 杨楠欢 叶璐璐 廖皓宇) 受春节过后的“返工潮”影响
2026-03-11 13:46:00
探路制造出海“关键一跃”:华南师范大学调研团队走进华翱集团
面对复杂多变的国际环境,佛山制造业正迎来新一轮深度转型的关键期。从深耕国内市场到逐鹿全球蓝海,如何实现从单一“产品出海”向涵盖“技术-制造-品牌”的全链条出海跨越
2026-03-11 13:04:00