存储在内存中的类的定义与实例相对应的位置在哪里?

时间:2012-10-08 06:31:57

标签: oop memory-management

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

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

在OO源代码中定义和对象时,例如在Java中,没有实例化它:

String s;

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

s = new String("abc");

?是否存在适用于所有OO语言的一般原则,如何分配内存或不同的语言实现者使用不同的技术来分配内存?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分: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

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

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

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

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

  • 它依赖于依赖项表中的类java.lang.String
  • “字符串文字表格中的”abc“
  • 您的方法按ID
  • 加载字符串文字
  • (在第一种情况下)您的方法使用第一个依赖类(String)作为参数调用其第一个依赖类(String)的构造函数。
  • 编译器可以证明将新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 ++暂时没有类型检查机制。