我有一个关于用java语言创建对象的内存问题。
当一个人在java中创建一个对象时,堆上会占用一定的内存空间 - 对吗?但是这段记忆的一部分是什么?是成员变量还是成员变量和方法?可能是因为引用同一个类的几个对象共享一些内容吗?
假设我有以下课程
class MyClass {
//Membervariables
protected int age;
protected long dateOfBirth;
/**
* Constructor
* @param age
*/
public MyClass(int age) {
this.age = age;
}
/**
*
* @param dateOfBirth
*/
protected void setDob(long dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
/**
*
* @return
*/
protected int getAge() {
return this.age;
}
/**
*
* @return
*/
protected long getDob() {
return this.dateOfBirth;
}
}
所以在本课程中我有以下内容: - 两个成员变量 - 一个 int 一个长
一个构造函数
一个mutator-method
一种访问者方法。
在main方法中,我创建了这个类的两个实例(对象):
MyClass myClass1 = new MyClass(10);
MyClass myClass2 = new MyClass(11);
所以我的问题是:
1)如何在计算机内存中描述?
2)关于对象的内存中存储事物的相同“架构”是否也可以应用于c ++?
提前致谢!!!
答案 0 :(得分:3)
对象由指向类的内部版本的指针,用于synchronized
锁定的区域,GC标志区域以及类中定义的实例字段组成。 (请注意,对象引用字段只是一个指针 - 引用的对象是单独分配的。)
通过遵循类的类指针并索引内部类对象中的方法表来定位方法。
上面的对象,在64位JVM中,大概是:
(这是一种可能的实现。有些技巧可用于减少/组合锁定和GC字段的空间,例如。但基本原则适用。)
答案 1 :(得分:1)
对象数据在堆上,类数据和成员函数是共享的
答案 2 :(得分:1)
Java语言规范未指定堆布局。在实践中,大多数Java对象将至少具有“vtable指针”(术语可疑),其指向方法向量表(可能是方法指针,但也很可能是一系列“跳转”指令)和其他运行 - 时间类型信息,然后是数据成员。因此,对于您的示例,对象的堆布局可能如下所示:
(4 bytes) vtable pointer (points to MyClass vtable)
(4 bytes) age
(8 bytes) date of birth
对于同一个类的任何两个对象,vtable指针应具有相同的值。因此,方法向量表和方法本身在地址空间中只出现一次。
请记住,这只是一个(简化的)示例,Java的实现不需要遵循这一点。
关于问题的第二部分,C ++使用相同的技术;但同样,在语言规范中没有完全指定堆布局。当然,C ++中的对象不一定需要存储在堆上(当某些优化发挥作用时,Java中也是如此),但是对象的内存布局通常不依赖于它的分配位置。
答案 3 :(得分:1)
当一个人在java中创建一个对象时,堆上会占用一定的内存空间 - 对吗?
可能,但JVM可以将它放在堆栈上或完全优化它。
但是这段记忆的一部分是什么?
如果你有一个世代收藏家,小的物体被放置在伊甸园空间中,大的物体被放置在终身空间。
是成员变量还是成员变量和方法?
只是变量。该对象具有指向包含所有已加载方法的类的链接。
是否可以这样引用同一个类的几个对象共享一些内容?
是的,当然。但这不是一个要求,只是一个更优化的解决方案。
1)如何在计算机内存中描述?
64位JVM有一个16字节的头,其中包含hashCode和对类的引用。接下来是字段。为了改善内存访问,更宽的字段一起显示以减少所需的填充量。
2)关于对象的内存中存储事物的相同“架构”是否也可以应用于c ++?
对于使用虚方法的C ++对象,它们也会有一个指向vtable的链接。