问题描述
我知道JVM使用堆栈和堆为对象引用分配内存,为方法分配对象值和内存。 但是我对术语感到困惑:METHOD AREA,HEAP和JAVA STACK,我没有几个问题。
当我们说“ ClassName obj = new ClassName()”时,new在HEAP上创建了一个对象(实例变量和静态变量也是如此),返回给reference(obj)的对象是什么? 有人习惯说它是CLASS TYPE,是否表示哈希码?
当new在堆上创建对象时,同时:i)对应于该对象的方法ii)局部变量和iii)对该对象的引用存储为STACK的一部分(是否是JAVA STACK?)。 如果是这样,那么METHOD AREA做什么? 还是我错了?
为该对象分配的内存量是多少?
一世。 供对象参考
ii。 用于对象值(取决于局部变量)
iii。 (因为非静态成员不在对象之间共享,并且为每个对象(包括方法)维护一个单独的副本),会分配内存来指向对象的方法吗?
顺便说一句,静态方法存储在哪里?
1楼
当我们说“ ClassName obj = new ClassName()”时,new在HEAP上创建了一个对象(实例变量和静态变量也是如此),返回给reference(obj)的对象是什么? 有人习惯说它是CLASS TYPE,是否表示哈希码?
是的,新的会在HEAP上创建对象。 堆是存储对象及其实例变量的内存位置。 不是静态变量,因为静态变量不属于对象,它属于类,因此存储在PermGem节中(与类有关的数据,与实例无关)。
返回值:引用(指针/内存地址),即哈希码
当new在堆上创建对象时,同时:i)对应于该对象的方法ii)局部变量和iii)对该对象的引用存储为STACK的一部分(是否是JAVA STACK?)。 如果是这样,那么METHOD AREA做什么? 还是我错了?
因为所有线程共享相同的方法区域,所以方法并不对应于它属于类的对象
方法区域的作用:方法区域存储每个类的信息,例如运行时常量池,方法代码,方法的返回类型(或void)等
为该对象分配的内存量是多少? 一世。 供对象参考ii。 用于对象值(取决于局部变量)iii。 (因为非静态成员不在对象之间共享,并且为每个对象(包括方法)维护一个单独的副本),会分配内存来指向对象的方法吗?
对象引用的内存量:它取决于许多VM,引用的大小是本机指针的大小 ,对于(iii)以上点,已经清除了该内容:
2楼
我知道JVM使用堆栈和堆为对象分配内存
正确。
对象值
我假设您是指对象的标题和字段。
和方法的记忆。
方法未存储在堆或堆栈中。 当您探查堆使用情况或设置最大堆大小时,方法的使用没有什么区别,因为它们不在Oracle或OpenJDK JVM中的堆上。
它们存储在PermGen或MetaSpace或其他一些空间中,具体取决于您使用的JVM。
但是我对以下术语感到困惑:METHOD AREA,
从Java中的
Java虚拟机具有一个在所有Java虚拟机线程之间共享的方法区域。 该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。 它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法(§2.9)。
堆
共享空间用于存储对象。 这通常是由JVM管理的本地内存的一个连续区域。
和JAVA STACK
线程的堆栈实际上是大多数JVM上的本机线程堆栈。
当我们说“ ClassName obj = new ClassName()”时,new在HEAP上创建一个对象(实例变量和静态变量也是如此)
可以,但也可以通过转义分析消除对象,将字段放在堆栈上,甚至可以消除这些对象。
并将什么返回给reference(obj)?
正确,Java仅具有引用和原语(如果您忽略都不是的void
类型)
有人说这是CLASS TYPE,
通过给出引用的类型(类或接口)来定义引用。
这意味着哈希码吗?
哈希码是对象的哈希值。 它与您提到的其他内容无关。
当new在堆上创建对象时,
在堆上创建new
对象时,只需为对象的标题(指向类及其方法)和其字段的空间创建空间。
(那些JVM没有优化掉)
同时:i)方法
该方法在各个阶段进行加载/编译。 这些方法是在第一次需要时加载的,以后再进行编译(如果需要的话)。
对应于该对象ii)局部变量
局部变量在堆栈上,不在堆上,不在对象中。
iii)对该对象的引用存储为STACK的一部分(是否是JAVA STACK?)。
Java堆栈是堆栈,是本机堆栈。
如果是这样,那么METHOD AREA做什么?
存储方法的代码。
为该对象分配的内存量是多少?
每个标头大约8-12个字节,每个原始字段的空间以及8或16个字节(32 GB-64 GB堆)的引用和对齐填充。
一世。 供对象参考
通常,在64位JVM(使用压缩的oop)上,它是32位的。 如果您有超过64 GB的堆,它将是64位。
ii。 用于对象值(取决于局部变量)
局部变量在堆上而不是对象上。
iii。 是否会分配一个内存来指向对象的方法?
方法内存使用对您不可见。 它既不在堆上,也不在每种方法的基础上进行度量。 我不知道一个探查器甚至可以向您显示。
(因为非静态成员不在对象之间共享,并且为每个对象(包括方法)维护一个单独的副本)。
这听起来像是对空间的疯狂浪费,这就是JVM这样做的原因。 一个方法只有一个副本,与实例数无关。
顺便说一句,静态方法存储在哪里?
与所有其他方法。 静态方法和非静态方法之间没有区别,只是非静态方法必须将实例作为其在JVM级别的第一个参数。 (并且修饰符中有一点可以说它是否是静态的)