我知道堆中的内存泄漏是由于堆栈中仍然可以访问/引用的对象导致 GC 无法清理它。
这只是内存泄漏的一个可能原因。另一个是static 变量中有不需要的引用。如果你挖得足够深,可能还有其他人。 (例如,您可以在本机代码中创建 Java 堆内存泄漏,或者通过管理不当的类加载器或直接内存缓冲区,或者通过运行太多线程。)
1) 这是否意味着仍有一个 Java 线程在运行,该线程拥有该堆栈内存。
Java 线程的堆栈在它终止时会被删除。因此,如果堆栈存在,则意味着其线程尚未终止。但它可能正在运行、等待锁定或在 I/O 操作中阻塞。
当线程终止时,保留在其堆栈中的任何剩余引用将立即变得无法访问。但从技术上讲,当run() 方法调用终止时,它们变得无法访问。
2) 如果是,再次运行同一个 Java 线程会增加内存泄漏,或者它会重复使用堆中的相同对象,因为它们对所有线程都是可见的?
如果某个特定的内存泄漏是由某个线程引起的,那么再次运行该线程1自然会泄漏更多的内存。另一方面,由于线程的线程终止会释放其所有引用,因此如果在线程终止后重新运行线程,则不会复合泄漏。
Java 不会“重用”对象。每次您new 一个类型(类或数组)时,都会创建一个全新的对象。总是。
堆中的对象并非对所有线程可见。它们仅对可访问它们的线程可见。
3) 如果不是,泄漏是否发生在堆内存和堆栈内存中,因为堆中的对象必须可以被堆栈访问才能在 GC 中存活?
正如我在开始时所说,有一些方法可以创建不依赖于堆栈的内存泄漏。无需通过堆栈引用对象即可访问。
1 - 我假设我们正在讨论使用与以前相同或等效的 Runnable 创建和启动一个新的 Thread。从技术上讲,Thread 不能运行(启动)两次。