Java 为什么可以';JVM不能确保垃圾收集

Java 为什么可以';JVM不能确保垃圾收集,java,garbage-collection,Java,Garbage Collection,这不是重复的,因为作为重复提到的线程只告诉您为什么不使用System.gc(),虽然我知道,但这不是我的问题。 使用System.gc()或Runtime.getRuntime().gc()并不总是执行垃圾收集,它只是请求垃圾收集,甚至可以被JVM忽略 这背后有什么原因吗?是“随机”吗?由于我认为编程中甚至不存在随机,我很好奇为什么它有时不收集,有时收集,而且在不同的时间收集。是的。这是一个很好的理由 首先,您需要了解关于垃圾收集的几个基本事实: 运行垃圾收集器是昂贵的 在错误的时间运行垃圾收

这不是重复的,因为作为重复提到的线程只告诉您为什么不使用System.gc(),虽然我知道,但这不是我的问题。

使用System.gc()或Runtime.getRuntime().gc()并不总是执行垃圾收集,它只是请求垃圾收集,甚至可以被JVM忽略


这背后有什么原因吗?是“随机”吗?由于我认为编程中甚至不存在随机,我很好奇为什么它有时不收集,有时收集,而且在不同的时间收集。

是的。这是一个很好的理由


首先,您需要了解关于垃圾收集的几个基本事实:

  • 运行垃圾收集器是昂贵的
  • 在错误的时间运行垃圾收集器(重复)可能会导致灾难性的低效1
  • 对于一个典型的应用程序来说,几乎不可能预测GC何时可以最有效地运行

  • 因此,对于您的问题:

    使用System.gc()或Runtime.getRuntime().gc()并不总是执行垃圾收集,它只是请求垃圾收集,甚至可以被JVM忽略。这背后有什么原因吗

    对。它主要是为了防止幼稚的程序员在错误的时间调用
    gc()
    可能导致的灾难性行为影响

    是“随机”吗

    没有。这与随机性无关

    实际上,典型的JVM有一个命令行开关,用于确定是否忽略
    gc()
    调用。这允许用户/部署人员/集成人员/任何人减轻程序员做出的糟糕选择

    但请注意,它不能从Java代码中重写。这将破坏使其成为命令行开关的目的

    我很好奇为什么它有时不收集,有时收集,而且在不同的时间收集

    JVM的正常行为是在最有效的时候尝试运行垃圾收集器。JVM可以通过两种方式进行优化:

    • 它可以优化以最大化收集器的吞吐量;i、 e.尽可能减少用于收集的CPU时间

    • 它可以优化以最小化GC暂停的长度;i、 e.JVM在收集期间必须冻结所有应用程序线程的时间

    这很复杂。从外部观察者(谁/谁没有访问heap stats的权限,等等)的角度来看,可能很难理解GC为什么在给定的时间点运行。但这肯定不是随机的


    1-GC算法的一个违反直觉的特性是,收集的成本(在大多数情况下)主要是跟踪非垃圾对象和在内存中移动以合并释放的空间的成本。因此,如果您在没有太多垃圾可收集的情况下调用GC,那么您最终将跟踪/移动大量非垃圾,而实际收益微乎其微。相比之下,JVM更能洞察何时是收集的好时机。首先,它知道在任何时间点每个池中还有多少空间


    除了违反直觉之外,随着堆变大,这种行为也会变得更糟。因此,程序员可以编写以错误方式使用
    gc()
    的代码,而不会注意到存在性能问题。只有在应用程序以生产工作负载/问题大小运行时,性能才会成为问题。再加上使用堆缓存东西和/或内存泄漏的影响…

    “我认为随机性甚至不存在…”-这很有趣。密码学依赖于它的存在;你是说密码术不存在吗?当然不是随机的@BoristheSpider加密不是随机的,但您知道它何时执行吗?有规则吗?@Boristeider这取决于OP如何定义编程中的随机性。如果没有一些外部资源(即一些熵发生器),我会认为这句话是正确的。@Turing85我不认为这取决于我如何定义随机,但我是否区分随机和伪随机:P“老实说,我不认为任何人都能赢得关于随机性的讨论”-真的不确定你在这里的意思,答案有正确的和错误的。我的观点是在这种情况下使用“随机”是。。。没用,回答得好。我唯一的建议是,为了进一步解释您提到的复杂性,添加一些关于如何有许多不同的垃圾收集器实现的信息。每种方法都采取不同的方法,在不同的场景中表现出不同的行为。@BasilBourque-我认为没有必要在这里解释复杂性。Oracle垃圾收集文档比我做得更好。另一个例子是将在Java11中添加的“垃圾收集器”。它根本不执行任何垃圾收集。