可以使用太多静态变量导致Java中的内存泄漏吗?

时间:2009-03-13 04:27:34

标签: java memory-management memory-leaks

如果我的应用程序有太多静态变量或方法,那么根据定义,它们将存储在堆中。如果我错了,请纠正我

1)在应用程序关闭之前,这些变量是否会在堆上? 2)他们可以随时使用GC吗?如果没有,我可以说这是内存泄漏吗?

5 个答案:

答案 0 :(得分:83)

静态方法只是方法,它们不存储在堆上,它们只是不能使用“this”参数。

静态变量充当GC的“根”。因此,除非您明确地将它们设置为null,否则只要程序存在,它们就会存在,所以从它们可以到达的所有内容都可以使用。

如果您打算让内存变得空闲并且它不会被释放,那么情境只会被视为内存泄漏。如果您打算让静态变量在某个时间内包含对象的引用,并且在完成该对象时忘记将其设置为null,则可能最终会出现泄漏。但是,如果你把它放在静态变量中并且打算在程序运行时它就在那里,那么它绝对不是泄漏,它更可能是一个“永久单例”。如果对象在你希望它仍然存在时被回收,那将是非常糟糕的。

关于堆的问题:Java中的所有对象都存在于堆上或堆栈上。使用new运算符在堆上创建对象。然后将引用附加到它们。如果引用变为null或超出范围(例如,块结束),则GC意识到无法再次到达该对象并回收它。如果您的引用是在静态变量中,它永远不会超出范围,但您仍然可以将其设置为null或另一个对象。

答案 1 :(得分:3)

如果您有静态hashmap并向其添加数据......数据将永远不会消失并且您有泄漏 - 如果您不再需要数据。如果你需要数据,那不是泄漏,而是一堆巨大的记忆。

答案 2 :(得分:2)

直接或间接由静态引用的对象将保留在堆上,直到可以收集适当的类加载器。有些情况(例如ThreadLocal),其他对象间接引用类加载器,导致它保持未收集状态。

如果您有一个静态列表,比如说并动态添加对它的引用,那么您很容易就会遇到“对象生存期争用问题”。出于多种原因避免使用可变静态。

答案 3 :(得分:1)

只要您可以从代码中的某个位置引用这些变量,就不能通过GCed来表示它们将在那里直到应用程序结束。

你能称之为内存泄漏吗?我不会把它称之为内存泄漏,通常内存泄漏是你通常希望恢复的内存,但你永远不会这样做,或者你只能恢复它的一部分。此外,内存泄漏通常会在时间上变得更糟(例如:每次调用方法时,更多内存都会被“泄露”),但在这种情况下,这些变量的内存使用量是(有点)静态。

答案 4 :(得分:1)

它不会导致经典C语义中的​​内存泄漏...例如

Class A{

static B foo;

...

static void makeFoo(){
   foo = new B();
   foo = new B();
}

在这种情况下,调用makeFoo()不会导致内存泄漏,因为第一个实例可能被垃圾回收。