简体   繁体   English

java中的静态分配——堆、栈和永久代

[英]static allocation in java - heap, stack and permanent generation

I have been lately reading a lot on memory allocation schemes in java, and there have been many doubts as I have been reading from various sources.我最近阅读了很多关于 Java 内存分配方案的文章,在阅读各种来源的文章时,有很多疑问。 I have collected my concepts, and I would request to go through all of the points and comment on them.我已经收集了我的概念,我会要求检查所有要点并对其进行评论。 I came to know that memory allocation is JVM specific, so I must say beforehand, that my question is Sun specific.我开始知道内存分配是特定于 JVM 的,所以我必须事先说明,我的问题是特定于 Sun 的。

  1. Classes (loaded by the classloaders) go in a special area on heap : Permanent Generation类(由类加载器加载)进入堆上的一个特殊区域:永久代
  2. All the information related to a class like name of the class, Object arrays associated with the class, internal objects used by JVM (like java/lang/Object) and optimization information goes into the Permanent Generation area.与类相关的所有信息,如类名、与类关联的对象数组、JVM 使用的内部对象(如 java/lang/Object)和优化信息都进入永久代区域。
  3. All the static member variables are kept on the Permanent Generation area again.所有的静态成员变量再次保存在永久代区域。
  4. Objects go on a different heap : Young generation对象在不同的​​堆上:年轻代
  5. There is only one copy of each method per class, be the method static or non-static.每个类的每个方法只有一个副本,无论是静态方法还是非静态方法。 That copy is put in the Permanent Generation area.该副本被放入永久世代区域。 For non-static methods, all the parameters and local variables go onto the stack - and whenever there is a concrete invocation of that method, we get a new stack-frame associated with it.对于非静态方法,所有参数和局部变量都进入堆栈 - 每当有该方法的具体调用时,我们都会得到一个与之关联的新堆栈帧。 I am not sure where are the local variables of a static method are stored.我不确定静态方法的局部变量存储在哪里。 Are they on the heap of Permanent Generation ?他们是否在永久代的堆上? Or just their reference is stored in the Permanent Generation area, and the actual copy is somewhere else (Where ?)或者只是他们的引用存储在永久代区域,而实际的副本在其他地方(哪里?)
  6. I am also unsure where does the return type of a method get stored.我也不确定方法的返回类型存储在哪里。
  7. If the objects (in the young generation) needs to use a static member (in the permanent generation), they are given a reference to the static member && they are given enough memory space to store the return type of the method,etc.如果对象(在年轻代中)需要使用静态成员(在永久代中),它们会被赋予一个对静态成员的引用 && 它们被赋予足够的内存空间来存储方法的返回类型等。

Thank you for going through this !谢谢你经历了这一切!

First, as should be clear to you by now that there are very few people who can confirm these answers from first hand knowledge.首先,您现在应该很清楚,很少有人能够从第一手知识中确认这些答案。 Very few people have worked on recent HotSpot JVMs or studied them to the depth needed to really know.很少有人在最近的 HotSpot JVM 上工作或研究它们到真正了解所需的深度。 Most people here (myself included) are answering based on things they have seen written elsewhere, or what they have inferred.这里的大多数人(包括我自己)都是根据他们在别处看到的东西或他们推断出来的东西来回答的。 Usually what is written here, or in various articles and web pages, is based on other sources which may or may not be definitive.通常,这里或各种文章和网页中所写的内容是基于其他来源,这些来源可能是确定的,也可能不是。 Often it is simplified, inaccurate or just plain wrong.它通常被简化、不准确或完全错误。

If you want definitive confirmation of your answers, you really need to download the OpenJDK sourcecode ... and do your own research by reading and understanding the source code.如果您想对您的答案进行明确确认,您确实需要下载 OpenJDK 源代码……并通过阅读和理解源代码来进行自己的研究 Asking questions on SO, or trawling through random web articles is not a sound academic research technique.就 SO 提出问题,或浏览随机的网络文章并不是一种可靠的学术研究技术。

Having said that ...话虽如此...

... my question is Sun specific. ...我的问题是针对 Sun 的。

At the time this question was asked, Sun Microsystems had ceased to exist.在提出这个问题时,Sun Microsystems 已经不复存在。 The question was therefore Oracle specific.因此,该问题是特定于 Oracle 的。 AFAIK, all current (non-research) 3rd-party JVM implementations are either direct ports of an OpenJDK release or descended from another Sun/Oracle release. AFAIK,所有当前(非研究)第 3 方 JVM 实现要么是 OpenJDK 版本的直接端口,要么是另一个 Sun/Oracle 版本的后代。

The answers below apply to Oracle Hotspot and OpenJDK releases, and probably to most others as well ... including GraalVM.下面的答案适用于 Oracle Hotspot 和 OpenJDK 版本,可能也适用于大多数其他版本......包括 GraalVM。

1) Classes (loaded by the classloaders) go in a special area on heap : Permanent Generation. 1)类(由类加载器加载)进入堆上的一个特殊区域:永久代。

Prior to Java 8, yes.在 Java 8 之前,是的。

As of Java 8, the PermGen space has been replaced with Metaspace.从 Java 8 开始,永久代空间已被元空间取代。 Loaded and JIT-compiled classes now go there.加载的和 JIT 编译的类现在去那里。 PermGen no longer exists. PermGen 不再存在。

2) All the information related to a class like name of the class, Object arrays associated with the class, internal objects used by JVM (like java/lang/Object) and optimization information goes into the Permanent Generation area. 2) 与类相关的所有信息,如类名、与类关联的对象数组、JVM 使用的内部对象(如 java/lang/Object)和优化信息都进入永久代区域。

More or less, yes.或多或少,是的。 I'm not sure what you mean by some of those things.我不确定你所说的其中一些是什么意思。 I'm guessing that "internal objects used by JVM (like java/lang/Object)" means JVM-internal class descriptors.我猜测“JVM 使用的内部对象(如 java/lang/Object)”意味着 JVM 内部类描述符。

3) All the static member variables are kept on the Permanent Generation area again. 3)所有的静态成员变量都再次保存在Permanent Generation区。

The variables themselves yes.变量本身是的。 These variables (like all Java variables) will hold either primitive values or object references.这些变量(与所有 Java 变量一样)将保存原始值或对象引用。 However, while the static member variables are in a frame that is allocated in the permgen heap, the objects/arrays referred to by those variables may be allocated in any heap.然而,虽然静态成员变量位于在 permgen 堆中分配的框架中,但这些变量引用的对象/数组可以在任何堆中分配。

4) Objects go on a different heap : Young generation 4)对象在不同的​​堆上:年轻代

Not necessarily.不一定。 Large objects may be allocated directly into the tenured generation.大对象可以直接分配到老年代。

5) There is only one copy of each method per class, be the method static or non-static. 5) 每个类的每个方法只有一个副本,无论是静态方法还是非静态方法。 That copy is put in the Permanent Generation area.该副本被放入永久世代区域。

Assuming that you are referring to the code of the method, then AFAIK yes.假设您指的是该方法的代码,那么 AFAIK 是的。 It may be a little more complicated though.不过可能会稍微复杂一些。 For instance that code may exist in bytecode and/or native code forms at different times during the JVM's life.例如,代码可能在 JVM 生命周期的不同时间以字节码和/或本机代码形式存在。

... For non-static methods, all the parameters and local variables go onto the stack - and whenever there is a concrete invocation of that method, we get a new stack-frame associated with it. ...对于非静态方法,所有参数和局部变量都进入堆栈 - 每当有该方法的具体调用时,我们都会得到一个与之关联的新堆栈帧。

Yes.是的。

... I am not sure where are the local variables of a static method are stored. ...我不确定静态方法的局部变量存储在哪里。 Are they on the heap of Permanent Generation ?他们是否在永久代的堆上? Or just their reference is stored in the Permanent Generation area, and the actual copy is somewhere else (Where ?)或者只是他们的引用存储在永久代区域,而实际的副本在其他地方(哪里?)

No. They are stored on the stack, just like local variables in non-static methods.不。它们存储在堆栈中,就像非静态方法中的局部变量一样。

6) I am also unsure where does the return type of a method get stored. 6) 我也不确定方法的返回类型存储在哪里。

If you mean the value returned by a (non-void) method call, then it is either returned on the stack or in a machine register.如果您的意思是(非空)方法调用返回的,那么它要么在堆栈上返回,要么在机器寄存器中返回。 If it is returned on the stack, this takes 1 or two words, depending on the return type.如果它在堆栈上返回,则需要 1 或两个字,具体取决于返回类型。

7) If the objects (in the young generation) nees to use a static member (in the permanent generation), they are given a reference to the static member && they are given enough memory space to store the return type of the method,etc. 7) 如果对象(在年轻代)需要使用静态成员(在永久代),他们被赋予一个对静态成员的引用 && 他们被赋予足够的内存空间来存储方法的返回类型等.

That is inaccurate (or at least, you are not expressing yourself clearly).这是不准确的(或者至少,您没有清楚地表达自己)。

If some method accesses a static member variable, what it gets is either a primitive value or an object reference .如果某个方法访问一个静态成员变量,它得到的要么是一个原始值,要么是一个对象引用 This may be assigned to an (existing) local variable or parameter, assigned to an (existing) static or non-static member, assigned to an (existing) element of a previously allocated array, or simply used and discarded.这可以分配给(现有的)局部变量或参数,分配给(现有的)静态或非静态成员,分配给先前分配的数组的(现有)元素,或者简单地使用和丢弃。

  • In no case does new storage need to be allocated to hold either a reference or a primitive value.在任何情况下都不需要分配新的存储来保存引用或原始值。

  • Typically, one word of memory is all that is needed to store an object or array reference, and a primitive value typically occupies one or two words, depending on the hardware architecture.通常,存储对象或数组引用只需要一个字的内存,而原始值通常占用一到两个字,具体取决于硬件架构。

  • In no case does space need to be allocated by the caller to hold some object / array returned by a method.在任何情况下,调用者都不需要分配空间来保存方法返回的某些对象/数组。 In Java, objects and arrays are always returned using pass-by-value semantics ... but that value that is is returned is an object or array reference.在 Java 中,对象和数组总是使用传值语义返回……但返回的值是对象或数组引用。


For more information, please refer to these resources:有关更多信息,请参阅以下资源:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM