0

这个问题只是出于兴趣,并试图了解面向对象语言中的内存管理。它不是特定于一种语言的,但我只是想理解为一般原则。

我想知道的是,与该引用的实例相比,对象引用的定义是如何存储的。

当您在 OO 源代码中定义和对象时,例如在 Java 中,而不实例化它:

String s;

这是如何存储的?此定义的内存使用情况与实际实例化对象时有何不同:

s = new String("abc");

? 就内存分配方式或不同语言实现者使用不同技术分配内存而言,是否有适用于所有 OO 语言的一般原则?

4

2 回答 2

0

通常,当我们声明像String s 这样的引用时;它被创建为一个普通变量,就像 int , float 但是这种类型的变量保存内存地址(它类似于 C 语言中的指针的概念)但是当我们使用 s = new String("abc"); ,它在堆中创建一个对象并将该地址分配给引用变量s

于 2012-10-08T06:41:52.973 回答
0

在 Java 字节码中,所有对象都存储为对象。需要时添加显式类型检查。例如这个Java函数

public Integer getValue(Object number){
  int i = ((Number) number).toInt();
  return new Integer(i);
}

被翻译成这样的字节码:

(accepts java.lang.Object, returns java.lang.Integer)

-read the first argument as an Object
-if the value is not a Number, raise an exception
-call the virtual method toInt(java.lang.Integer) of the value
    and remember the int result
-use the value as an int argument
-instantiate a new java.lang.Integer
-call the constructor(int) of java.lang.Integer on the new number,
    getting an Object back
[since the declared return value of Number.toInt is the same
    as the return value of our function, no type checking is needed]
-return the value

因此,编译器会去除未使用的变量类型。公共和受保护字段的类型与其类一起存储。

对象的运行时类型与对象一起存储。在 C++ 中,它是指向虚拟方法表的指针。在 Java 中,它是所有已加载类表的 16 位索引。

Java 类文件将所有依赖类的索引存储在一个类似的表中。这里只存储类名。然后所有字段描述都指向该表。

因此,当您编写String s = new String("abc")(甚至String s = "abc")时,您的班级会存储:

  • 它依赖于依赖表中的类 java.lang.String
  • 字符串文字表中的“abc”
  • 您的方法按 ID 加载字符串文字
  • (在第一种情况下)您的方法调用其第一个依赖类(String)的构造函数,并将第一个依赖类(String)作为参数。
  • 编译器可以证明将新字符串存储在字符串变量中是安全的,因此它会跳过类型检查。

一个类可以在被引用后立即加载,或者在第一次使用时加载(在这种情况下,它由其依赖的类和类中的 ID 引用)。我认为后者现在总是如此。

加载类时:

-its class loader is asked to retreive the class by its name.
-(in the case of the system loader) the class loader looks
    for the corresponding file in the program JAR, in the system library
    and in all libraries referenced.
-the byte stream is then decoded into a structure in memory
-(in the case of early loading) all dependent classes are loaded recursively
    if not already loaded
-it is stored in the class table
-(in the case of late loading) its static initialiser is run
    (possibly loading more classes in the process).

在 C++ 中,不会发生任何类加载,因为所有用户类和大多数库都作为单纯的虚拟方法表和相应的方法存储在程序中。所有系统函数(不是类)仍然可以存储在 DLL(在 Windows 的情况下)或类似文件中,并在运行时由库加载。如果显式类型转换隐含类型检查,则在虚拟方法表上执行。另请注意,C++ 有一段时间没有类型检查机制。

于 2012-10-08T08:41:33.790 回答