GC是否足够聪明,可以删除引用但不再使用的对象? [英] Is GC smart enough to remove objects that are referenced but no longer used?

查看:101
本文介绍了GC是否足够聪明,可以删除引用但不再使用的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个名为"master"的对象,它拥有100个分别称为"slave0"到"slave99"的对象.(这不是一个数组.我的主"类中分别有100个字段,分别称为salve0到slave99.)现在,让我的程序首先读取一个文件,该文件包含主"对象的序列化存储版本.但是,假设我的程序从不使用对象slave50到slave99.会发生什么?(我的猜测是,作为读取/反序列化过程的一部分,java程序将首先读取所有100个从属对象,并且在读取所有100个从属对象后 only ,它可能会选择在以下位置执行GC注意:对象"master"仍在使用中,因此从技术上讲,父对象master仍在引用slave50到slave99的对象,并且父对象主控仍在积极使用中.)

Let's say I have an object called "master" which owns 100 objects called "slave0" through "slave99" respectively. (This is not an array. I have 100 fields in my "master" class called salve0 to slave99 respectively.) Now, let's say my program first reads in a file which contained the serialized stored version of a "master" object.But, let's say my program never uses objects slave50 through slave99. What will happen? (My guess is that the java program will first read all 100 slave objects as part of the reading/deserialization process, and only after reading all 100 slave objects in, it might choose to do a GC, at which point objects slave50 through slave99 will get removed by the GC and the memory reclaimed. Is this right? NOTE: Object "master" is still being used, so technically, objects slave50 through slave99 are still being referenced by the parent object, master, and the parent object master is still being actively used.)

因此,可以说我上面的猜测关于GC的工作方式是正确的;如果我的长时间运行的程序花了几分钟时间处理从属对象slave0到slave50,然后又进入另一个名为"X"的最终(长时间运行)过程,该过程仅处理从属对象slave0到第二个事件,会发生什么.然后,GC是否会意识到,即使从属对象master仍在引用slave25到slave50对象,并且即使仍在使用对象master,GC仍将足够聪明以摆脱它从slave25到slave50的对象,因为没有人会从过程X"开始使用它?

So let's say my guess above is correct regarding how the GC works; what then happens if my long-running program spends say a few minutes processing objects slave0 through slave50, but then gets into another final (long-running) procedure named "X" that ONLY processes objects slave0 through slave25. Would the GC then realize that even though the objects slave25 through slave50 are still being reference by parent object master, and even though object master is still being used, the GC will still be smart enough to get rid of objects slave25 through slave50 since no one is going to ever use it from "procedure X" onwards?

推荐答案

对此没有简单的答案.您说对象'master'仍在使用",但不是以这种方式.原则上,可以优化对象的读写字段,甚至可以调用对象上的方法,从而无需存储对象.

There is no simple answer to this. You say "Object ‘master’ is still being used", but not, in which way. In principle, reading and writing fields of an object and even invoking methods on it can get optimized to not requiring the memory of an object.

或者,作为

可以设计程序的优化转换,以将可到达的对象数量减少到少于天真的被认为可到达的对象数量.例如,Java编译器或代码生成器可能会选择设置将不再用于 null 的变量或参数,以使此类对象的存储可能更快地被回收.

Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

如果将对象字段中的值存储在寄存器中,则会出现这种情况的另一个示例.然后,程序可能会访问寄存器而不是对象,并且再也不会访问该对象.这意味着该对象是垃圾.

Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.

正如" finalize()在Java 8中强可访问对象上调用中所讨论的那样,这不仅仅是理论上的问题.

As discussed in "finalize() called on strongly reachable object in Java 8", this is more than a theoretical issue.

但是规范还说:

请注意,只有在引用位于堆栈上而不存储在堆中的情况下,才允许进行这种优化.

Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.

...(在示例中)只要外部类对象可访问,内部类对象就应该是可访问的.

… (within the example) the inner class object should be reachable for as long as the outer class object is reachable.

这暗示着,只要您的主"对象引用了"slave50"至"slave99",则只要将主"对象视为可访问对象,就必须将它们视为可访问对象,但原则上允许一起收集它们.但是根据相同的规则,如果优化的代码能够在不再次访问其内存的情况下运行,那么即使是仍在使用的"slave0"到"slave25"也可以被收集.

Which implies that as long as your "master" object has references to "slave50" through "slave99", they must be considered reachable as long as the "master" object is considered reachable, but in principle, it is allowed to collect them all together. But according to the same rules, even the still in use "slave0" through "slave25" could get collected then, if the optimized code is capable of running without accessing their memory again.

请注意,由于优化后的代码旨在表现得与原始代码一样,因此您的程序不会注意到它们之间的区别.

Note that since optimized code is intended to behave just like the original code, your program won’t notice the difference.

因此,即使未使用的对象天真的被认为是可以到达的",它们也具有检测功能,但是它们通常取决于方法代码的优化状态,因为垃圾收集器不会分析代码,而是JVM的优化器做.在这方面,局部变量作用域纯粹是编译时的事情.对于未优化的代码可能会发生,垃圾回收器有时会认为引用仍然存在,而局部变量从源代码的角度来看却超出范围.但是更常见的是,相反的情况是,未使用的局部变量在优化的代码中消失了,即使从源代码的角度来看也是如此.无论哪种情况,从方法返回都会破坏整个堆栈框架,包括所有局部变量,因此您无需在返回之前将局部变量设置为 null .

So, there are capabilities to detect unused objects, even if they "would naively be considered reachable", but usually they depend on the optimization state of the method’s code, as the garbage collector does not analyze code, but the JVM’s optimizer does. In that regard, local variable scope is purely a compile-time thing. It may happen for unoptimized code, that the garbage collector sometimes considers a reference to be still existing, while the local variable is out of scope from the source code’s perspective. But more than often, it happens the other way round, unused local variables disappear in optimized code, even when being in scope from the source code’s perspective. In either case, returning from a method destroys the entire stack frame, including all local variables, thus you never need to set local variables to null before returning.

最好的策略是永远不要插入任何明确的操作来帮助垃圾收集器",除非您遇到方案的实际问题,否则JVM无法充分处理.这些真的很少见.

The best strategy is to never insert any explicit action to "help the garbage collector", unless you encounter an actual problem with a scenario, the JVM can’t handle sufficiently. These are really rare.

这篇关于GC是否足够聪明,可以删除引用但不再使用的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆