Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 与实例相反,存储在内存中的类的定义在哪里?_Oop_Memory Management - Fatal编程技术网

Oop 与实例相反,存储在内存中的类的定义在哪里?

Oop 与实例相反,存储在内存中的类的定义在哪里?,oop,memory-management,Oop,Memory Management,这个问题只是出于兴趣,并试图了解一些面向对象语言中的内存管理。这不是一种特定的语言,但我只想作为一个一般原则来理解 我想知道的是,与对象引用的实例相比,对象引用的定义是如何存储的 当您在OO源代码(例如Java)中定义和对象而不实例化它时: String s; 这是如何存储的?此定义的内存使用情况与实际实例化对象时的内存使用情况有何不同: s = new String("abc"); ??在如何分配内存方面,是否有一个适用于所有OO语言的一般原则,或者不同的语言实现者是否使用不同的技术来分配

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

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

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

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

s = new String("abc");

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

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

,在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++没有一段时间的类型检查机制。