最近,我读了很多关于java内存分配方案的文章,也有很多疑问,因为我一直在从不同的来源阅读。我已经收集了我的概念,我会要求对所有的观点和评论。我知道内存分配是JVM特定的,所以我必须事先说,我的问题是Sun特定的。
谢谢你经历了这一切!
发布于 2010-10-03 12:55:30
首先,正如你现在应该清楚的那样,很少有人能用第一手的知识来证实这些答案。很少有人研究过最近的HotSpot JVM,或者对它们进行了深入的研究。这里的大多数人(包括我在内)都是根据他们在其他地方看到的东西或者推断出来的东西来回答的。通常,这里所写的内容,或在各种文章和网页中所写的内容,都是基于其他来源,这些来源可能是确定的,也可能不是确定的。它通常是简化的,不准确的,或者完全错误的。
如果你想确认你的答案,你真的需要下载OpenJDK源代码.通过阅读和理解源代码来做你自己的研究。在这样的问题上提问,或者随意浏览网页文章,都不是一种很好的学术研究方法。
既然这么说了..。
..。我的问题是专门针对孙的。
在提出这个问题时,已经不复存在。因此,问题是甲骨文特有的。AFAIK,所有当前(非研究的)第三方JVM实现要么是OpenJDK发行版的直接端口,要么是另一个Sun/Oracle版本的后代。
下面的答案适用于Oracle和OpenJDK发行版,可能也适用于其他大多数版本.包括GraalVM。
1)类(由类加载器加载)位于堆上的一个特殊区域:永久生成。
在Java 8之前是的。
从Java 8开始,PermGen空间已经被Metaspace所取代。加载和JIT编译的类现在进入了那里。PermGen不再存在。
2)与类名称、类关联的对象数组、JVM使用的内部对象(如java/lang/ Object )和优化信息相关的所有信息都进入永久生成区域。
或多或少,是的。我不知道你说的这些话是什么意思。我猜“JVM使用的内部对象(如java/lang/Object)”指JVM--内部类描述符。
3)所有静态成员变量再次保留在永久性发电区域。
变量本身是的。这些变量(与所有Java变量一样)将保存原始值或对象引用。但是,虽然静态成员变量位于permgen堆中分配的帧中,但这些变量所引用的对象/数组可以在任何堆中分配。
4)对象在不同的堆上:年轻一代
不一定。大型对象可以直接分配到终身生成中。
5)每个类只有一个方法副本,无论方法是静态的还是非静态的。那份副本被放在了永久世代区。
假设您引用的是该方法的代码,则AFAIK是。不过,情况可能要复杂一些。例如,在JVM生命的不同时间,字节码和/或本机代码形式中可能存在这些代码。
..。对于非静态方法,所有参数和局部变量都会进入堆栈--每当有该方法的具体调用时,我们就会得到一个与它相关的新堆栈框架。
是。
..。我不知道静态方法的局部变量存储在哪里。他们是在永久一代的堆里吗?或者仅仅是它们的引用存储在永久生成区域,而实际的副本在其他地方(哪里?)
不是的。它们存储在堆栈中,就像非静态方法中的局部变量一样。
6)我也不确定方法的返回类型存储在哪里。
如果您指的是(非空)方法调用返回的值,那么它将在堆栈或机器寄存器中返回。如果它在堆栈上返回,这需要一个或两个单词,这取决于返回类型。
7)如果对象(在年轻一代中)需要使用静态成员(在永久代中),则给它们一个静态成员的引用&给它们足够的内存空间来存储方法的返回类型,等等。
这是不准确的(或者至少,你没有清楚地表达自己)。
如果某些方法访问静态成员变量,则它得到的要么是原语值,要么是对象引用。这可以分配给(现有的)局部变量或参数,分配给(现有的)静态或非静态成员,分配给以前分配的数组的(现有)元素,或者简单地使用和丢弃。
欲了解更多信息,请参阅以下资源:
https://stackoverflow.com/questions/3849634
复制相似问题