java java中的运行时与编译时内存分配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12285412/
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
Runtime vs compile time memory allocation in java
提问by user1649415
I am confused regarding whether memory allocation in java occurs at run time or compile time.
我对 java 中的内存分配是发生在运行时还是编译时感到困惑。
For example:
例如:
class Test{
int a;
public Test(){
a=10;
}
};
// somewhere else
Test t = new Test();
Is a
allocated at run time or at compile time? If at compile time, how is it possible as java runs on a VM which directly takes compiled .class files?
是a
在运行时分配还是在编译时分配?如果在编译时,java 怎么可能运行在直接接受编译的 .class 文件的 VM 上?
Also:
还:
when is
a
assigned the value10
?how does it work for reference variable
t
?
什么时候
a
赋值10
?它如何用于参考变量
t
?
Thanks.
谢谢。
回答by kosa
Compile time no memory allocation happens. Only at load and runtime.
编译时没有内存分配发生。仅在加载和运行时。
Compile time generates .class files that's it.
编译时生成 .class 文件就是这样。
Remember you need to have a main class to run the program. When you run your program using Java with classpath to .class file, there will be steps like loading & linking etc.,
请记住,您需要有一个主类来运行该程序。当您使用 Java 运行程序时,将类路径设置为 .class 文件,将会有加载和链接等步骤,
Classloaders loads the files to permgen.
类加载器将文件加载到 permgen。
When main method invoked, there will be stack created and local variables will be placed there
调用 main 方法时,会创建堆栈并放置局部变量
When runtime encounters newit creates object on heap and allocates required memory there like memory required for Test.
当运行时遇到new 时,它会在堆上创建对象并在那里分配所需的内存,就像测试所需的内存一样。
回答by Peter Lawrey
Local variables and method parameters such as primitives or reference, are notionally allocated a place on the stack at compile time.
局部变量和方法参数(如基元或引用)在编译时在概念上分配到堆栈上的一个位置。
At runtime, this isn't guaranteed to to reflect how it is laid out in memory.
在运行时,这不能保证反映它在内存中的布局。
Allocation of objects on the heap only occurs at runtime.
堆上的对象分配只发生在运行时。
how is it possible as java runs on VM which directly takes compile .class file.
java怎么可能在VM上运行,它直接编译.class文件。
Only the VM knows how the code will be compiled so it not possible to do memory allocation at compile time.
只有 VM 知道代码将如何编译,因此无法在编译时进行内存分配。
when is a assigned value 10
什么时候赋值 10
At the line where the assignment occurs. Given its not used, the JIT can discard it so it might no happen at all.
在分配发生的行。鉴于它没有被使用,JIT 可以丢弃它,所以它可能根本不会发生。
Also the same question stands for reference variable t.
同样的问题也代表参考变量 t。
t
is assigned where the =
is after the object is constructed.
t
=
在对象被构造后被分配到的位置。
回答by alvonellos
Well, this one is a bit of a doozy and I'm not sure that you're going to get the exact answer that you want out of this entire thread, since really, what you're asking, is a major discourse in the internals of the compiler, and most people really don't care.
好吧,这个问题有点难,我不确定您是否会从整个线程中得到您想要的确切答案,因为实际上,您要问的是编译器的内部结构,大多数人真的不在乎。
For the most part, the Java Compiler uses automatic memory management, so it's really up to the compiler to determine what it will or will not do, and this can change between versions.
在大多数情况下,Java 编译器使用自动内存管理,因此真正由编译器决定它将做什么或不做什么,并且这可以在版本之间改变。
But before I start explaining this, I want to clarity my notation:
但在我开始解释之前,我想澄清一下我的符号:
- I will use [Object] when referring to a Java object that is not a primitive.
- I will use [object] when referring to a location in memory that has a value and an identifier.
- I will use [primitive] to refer to an [object] that is composed of one of the primitive types in Java (int, double, float, and so on, excluding string)
String is a special case in java, and although it is an object, it may be treated differently than other objects.
An [object] has a special property. It has a value and an identifier, and the process by which an identifier is resolved to a value and at which time it occurs depends on the type of binding.
There is static binding, in which the binding can be resolved at compile time and the value or method of which is known at compile time. This is also known as "early" binding. For example.
int a = 0; // AND //a direct function call, like print();
There is also dynamic binding, in which the binding between an identifier and a value or a subprogram to a program cannot occur until runtime. This is also known as "late" binding. For example.
public void foo(java.util.List list) { list.add("bar"); }
There's also a hybrid kind of binding, but I'm not going to talk about that because I haven't discovered Java to have it.
Now, binding is also very closely related to scoping, which is the idea that a variable "lives" in a certain scope. That's a topic of discourse I really don't want to go into (scoping is kind of a bear) and make this post a novel rather than a novella.
The way memory allocation in Java works depends on a few things:
If the reference to an [Object], [object], or [primitive] is known at compile time, and is it possible for static binding to occur, then the compiler is likely to allocate memory for those objects (notice how I didn't use brackets) at compile time.
If the reference to an [Object], [object], or [primitive] cannot be known at compile time, and dynamic binding must be used, then the compiler is likely to allocate memory for those objects at runtime.
The way that Java treats objects allocated at runtime differentiates depends on which binding was used for what type.
- Static binding
- Objects that are a kind of [Object] will have their references placed on the stack at compile time, but their memory allocated on the heap at runtime. (Lazy).
- Objects that are a kind of [primitive] will be bound and allocated at runtime.
- Strings are a special case, but are generally handled like the case of an [Object]
- Late binding
- Allocation on the stack and heap done at runtime.
In summary, don't worry about it. It's a big headache for you to do so.
If I'm wrong about any of this, someone please let me know. I'm a little bit rusty.
- 我将在引用非原始对象的 Java 对象时使用 [Object]。
- 在引用内存中具有值和标识符的位置时,我将使用 [object]。
- 我将使用 [primitive] 来指代由 Java 中的一种原始类型(int、double、float 等,不包括字符串)组成的 [object]
String在java中是一个特例,虽然是一个对象,但可能与其他对象的处理方式不同。
[对象] 有一个特殊的属性。它有一个值和一个标识符,将标识符解析为值的过程以及发生的时间取决于绑定的类型。
有静态绑定,其中绑定可以在编译时解析,并且其值或方法在编译时已知。这也称为“早期”绑定。例如。
int a = 0; // AND //直接函数调用,如print();
还有动态绑定,其中标识符与值或子程序与程序之间的绑定直到运行时才能发生。这也称为“后期”绑定。例如。
public void foo(java.util.List list) { list.add("bar"); }
还有一种混合类型的绑定,但我不打算谈论它,因为我还没有发现 Java 拥有它。
现在,绑定也与作用域密切相关,作用域是变量“存在”在某个范围内的想法。这是一个我真的不想讨论的话题(范围界定是一种熊)并且使这篇文章成为小说而不是中篇小说。
Java 中内存分配的工作方式取决于以下几点:
如果在编译时对 [Object]、[object] 或 [primitive] 的引用是已知的,并且有可能发生静态绑定,那么编译器很可能会为这些对象分配内存(注意我是如何做到的) t 使用括号)在编译时。
如果在编译时无法知道对 [Object]、[object] 或 [primitive] 的引用,并且必须使用动态绑定,那么编译器很可能会在运行时为这些对象分配内存。
Java 处理在运行时分配的对象的不同方式取决于哪种绑定用于哪种类型。
- 静态绑定
- 属于 [Object] 类型的对象将在编译时将其引用放在堆栈上,但在运行时将其内存分配在堆上。(懒惰的)。
- 属于 [primitive] 类型的对象将在运行时绑定和分配。
- 字符串是一种特殊情况,但通常像 [Object] 的情况一样处理
- 后期绑定
- 堆栈和堆上的分配在运行时完成。
总之,不用担心。这样做让你很头疼。
如果我对此有任何错误,请有人告诉我。我有点生锈了。
回答by Hyman
In java a class is not loaded until unless its object is created which are created at runtime so any member variables like "a" in yours will get space when class is loaded same goes for object it will be allocated space at run time.
在java中,除非创建了在运行时创建的对象,否则不会加载类,因此在加载类时,您的任何成员变量(如“a”)都将获得空间,对于对象,它将在运行时分配空间。