在Java中,每个共享引用是否占用另一个内存字(例如32或64位)?
假设3个对象都有一个对象x
的引用,那么这3个引用中的每一个都会占用另一个内存字(例如32或64位,意味着总共96或192位),即使它们都被设置为同一个对象
例如
X x = getX();
object1.x = x;
object2.x = x;
object3.x = x;
?
此外,如果我有一个HashMap<Character, Character>
,其中我总是输入与key和value完全相同的Character
对象,那么它是否占用了HashSet<Character>
中引用的两倍内存加上Characters
本身的内存量,即使每次对key和value都使用相同的对象引用?我知道这可能与第一个问题相同,但我想知道这个案例的表现是否会有所不同
在每种情况下,如果根对象是static
,那么引用是存储在堆栈还是堆上
# 1 楼答案
基本上,如果有多个引用,每个引用都会占用单独的内存,而不管它指向哪里
# 2 楼答案
引用总是占用相同的内存量,即使在64位JVM上,通常也是32位的。它不会因为引用同一个对象和另一个引用而变小
不是。HashSet是HashMap的包装器,所以它消耗相同的内存量
静态字段总是存储在HotSpot中的堆上,但如果在JLS中没有指定,则可能会有所不同。把它放在堆栈上是没有意义的,因为它是线程本地的
# 3 楼答案
是的,你有3个参考,所以它是参考内存的3倍
Character
对象获取引用的内存及其内容(例如,char
)。一个char
原语只会占用原语的空间(这比64位系统上的引用要小)。如果将相同的对象用作键和值,那么可以查看两个引用和一个对象# 4 楼答案
将对象想象成数据库表中的一行:对于给定列,两行是否具有相同的值并不重要:仍然必须将值保存在特定行中,因此,如果两个用户共享名称John,则表将增长为托管两个John:)
# 5 楼答案
对象x、对象1、对象2和对象3将在堆上分配一次。最后三个对象中的每一个都将通过引用引用实例x。除了引用属性(假设它们没有任何其他属性)之外,这些对象中的每一个都不需要额外的内存。通常,每个对象占用的空间取决于其属性。每个分配的对象还需要jvm提供一个头,通常包括一个标记字、类元数据,如果实例是一个数组,则需要它的长度(请参见http://www.cs.princeton.edu/picasso/mats/HotspotOverview.pdf)
在类初始化阶段,静态定义的类属性在永久生成(热点中)中的类定义中分配(http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.5).
# 6 楼答案
在您编写的代码中,没有消耗尚未消耗的额外内存。您只是在更改引用
object1.x
、object2.x
和object3.x
的内容在当前的JDK中,一个
HashMap<Character, Character>
将占用与相同大小的HashSet<Character>
相同的内存量。(实际上,稍微少一些。)这与是否将字符映射到自身无关堆栈上只存储方法局部参考变量;其他所有东西都存储在堆中。特别是,任何对象的字段(无论它是否为
static
)都将像对象的其余部分一样存储在堆上