【问题标题】:What happens to the Java Thread during a memory leak in the heap?在堆内存泄漏期间 Java 线程会发生什么?
【发布时间】:2020-04-28 03:37:54
【问题描述】:

我知道堆中的内存泄漏是由于堆栈中仍然可以访问/引用的对象,因此 GC 无法清理它。所以我的问题是:

  1. 这是否意味着仍有一个 Java 线程在运行,它拥有该 Stack 内存?
  2. 如果是,再次运行同一个 Java 线程会增加内存泄漏,或者它会重复使用堆中的相同对象,因为它们对所有线程都是可见的?
  3. 如果不是,由于堆中的对象必须能够被堆栈访问才能在 GC 中幸存下来,因此堆内存和堆栈内存中是否都会发生泄漏?

对于这些简单的问题,我很抱歉,但我很难找到明确的答案。谢谢!

【问题讨论】:

    标签: java memory-leaks


    【解决方案1】:

    我知道堆中的内存泄漏是由于堆栈中仍然可以访问/引用的对象导致 GC 无法清理它。

    这只是内存泄漏的一个可能原因。另一个是static 变量中有不需要的引用。如果你挖得足够深,可能还有其他人。 (例如,您可以在本机代码中创建 Java 堆内存泄漏,或者通过管理不当的类加载器或直接内存缓冲区,或者通过运行太多线程。)

    1) 这是否意味着仍有一个 Java 线程在运行,该线程拥有该堆栈内存。

    Java 线程的堆栈在它终止时会被删除。因此,如果堆栈存在,则意味着其线程尚未终止。但它可能正在运行、等待锁定或在 I/O 操作中阻塞。

    当线程终止时,保留在其堆栈中的任何剩余引用将立即变得无法访问。但从技术上讲,当run() 方法调用终止时,它们变得无法访问。

    2) 如果是,再次运行同一个 Java 线程会增加内存泄漏,或者它会重复使用堆中的相同对象,因为它们对所有线程都是可见的?

    如果某个特定的内存泄漏是由某个线程引起的,那么再次运行该线程1自然会泄漏更多的内存。另一方面,由于线程的线程终止会释放其所有引用,因此如果在线程终止后重新运行线程,则不会复合泄漏。

    Java 不会“重用”对象。每次您new 一个类型(类或数组)时,都会创建一个全新的对象。总是。

    堆中的对象并非对所有线程可见。它们仅对可访问它们的线程可见。

    3) 如果不是,泄漏是否发生在堆内存和堆栈内存中,因为堆中的对象必须可以被堆栈访问才能在 GC 中存活?

    正如我在开始时所说,有一些方法可以创建不依赖于堆栈的内存泄漏。无需通过堆栈引用对象即可访问。


    1 - 我假设我们正在讨论使用与以前相同或等效的 Runnable 创建和启动一个新的 Thread。从技术上讲,Thread 不能运行(启动)两次。

    【讨论】:

      猜你喜欢
      • 2018-06-08
      • 2011-05-13
      • 2011-06-28
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      • 2018-07-15
      • 2021-08-15
      • 2016-10-02
      相关资源
      最近更新 更多