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

时间:2013-01-14 15:14:49

标签: java jsf garbage-collection

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

如果B包含对A的引用,那么情况会发生相反的变化吗?如果是,那么为什么?

4 个答案:

答案 0 :(得分:6)

  

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

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

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


  

如果B包含对A的引用,那么情况会改变吗?如果是,那么为什么?

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

总而言之,不应该根据GC行为选择托管bean作用域,而应该基于它保存的数据。另请参阅How to choose the right bean scope?

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

  

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

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

答案 3 :(得分:0)

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