java中的静态分配——堆、栈和永久代 [英] static allocation in java - heap, stack and permanent generation

查看:30
本文介绍了java中的静态分配——堆、栈和永久代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近阅读了很多关于java内存分配方案的内容,并且在阅读各种来源时有很多疑问.我已经收集了我的概念,我会要求检查所有要点并对其进行评论.我开始知道内存分配是特定于 JVM 的,所以我必须事先说明,我的问题是特定于 Sun 的.

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. 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.

  1. 类(由类加载器加载)位于堆上的一个特殊区域:永久代
  2. 与类相关的所有信息,如类的名称、与类关联的对象数组、JVM 使用的内部对象(如 java/lang/Object)和优化信息都进入永久代区域.
  3. 所有静态成员变量再次保存在永久代区域.
  4. 对象在不同的​​堆上:年轻代
  5. 每个类的每个方法只有一个副本,无论是静态方法还是非静态方法.该副本被放置在永久世代区域.对于非静态方法,所有参数和局部变量都进入堆栈 - 每当有该方法的具体调用时,我们都会得到一个与之关联的新堆栈帧.我不确定静态方法的局部变量存储在哪里.他们在永久代的堆上吗?或者只是他们的引用存储在永久代区域,而实际的副本在其他地方(哪里?)
  6. 我也不确定方法的返回类型存储在哪里.
  7. 如果对象(在年轻代中)需要使用静态成员(在永久代中),它们会被赋予一个对静态成员的引用 &&它们有足够的内存空间来存储方法的返回类型等.

感谢您完成此操作!

推荐答案

首先,您现在应该很清楚,很少有人能够从第一手知识中确认这些答案.很少有人在最近的 HotSpot JVM 上工作或研究它们到真正了解所需的深度.这里的大多数人(包括我自己)都是根据他们在别处看到的东西或他们的推断来回答的.通常,此处或各种文章和网页中所写的内容基于其他来源,这些来源可能是确定的,也可能不是.它通常被简化、不准确或完全错误.

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. 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.

如果您想对您的答案进行明确确认,您确实需要下载 OpenJDK 源代码......并通过阅读和理解源代码自行研究.就 SO 提出问题,或随意浏览网络文章并不是一种可靠的学术研究技术.

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. Asking questions on SO, or trawling through random web articles is not a sound academic research technique.

话虽如此……

...我的问题是针对 Sun 的.

... my question is Sun specific.

在提出此问题时,Sun Microsystems 已不复存在.因此,该问题是特定于 Oracle 的.AFAIK,所有当前(非研究)第 3 方 JVM 实现要么是 OpenJDK 版本的直接移植,要么是另一个 Sun/Oracle 版本的后代.

At the time this question was asked, Sun Microsystems had ceased to exist. The question was therefore Oracle specific. AFAIK, all current (non-research) 3rd-party JVM implementations are either direct ports of an OpenJDK release or descended from another Sun/Oracle release.

以下答案适用于 Oracle Hotspot 和 OpenJDK 版本,可能也适用于大多数其他版本......包括 GraalVM.

The answers below apply to Oracle Hotspot and OpenJDK releases, and probably to most others as well ... including GraalVM.

1) 类(由类加载器加载)进入堆上的一个特殊区域:永久代.

1) Classes (loaded by the classloaders) go in a special area on heap : Permanent Generation.

在 Java 8 之前,是的.

Prior to Java 8, yes.

从 Java 8 开始,永久代空间已被元空间取代.加载的和 JIT 编译的类现在去那里.PermGen 不再存在.

As of Java 8, the PermGen space has been replaced with Metaspace. Loaded and JIT-compiled classes now go there. PermGen no longer exists.

2) 与类相关的所有信息,如类名、与类关联的对象数组、JVM 使用的内部对象(如 java/lang/Object)和优化信息都进入永久代区域.

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)"是指 JVM 内部的类描述符.

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.

3) 所有的静态成员变量再次保存在永久代区.

3) All the static member variables are kept on the Permanent Generation area again.

变量本身是的.这些变量(与所有 Java 变量一样)将保存原始值或对象引用.然而,虽然静态成员变量位于在 permgen 堆中分配的帧中,但这些变量引用的对象/数组可能会分配在任何堆中.

The variables themselves yes. These variables (like all Java variables) will hold either primitive values or object references. 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.

4) 对象在不同的​​堆上:年轻代

4) Objects go on a different heap : Young generation

不一定.大对象可以直接分配到年老代.

Not necessarily. Large objects may be allocated directly into the tenured generation.

5) 每个类的每个方法只有一个副本,无论是静态方法还是非静态方法.该副本被放入永久代区域.

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.

假设您指的是方法的代码,那么 AFAIK 是的.不过可能会稍微复杂一些.例如,代码可能在 JVM 生命周期的不同时间以字节码和/或本机代码形式存在.

Assuming that you are referring to the code of the method, then AFAIK yes. 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.

... 对于非静态方法,所有参数和局部变量都进入堆栈 - 每当有该方法的具体调用时,我们都会得到一个与之关联的新堆栈帧.

... 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 ?)

没有.它们存储在堆栈中,就像非静态方法中的局部变量一样.

No. They are stored on the stack, just like local variables in non-static methods.

6) 我也不确定方法的返回类型存储在哪里.

6) I am also unsure where does the return type of a method get stored.

如果您指的是由(非空)方法调用返回的,那么它要么在堆栈上返回,要么在机器寄存器中返回.如果它在堆栈上返回,这需要 1 或 2 个字,具体取决于返回类型.

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.

7) 如果对象(在年轻代中)需要使用静态成员(在永久代中),它们会被赋予一个对静态成员的引用 &&它们有足够的内存空间来存储方法的返回类型等.

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.

这是不准确的(或者至少,您没有清楚地表达自己).

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.

在任何情况下,调用者都不需要分配空间来保存方法返回的某些对象/数组.在 Java 中,对象和数组总是使用传值语义返回......但返回的值是对象或数组引用.

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.

有关更多信息,请参阅以下资源:

For more information, please refer to these resources:

这篇关于java中的静态分配——堆、栈和永久代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆