繁体   English   中英

了解Java中用于容器管理的对象的垃圾收集

[英]Understanding garbage collection in Java for objects managed by container

假设我有一个名为A的托管bean,它是@RequestScoped让我们说A有一个对另一个托管bean B的引用, B被声明为@SessionScoped A是否具有对具有更长范围的另一个bean的引用这一事实是否会阻止AHttpRequest结束时收集垃圾?

如果B包含对A的引用,情况是否会改变另一种方式? 如果是,那么为什么?

A是否具有对具有更长范围的另一个bean的引用这一事实是否会阻止AHttpRequest结束时收集垃圾?

不,如果没有对它的引用,则对象实例仅适用于GC。

默认情况下,请求范围bean仅在当前HTTP请求中引用(作为请求属性 )。 因此,如果HTTP请求完成并被销毁,那么请求范围的bean将被完全取消引用,因此符合GC的条件。 请求范围bean依次包含对会话范围bean的引用,这与GC完全无关。 只有当会话范围bean没有被引用到任何地方时(例如,当会话已经过期时),那么会话范围的bean反过来也变得对于GC来说是可用的。


如果B包含对A的引用,情况是否会改变另一种方式? 如果是,那么为什么?

是的,它会改变。 默认情况下,会话范围bean仅在HTTP会话中引用(作为会话属性 ),其寿命比HTTP请求长。 因此,只要建立了HTTP会话,请求范围的bean就会存在。 这将导致潜在的数据完整性问题,因为您引用的东西应该不应该存在那么久。 这就是为什么JSF不允许您通过@ManagedProperty在更广泛的范围内的bean中注入更窄的范围bean的原因之一。

总而言之,不应根据GC行为选择托管bean作用域,而应基于它所拥有的数据。 另请参见如何选择正确的bean范围?

No.GC仅取决于有多少实时引用指向对象,而不是另一种方式。 JVM始终维护一组活动的引用。 从这个根引用集无法访问的任何东西都有资格进行垃圾收集。即使一个对象是A指向另一个正在运行的对象B,如果内存中没有其他对象引用了A,那么A是可用的对于GC。

在您的情况下,A的范围仅限于单个请求。因此,当服务器完成该请求处理时,如果没有内存泄漏,则A将可用于gc.B将保留在内存中,因为它具有会话范围。

在您的示例中,您遇到以下情况:请求范围引用对象A,A和会话范围引用对象B.当请求结束时,它将被删除,因此不会引用对象A.它可以被垃圾回收。 在该会话之后仍然引用对象B并且它无法收集。 根据Java规范:

当任何代码无法访问对象时,该对象就有资格进行垃圾回收。

这意味着当对象无法访问时很简单。 在这种情况下,A将无法访问,但B将是。

在任何情况下,如果从一个根对象中引用了你的对象(只要有从Main()或任何其他静态/单例/ bean到达它的方法,它无论多深,无论如何)GC不会收集它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM