在 Java 中导致内存泄漏的最简单方法

2022-09-01 03:01:37

可能的重复项:
使用 Java 创建内存泄漏

导致 Java 内存泄漏的最简单方法是什么?


答案 1

在Java中,你不能真正“泄漏内存”,除非你:

  • 实习生字符串
  • 生成类
  • 泄漏 JNI 调用的本机代码中的内存
  • 在某个被遗忘或晦涩的地方保留你不想看到的事物的引用。

我认为你对最后一种情况感兴趣。常见方案包括:

  • 侦听器,尤其是使用内部类完成的侦听器
  • 缓存。

一个很好的例子是:

  • 构建一个Swing GUI,可以启动可能无限数量的模式窗口;
  • 让模式窗口在初始化期间执行如下操作:
    StaticGuiHelper.getMainApplicationFrame().getOneOfTheButtons().addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){
    // do nothing...
    }
    })
    

注册的操作不执行任何操作,但它会导致模式窗口永远在内存中徘徊,即使在关闭后,也会导致泄漏 - 因为侦听器永远不会被取消注册,并且每个匿名内部类对象都持有对其外部对象的引用(不可见)。更重要的是 - 从模式窗口引用的任何对象也有可能泄漏。

这就是 EventBus 等库默认使用弱引用的原因。

除了听众之外,其他典型的例子是缓存,但我想不出一个好例子。


答案 2

“在计算机科学中,内存泄漏(或在这种情况下的泄漏)发生在计算机程序消耗内存但无法将其释放回操作系统时。(维基百科)

简单的答案是:你不能。Java 执行自动内存管理,并将释放您不需要的资源。你无法阻止这种情况的发生。它将始终能够释放资源。在具有手动内存管理的程序中,这是不同的。你可以使用malloc()在C中获取一些内存。要释放内存,您需要 malloc 返回的指针,并在其上调用 free()。但是,如果您不再有指针(覆盖或超过生存期),那么不幸的是,您无法释放此内存,因此存在内存泄漏。

到目前为止,所有其他答案在我的定义中都不是真正的内存泄漏。它们都旨在用毫无意义的东西真正快速地填充记忆。但是,在任何时候,您仍然可以取消引用您创建的对象,从而释放内存→没有铅acconrad的答案非常接近,尽管我不得不承认,因为他的解决方案实际上是通过强制垃圾收集器在无休止的循环中“崩溃”垃圾收集器)。

很长的答案是:通过使用JNI为Java编写一个库,你可以得到一个内存泄漏,JNI可以手动管理内存,因此有内存泄漏。如果调用此库,Java 进程将泄漏内存。或者,您可能在 JVM 中存在错误,从而导致 JVM 丢失内存。JVM中可能存在错误,甚至可能有一些已知的错误,因为垃圾回收并不是那么微不足道,但它仍然是一个错误。根据设计,这是不可能的。您可能要求一些受此类错误影响的Java代码。对不起,我不知道一个,无论如何,在下一个Java版本中,它很可能不再是一个错误。


推荐