回答

收藏

如何在 Java 中创建内存泄漏?

技术问答 技术问答 254 人阅读 | 0 人回复 | 2023-09-11

我刚接受了面试,我被要求使用 Java创建内存泄漏。" u1 s, K' D3 s6 ]5 `0 G* n1 L
不用说,我不知道如何开始创造一个
8 k% `# S" q! {& m1 h- v能举个例子吗?3 g7 f7 \" {5 V' T; O1 L) C  A6 m. Z
                                                               
$ i% z2 ^/ ]+ y6 K: v* J/ \+ M    解决方案:                                                               
8 Z! ]/ B5 n4 U6 A( }+ C                                                                这是在纯 Java 创建真正的内存泄漏(运行代码无法访问但仍存储在内存中的对象)的好方法:$ N- \; ~/ K5 g8 C
[ol]创建长时间运行的线程(或使用线程池更快泄漏)。2 o: \/ W1 j$ q& d5 T# `  b
通过(可选定义)加载一个类ClassLoader。
" J& W% t, W, B4 H- s, d这类内存分配很大(例如)new byte[1万])将强引用存储在静态字段中,然后将自己的引用存储在静态字段中ThreadLocal. 可以选择分配额外的内存(泄漏实例就足够了),但它会使泄漏工作更快。1 n! S3 W$ ^% I# E+ t/ s, z
清除所有自定义类或应用程序ClassLoader引用其加载类。, \" w% `3 [5 D& E7 h) s  V- P
重复。[/ol]由于ThreadLocal在 Oracle 的 JDK 中实现的方式会产生内存泄漏:
- a1 e2 V: W/ S3 D每个Thread都有私有字段threadLocals,它实际上存储线程本地值。5 N+ K" W; i/ h- B( n
这个映射中的每一个键都是对象的弱引用ThreadLocal,因此在该ThreadLocal垃圾回收后,其项目将从映射中删除。
1 k9 j3 R2 @( T  r6 R7 y但是每个值都是强引用,所以当一个值(直接或间接)指向时ThreadLocal其key只要线程存在,对象就不会被垃圾收集或从映射中删除。
强引用链如下:+ E% H+ e8 V8 n2 W8 R" U
Thread对象→threadLocals映射→示例实例→示例类→静态ThreadLocal字段→ThreadLocal对象。
% V  D; T1 Y3 _  g, D/ e(ClassLoader在创建泄漏方面并没有真正发挥作用,它只是因为这个额外的引用链而使泄漏变得更糟:示例类→→ClassLoader它加载的所有类别。在许多 JVM 甚至更糟,尤其是在以前Java 7,因为 classes 和ClassLoaders 被直接分配到 permgen 根本没有垃圾回收。& N* W" J! h" @+ z) ^) g! h
这种模式的一个变体是,如果你经常重新部署并正确使用它ThreadLocal 以某种方式指向自己s 的应用程序,应用程序容器(如 Tomcat)内存可能会像筛子一样泄漏。这可能是由于许多微妙的原因,通常很难调试和/或修复。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则