我刚刚接受了一次采访,我被要求用Java创建一个100.

不用说,我觉得自己很傻,甚至不知道如何开始创建一个.

举个例子好吗?

推荐答案

下面是一个在纯Java中创建真正内存泄漏(运行代码无法访问但仍存储在内存中的对象)的好方法:

  1. 应用程序会创建一个长时间运行的线程(或者使用线程池来更快地泄漏).
  2. 线程通过(可选的自定义)ClassLoader加载一个类.
  3. 该类分配一大块内存(例如new byte[1000000]),在静态字段中存储对它的强引用,然后在ThreadLocal中存储对自身的引用.分配额外的内存是可选的(泄漏类实例就足够了),但这会使泄漏工作更快.
  4. 应用程序清除对自定义类或从中加载它的ClassLoader的所有引用.
  5. 重复

由于在Oracle的JDK中实现ThreadLocal的方式,这会造成内存泄漏:

  • 每个Thread都有一个私有字段threadLocals,它实际上存储线程本地值.
  • 此映射中的每个key都是对ThreadLocal对象的弱引用,因此在对该ThreadLocal对象进行垃圾收集后,其条目将从映射中删除.
  • 但每个value都是一个强引用,因此当一个值(直接或间接)指向ThreadLocal对象(即其key)时,只要线程存在,该对象就不会被垃圾收集,也不会从映射中移除.

在本例中,强引用链如下所示:

对象→threadLocals映射示例类→实例→示例类→静电字段→ThreadLocal对象.

(ClassLoader在创建泄漏中并没有真正起到作用,它只是因为这个额外的引用链:example类而使泄漏变得更严重.)→ ClassLoader→ 它加载的所有类.在许多JVM实现中,情况甚至更糟,尤其是在Java 7之前,因为类和ClassLoader被直接分配到permgen中,而且从未被垃圾收集过.)

这种模式的一个变化是,如果经常重新部署碰巧使用ThreadLocal个以某种方式指向自身的应用程序,那么应用程序容器(如Tomcat)会像筛子一样泄漏内存.发生这种情况有很多微妙的原因,通常很难调试和/或修复.

Update:因为很多人一直要求,所以here's some example code that shows this behavior in action.

Java相关问答推荐

验证使用GCP生成的非对称密钥时签名不起作用

找到允许的最大底片

有没有一种方法使保持活动设置专用于java.net.http.HttpClient的一个实例

Java记录的不同序列化/反序列化

SpringBootreact 式Web应用程序的Spring Cloud Configer服务器中的资源控制器损坏

使用Spring Boot3.2和虚拟线程的并行服务调用

查找剩余的枚举

将带有js文件的 bootstrap 程序导入maven项目时出错

如何在ApachePOI中将图像添加到工作表的页眉?

如何获取Instant#of EpochSecond(?)的最大值

Spring和可编辑";where";@Query

我如何知道MediaDiscoverer何时完成发现介质?

如何在JavaFX中处理多个按钮

从LineChart<;字符串、字符串和gt;中删除数据时出现特殊的ClassCastException;

A.ForEach与For(类型a:集合)

在Oracle db中,当我们提供字符串而不是数字时,比较是如何工作的?

我的代码是线程安全的吗?[Java、CAS、转账]

Android无法在Java代码中调用Kotlin代码,原因是在Companion中使用Kotlin枚举时

为什么JavaFX MediaPlayer音频播放在Windows和Mac上运行良好,但在Linux(POPOS/Ubuntu)上却有问题?

Java HashMap保留所有时间复杂性