Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用过多的静态变量会导致内存泄漏吗?_Java_Memory Management_Memory Leaks - Fatal编程技术网

在Java中使用过多的静态变量会导致内存泄漏吗?

在Java中使用过多的静态变量会导致内存泄漏吗?,java,memory-management,memory-leaks,Java,Memory Management,Memory Leaks,如果我的应用程序有太多的静态变量或方法,那么根据定义,它们将存储在堆中。如果我错了,请纠正我 1) 在应用程序关闭之前,这些变量是否在堆上? 2) 它们是否随时可供GC使用?如果不是,我可以说这是内存泄漏吗?静态方法只是方法,它们不存储在堆上,它们只是不能使用“this”参数 静态变量充当GC的“根”。因此,除非您显式地将它们设置为null,否则它们将在程序的生命周期内一直存在,从它们可以访问的所有内容也是如此 只有当您希望内存变为可用而未变为可用时,这种情况才被视为内存泄漏。如果您打算让静态变

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

1) 在应用程序关闭之前,这些变量是否在堆上?

2) 它们是否随时可供GC使用?如果不是,我可以说这是内存泄漏吗?

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

静态变量充当GC的“根”。因此,除非您显式地将它们设置为null,否则它们将在程序的生命周期内一直存在,从它们可以访问的所有内容也是如此

只有当您希望内存变为可用而未变为可用时,这种情况才被视为内存泄漏。如果您打算让静态变量在一段时间内包含对某个对象的引用,但在处理完该对象后忘记将其设置为null,那么很可能会导致泄漏。但是,如果您将它放在静态变量中,并希望它在程序运行期间一直存在,那么它肯定不是泄漏,更可能是“永久单例”。如果对象在您希望它仍然存在时被回收,那将是非常糟糕的


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

只要您可以从代码中的某个地方引用这些变量,GCed就不能引用,这意味着它们将一直存在,直到应用程序结束


你能称之为内存泄漏吗,我不会称之为内存泄漏,通常情况下,内存泄漏是指你通常希望恢复的内存,但你从未恢复过,或者你只恢复了部分内存。此外,内存泄漏通常会在时间上变得更严重(例如:每次调用一个方法时,都会有更多的内存“泄漏”),但是在这种情况下,这些变量的内存使用是(某种)静态的。

它不会导致经典C意义上的内存泄漏。。。比如说

Class A{

static B foo;

...

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

在这种情况下,对makeFoo()的调用不会导致内存泄漏,因为可以对第一个实例进行垃圾收集。

静态直接或间接引用的对象将保留在堆上,直到可以收集到相应的类装入器。在某些情况下(例如ThreadLocal),其他对象间接引用类加载器,导致类加载器保持未收集状态


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

如果您有一个静态哈希映射,并向其中添加数据。。。数据永远不会消失,你有一个泄漏-以防你不再需要这些数据。如果您需要数据,它不是泄漏,而是一堆巨大的内存。

IIRC声明静态字段的类一旦被GCed,静态字段就会被GCed。如果类的最后一个实例消失了,那么类声明就会消失,静态字段也随之消失。我不确定@o11rig是否完全准确,但我相信在某些情况下允许GC为没有成员的类收集静态数据。我听过一些消息来源,但从未听过确切的解释。如果对象引用和原语是当前执行方法的局部变量,则它们可以存储在堆栈上,否则将存储在堆上。(除了在任何具有JIT的现代JVM中,JIT的优化器可以将对象放在它喜欢的任何地方,只要它仍然像对象在堆上一样工作。)而且可以认为静态方法——或者至少是实现它们的Java字节码——也存在于堆上,作为类对象的一部分,该对象表示定义它们的类。不需要从代码中引用静态变量。。。类加载器永久保存引用,因此GC永远不会启动;我将映射的引用设为null(不是它包含的所有对象)?是内存泄漏吗?因为您已经声明“类加载器永久地持有一个静态引用,因此GC将永远不会启动”?如果您将静态引用设置为null,并且您没有在任何其他地方引用该映射,那么内存将被释放。如果该映射中的被引用对象未被其他人引用,则它们也将被释放。