5

假设我有一堂课A.java

在此处输入图像描述

当我将执行 A 的构造方法时,它会为xyzObject 创建一个内存空间。

A xyz = new A();

对内存的引用可能类似于,

[xyz] ---> '0x34524'

这就是 OOP 的基础知识。够简单!

现在,

如果一个类从不同的父类继承会发生什么?将在内存中创建多少对象空间?

可以说我们有,

在此处输入图像描述

然后我们创建一个类的对象D.java

D omg = new D();

在这里,我们知道 D 的对象将调用 C.java 的构造,依此类推,直到 A.java。这是否意味着在内存中我们有 4 个不同的内存引用,因为我们正在实例化所有四个对象(一个直接实例化,另一个 3 个间接实例化)?

[omg] ---> '0x34525'
[C]   ---> '0x34526'
[B]   ---> '0x34527'
[A]   ---> '0x34528'

笔记 :

  1. 这不是作业问题,这只是一个好奇心问题。
  2. 我知道如果我们在 A.java 中有一个实例变量,那么我们将不会只创建对象 A,但每当我们点击new关键字时,我们都会创建其他内部对象。
4

3 回答 3

5

首先,一点点......调用对象​​的构造函数不会分配它。在字节码中,初始化new Object()表示为...

new java/lang/Object
invokespecial java/lang/Object <init>()V

new指令负责分配空间并获取对尚未初始化的对象的引用,而invokespecial句柄调用构造函数本身(在内部编译为void名为 的方法<init>,因此是描述符 <init>()V)。

继续前进,堆上的对象分配和表示的内部结构完全是 JVM 特定的。但是,据我所知,每个分配的对象只有一个分配的对象,无论其超类的数量如何。内存中的对象本身具有用于其自身类及其超类的实例字段的空间。它还必须为虚拟方法表留出空间,以便在对对象执行虚拟方法调用(例如 via invokevirtual)时进行虚拟调度。

在内部,Oracle HotSpot JVM 管理称为oops或普通对象指针的东西。您可以在此处阅读有关 HotSpot 内存布局的更多信息。随意浏览 HotSpot 源代码库

于 2012-08-06T23:12:55.473 回答
1

JVM 只为一个对象分配内存(这里是 D)

  1. 内存分配和初始化发生在底部(这里是 D)到顶部(对象)
  2. 初始化/调用构造函数发生在顶部(对象)到底部(此处为 D)

参考 :

http://www.artima.com/designtechniques/initialization.html

于 2012-08-30T11:34:28.223 回答
0

我没有在任何地方读过这篇文章,但这是我的经历。当您调用new D()时,构造函数链开始,它首先创建 anjava.lang.Object然后extends它到 an A,我的意思是在创建Object(这是所有对象的根)之后,通过为 A 的成员(包括字段和方法)添加内存来初始化 A (这是指向某些代码的指针!)。然后它extends到 B 等等。

在扩展过程中,如果方法被覆盖,对象中的方法指针将指向新的代码。

它只是对 D 的一次引用。

于 2012-08-06T23:27:28.973 回答