2

这是我心中的一个怀疑,并认为要彻底解决它。
假设我有以下作为我的应用程序的一部分加载的类:

class HeavyClass {
    static final ArrayList list = new ArrayList(100);
}

静态成员的生命周期是否与应用程序保持一致,而不管 HeavyClass 的实例发生了什么。
如果静态将自身与未收集垃圾的类加载器内存(permgen)对齐 - 确保这样一个对象仅在需要的基础上消耗(并清理成员)的编程习惯是什么;假设我们必须有一个静态在所有实例之间共享)

4

2 回答 2

6

静态变量存在于类对象的生命周期中。也就是说,它们是在加载类时创建的,并且通常仅在 ClassLoader 被处置时才会消失。

如果列表要附加到HeavyClass你不应该做的实例static,调用方法会给你。list.clear()finalizeunpredictable results

参考java语言规范

8.3.1.1。静态字段

如果一个字段被声明为静态的,那么无论最终创建多少个类的实例(可能为零),都只存在该字段的一个化身。静态字段,有时称为类变量,在类初始化时体现(第 12.4 节)。

于 2013-05-27T03:21:33.530 回答
1

静态成员的生命周期是否与应用程序保持一致,而不管 HeavyClass 的实例发生了什么。

差不多,是的。请参阅 BevnQ 的答案。

如果静态将自身与未被垃圾收集的类加载器内存(permgen)对齐......

虽然类的静态框架(通常)在 permgen 中分配:

  1. permgen memory >>is<< 垃圾收集,并且
  2. 静态框架中的对象引用(例如,arraylist)未在 permgen 中分配。

然而,这些事实都没有真正改变任何东西......除非您的应用程序确实成功地处理了加载相关类的类加载器。

确保这样的对象仅在需要的基础上使用(并清理成员)的编程习惯是什么;假设我们必须有一个静态要在所有实例之间共享)

问题是知道何时不再需要这些成员。如果可以重新生成成员,则可以使用弱引用实现缓存。这是一个常见的解决方案,并且工作得相当好,尽管您可能希望限制缓存大小。(无限缓存会消耗大量内存,这些内存更适合用于其他用途。您不会获得 OOME,但最终会更频繁地运行 GC。)

否则,您将需要实现某种引用计数机制,并希望共享数据结构的所有“客户”都遵守规则……一直。这不是一个好的解决方案。

我的建议是弄清楚如何避免使用永久“根可访问”的静态或(更一般地)大型共享数据结构。

于 2013-05-27T04:31:25.497 回答