线程完成后何时释放线程上分配的对象? [关闭]

Posted

技术标签:

【中文标题】线程完成后何时释放线程上分配的对象? [关闭]【英文标题】:When will objects allocated on a thread be freed after the thread completes? [closed] 【发布时间】:2018-04-29 07:22:14 【问题描述】:

在这段代码中

    new Thread(new Runnable() 
        @Override
        public void run() 
            byte b[] = new byte[1024*1024*1024];

            try 
                Thread.sleep(5000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            // just for testing
            b = null;

        
    ,"thread").start();

5 秒后 1 GB 的内存应该是空闲的! 但它不会!

永远不会!!

我怎样才能找回记忆?

【问题讨论】:

为什么你认为它应该是免费的?它是符合条件的 GC,这并不意味着它很快就会被 GC。您所能做的就是相信 GC 最终会做到这一点。 @AndyTurner 不符合 GC 条件。 @shmosel 正确,但在休眠后,变量被重新分配为 null,删除了对 b 的最后引用。 OP 期望它在睡眠之后立即被释放。 @mehranrafiee 为什么?你想达到什么目标,你想解决什么问题? GC 最终将运行,清理阵列。如果您希望进程将一些堆内存返回给操作系统,那么这也是可能的。一些 GC 可以做到这一点,例如G1 GC,它是 Java 9 中的默认 GC(但也可以在以前的版本中启用)。您可以尝试运行System.gc(),但这只是一种启发式方法,它可以根据许多事情实现为无操作... 任务管理器不会测量JVM堆,它会测量分配给JVM进程的总内存,这是另一回事。要查看 JVM 堆,请使用 jvisualvm 之类的工具。 jvisualvm 工具可以向您显示堆内分配的对象,您可以使用它向您的 JVM 发送信号,请求它在设置为 null 后删除任何孤立对象,例如您的 b 数组。如果在从 jvisualvm 发送此类信号后的一段时间内,jvisualvm 报告分配的对象占用的空间随着时间的推移继续增长,那么您可能有内存泄漏。 【参考方案1】:

简单的答案是最终:不早也不晚。

您无法直接控制何时收集垃圾。如果实例不再引用它,垃圾收集器会在某个时候清理它。

【讨论】:

就是这样,我想知道GC无法释放内存的连接在哪里 仅在一种情况下 - 当列表中有一个引用仍在使用时。例如,当您在方法中创建对象然后将其返回给调用者时。直到调用者中的引用保持 GC 才能触及内存。这就是为什么有时使用new 并不好,而使用工厂来创建对象是更好的方法。 但在这种情况下,只有一个字节数组,仅此而已! 谁在乎它是什么?它是一个对象,并且有对它的引用。您的问题可能在代码中的某个地方。例如,如果代码将对象放入任何集合(列表、映射、集合)并保留它 - 因此,该集合中存在对它的引用......等等......【参考方案2】:

在 Java 中,您不能显式释放内存。

这取决于 JVM 垃圾收集器设置。 GC 行为有许多参数。

其中一些与一个 JVM 实现和版本不同。

但是,你不需要关心它。当不再引用该对象时,将在 GC 决定该时间时清理内存。

一般来说,当方法完成并且内存可以被 GC 清理时,方法引用中的所有变量都会消失。

您可以建议 GC 运行如下:

...
// just for testing
b = null;
System.gc();

但无论如何这都是一个提示。 GC 可能会运行,也可能不会。

有时像你一样排队

b = null;

不仅有利于测试,而且并不常见。

您可以尝试在 JVM 参数中操纵 GC 设置,以使 GC 更加积极,以避免经常运行 Full GC。

Internet 上有大量资源作为 Oracle JVM 的示例: Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide

记住:不同的JVM可能有不同的GC参数。

【讨论】:

还有一点需要注意:在某些情况下,内存会变成“孤儿”,只能由 Full GC 清除,Full GC 仅在堆大小接近顶部时运行。部分 GC(在方法调用之间)无法选择它。 Full GC 非常昂贵 - 当它运行所有线程时停止并等待它完成。我不记得它的实际案例,但它可能会发生。这是关于创作者在创作之前离开的时间等等......【参考方案3】:

在 java 中没有直接释放内存的方法。 GC 将运行并处理此问题。如果你认为你会得到 outofmemoryexception,那么请注意,java 将在抛出该错误之前运行垃圾收集器以释放一些内存。希望这会有所帮助

【讨论】:

你的意思是它会一直保留在内存中,直到其他东西需要内存? no.. GC运行时,内存会被释放......即使没有剩余内存,在抛出OutOfMemoryException之前,Java会运行GC,看看是否可以释放任何东西

以上是关于线程完成后何时释放线程上分配的对象? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

何时释放/保留传递给辅助线程的对象?

Servlet 异步处理

C#无法访问已释放的对象

ios:ARC中的过度释放对象[关闭]

C#如何释放线程

Java Review - 线程池资源一直不被释放案例&源码分析