java java中的静态内存怎么了?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/405364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Whats up with static memory in java?
提问by ForYourOwnGood
This question is for the java language in particular. I understand that there is a static protion of memory set aside for all static code.
这个问题特别针对 java 语言。我知道为所有静态代码预留了一个静态内存部分。
My question is how is this static memory filled? Is a static object put into static memory at import, or at first reference? Also, do the same garbage collection rules apply to static objects as they do for all other objects?
我的问题是这个静态内存是如何填充的?静态对象是在导入时还是在第一次引用时放入静态内存中?另外,垃圾收集规则是否适用于静态对象,就像它们适用于所有其他对象一样?
public class Example{
public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;
public class MainApp{
public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
Example.someO.someMethod();
// Do the same garbage collection rules apply to a
// static object as they do all others?
Example.someO = null;
System.gc();
}
}
回答by erickson
Imports don't correlate with any instructions in compiled code. They establish aliases for use at compile time only.
导入与编译代码中的任何指令无关。它们建立仅在编译时使用的别名。
There are some reflective methods that allow the class to be loaded but not yet initialized, but in most cases, you can assume that whenever a class is referenced, it has been initialized.
有一些反射方法允许类被加载但尚未初始化,但在大多数情况下,您可以假设每当一个类被引用时,它已经被初始化。
Static member initializers and static blocks are executed as if they were all one static initializer block in source code order.
静态成员初始值设定项和静态块的执行就像它们在源代码顺序中都是一个静态初始值设定项块一样。
An object referenced through a static member variable is strongly referenced until the class is unloaded. A normal ClassLoadernever unloads a class, but those used by application servers do under the right conditions. However, it's a tricky area and has been the source of many hard-to-diagnose memory leaks—yet another reason not to use global variables.
通过静态成员变量引用的对象将被强引用,直到类被卸载。正常ClassLoader从不卸载类,但应用服务器使用的类在正确的条件下会卸载。然而,这是一个棘手的领域,并且是许多难以诊断的内存泄漏的根源——这也是不使用全局变量的另一个原因。
As a (tangential) bonus, here's a tricky question to consider:
作为(切向)奖励,这里有一个棘手的问题需要考虑:
public class Foo {
private static Foo instance = new Foo();
private static final int DELTA = 6;
private static int BASE = 7;
private int x;
private Foo() {
x = BASE + DELTA;
}
public static void main(String... argv) {
System.out.println(Foo.instance.x);
}
}
What will this code print? Try it, and you'll see that it prints "6". There are a few things at work here, and one is the order of static initialization. The code is executed as if it were written like this:
这段代码会打印什么?试试看,你会看到它打印出“6”。这里有几件事在起作用,一是静态初始化的顺序。代码的执行就像是这样写的:
public class Foo {
private static Foo instance;
private static final int DELTA = 6;
private static int BASE;
static {
instance = null;
BASE = 0;
instance = new Foo(); /* BASE is 0 when instance.x is computed. */
BASE = 7;
}
private int x;
private Foo() {
x = BASE + 6; /* "6" is inlined, because it's a constant. */
}
}
回答by krosenvold
There is normally no such thing as "static" memory. Most vm's have the permanent generation of the heap (where classes get loaded), which is normally not garbage collected.
通常没有“静态”内存这样的东西。大多数虚拟机都有永久生成的堆(类被加载的地方),通常不会被垃圾收集。
Static objects are allocated just like any other object. But, if they live for long they will be moved between the different generations in the garbage collector. But they will not end up in permgenspace.
静态对象的分配就像任何其他对象一样。但是,如果它们存活时间长,它们将在垃圾收集器中的不同代之间移动。但它们不会最终进入永久空间。
If your class is holding onto this object permanently, it will only be released when the vm exits.
如果你的类永久持有这个对象,它只会在 vm 退出时被释放。
回答by Yaba
This static variable some0is initialized as soon as your class is referenced in your code. In your example this will be executed in first line of your main method.
一旦您的类在您的代码中被引用,这个静态变量some0 就会被初始化。在您的示例中,这将在您的 main 方法的第一行中执行。
You can validate this by creating a static initializer block. Put a break point in this initializer block and you'll see, when it will be called. Or even more simplier... put a breakpoint in the constructor of SomeObject.
您可以通过创建静态初始化程序块来验证这一点。在这个初始化块中放置一个断点,你会看到它什么时候被调用。或者更简单的......在 SomeObject 的构造函数中放置一个断点。
回答by Kevin Loney
The initialization of static variables is covered in Section 2.11 Static Initializersof suns JVM spec. The specification does not define the implementation of Garbage collection however so I imagine that garbage collection rules for static objects will vary depending on your VM.
静态变量的初始化在 suns JVM 规范的第2.11节静态初始化器中有介绍。该规范没有定义垃圾收集的实现,所以我想静态对象的垃圾收集规则会因您的 VM 而异。
回答by Thomas Morgner
It should be noted, that only the pointer (or any other primitive type) is stored in the PermGenSpace(thats the proper name for the area where the static stuff is stored).
应该注意的是,只有指针(或任何其他原始类型)存储在 PermGenSpace(这是存储静态内容的区域的正确名称)中。
So the Object referenced by the pointer sits in the normal heap, like any other object.
所以指针引用的对象位于普通堆中,就像任何其他对象一样。
回答by Alex Miller
If the static field is changed to reference a different object, the original object pointed to by the static field is eligible for GC just like any other object.
如果更改静态字段以引用不同的对象,则静态字段指向的原始对象与任何其他对象一样有资格进行 GC。
It could also be free'ed (even if not nulled) if the class itself is unloaded and the entire object graph is cut from the heap. Of course, when a class can be unloaded is a good topic for a host of other questions... :)
如果类本身被卸载并且整个对象图从堆中切出,它也可以被释放(即使没有被清空)。当然,何时可以卸载类是解决许多其他问题的好话题...... :)

