Java垃圾收集器无法在我编写的程序中收集死对象,我相信这是因为死对象已经创建了内部类的实例。
当我在调试模式下查看内部类的实例时,应该在收集创建者之后,找到一个标题为this$0
的引用,它指向应该死的对象。
有没有办法阻止在Outer.this
的每个实例中由java创建Inner
引用?该字段在程序中没有用处,它所做的只是防止垃圾收集,很快导致堆耗尽内存。从Inner
移出Outer
不是一种选择,因为它有public
个数据字段,只有Outer
可见。
答案 0 :(得分:4)
您的内部类维护this$0
,以便它可以获取外部类的私有字段和方法。如果内部类不需要在外部类中使用任何内容,则可以标记内部类static
以防止它维护对包含类的实例的引用。
答案 1 :(得分:4)
尽管如此,我需要我的内部类是非静态的,因为它的每个实例都需要调用使用它的非静态实例数据的非静态方法。
在这种情况下,外部对象不应该被垃圾收集...因为外部对象是实例数据所在的位置!
<强>后续强>
那么你会推荐什么?我不知道如何使用包,但我需要创建Inner的实例,这些实例只有
Outer
可访问的公共数据字段,并且可以在Outer
的销毁之后存活下来。我运气不好吗?
在我回答你的问题之前:
现在问你的问题......
如果只希望Outer
类(以及嵌套在其中的类)可以访问字段,那么必须使用嵌套或内部类。 (如果您尝试使用包和包私有访问来执行此操作,那么在同一个包中声明的其他类也可以访问这些字段。但是,如果这是可接受的,那么包是一种更简单的方法。)
假设您要使用嵌套或内部类来执行此操作,则有两种方法可以执行此操作:
如果您将Inner
类声明为private static class Inner
,那么Inner
类中的方法无法调用Outer
的实例方法或访问实例字段...除非他们引用了Outer
实例(例如作为参数传递)。如果Inner
为static
,则Inner
和Outer
的实例的生命周期是独立的。
如果您将Inner
类声明为private class Inner
,那么Inner
类中的方法可以调用Outer
的实例方法或访问实例字段。但另一方面,Outer
实例及其Inner
实例的生命周期现在依赖于它。具体而言,只要至少有一个Outer
实例继续存在,就会存在Inner
实例。 (反之则不然......除非Outer
实例在(例如)集合类型字段中保留对Inner
个实例的引用。)
重述我之前所说的话。如果Inner
实例需要访问Outer
实例上的实例字段或调用实例方法,则需要显式或引用该Outer
实例。这意味着Outer
实例是可访问的,并且不是垃圾收集器删除的候选者。
另一点是Inner
的实例如果仍然可以访问则不会消失;即,如果正在运行的应用程序的某些部分引用了它可能使用的实例。在Java中,如果任何可能它们可以被正在运行的应用程序使用,则不会对对象进行垃圾回收。在这方面,内部/嵌套类的实例并不特殊。
实际上,可能有一种(非常讨厌的!)方式来打破Inner
和Outer
实例之间的联系。如果您可以找到所有Inner
个实例,则可以使用反射将null
分配给每个this$0
隐藏变量。但是,如果这样做,Inner
类中引用Outer
实例状态的任何代码都将中断。如果你要采用这种肮脏的方式,最好将Inner
声明为static
类。
答案 2 :(得分:0)
关于你所能做的就是让内部类静态,或者根本不使用内部类。
当然,您可以使用包作用域来限制类中字段的可见性,而不必求助于内部类。