内存中引用变量和对象的逻辑结构/细节?
假设我们有一个class级:
class Class1 { int i = 1; }
我们有一个变量:
Class1 ob1 = new Class1();
- 存储在变量
ob1
的引用本身是否存储它引用Class1
对象的信息? - 存储
Class1
的堆的部分是否存储了Class1
类型的信息? - 逻辑上看起来如何看待这些信息? 它是一个像application1.Class1这样的字符串或对某些引用类型池的引用?
如果您可以推荐这些信息的来源,我将非常感谢提供它,我在参考书中找不到它。
存储在变量ob1中的引用本身是否存储它引用Class1对象的信息?
不 。 引用变量ob1
仅存储它指向的对象的引用。 有关该对象的信息已为应用程序(或JVM)所知。
存储Class1的堆的部分是否存储了Class1类型的信息?
不 。 有关正在加载的类的信息存储在方法区域中 。 如此链接中所指定
对于它加载的每种类型,Java虚拟机必须在方法区域中存储以下类型的信息:
- 类型的完全限定名称
- 类型的直接超类的完全限定名称(除非类型是接口或类java.lang.Object,它们都没有超类)
- 类型是类还是接口
- 类型的修饰符(`public,abstract,final的某个子集)
- 任何直接超接口的完全限定名称的有序列表
逻辑上看起来如何看待这些信息? 它是一个像application1.Class1这样的字符串或对某些引用类型池的引用?
在Java类文件和Java虚拟机中,类型名称始终存储为完全限定名称 。 例如,包java.lang中的类Object的完全限定名称表示为java / lang / Object 。 在方法区域中,完全限定名称可以用设计者选择的任何forms和数据结构表示。
每个java对象引用都在运行时知道它的类; 这个所谓的“运行时类型信息”在这样的代码中使用:
if (obj instanceof class1) { // true! }
您还可以通过obj.getClass()
访问对象的类。 这将返回class1.class
,类Class
的对象。 请参见Object.getClass方法。
(注意,如果您的类被参数化,作为class1
,由于“擦除”, T
的类型将不会在运行时存储。)
我不知道类信息是用指针存储还是与数据一起存储; 它可能在jvm中特定于实现; 但从实际的角度来看,这几乎不重要。 (所以要么回答1或2,要么两者都是“是”)。
3的答案是,就java程序员而言,运行时类型信息被封装在类Class
的对象中。 在幕后,JVM可以以这种或那种方式实现这一点。
回答你的问题:
-
不,它没有 。 引用只是一个引用,即堆中的某个地址,其中存储了相应的对象。 不需要在引用本身中存储关于引用类型的重复信息,因为实际上包含其引用地址的实数变量可以是各种类类型。
-
很奇怪的问题。 当然, 是的,确实如此 。 此外,这个“堆的一部分”是一个对象,它包含这个特定的类描述。 任何
Class
对象都包含有关该类的全名的信息,该类由其描述。 -
如果你的意思是它的结构,它没有被定义为逻辑上看起来如何:
2.7物体的表示:
Java虚拟机不强制要求对象的任何特定内部结构。
但是如果我们讨论有关类类型的信息 – 是的,它只是一个String
对象,因为Class
对象的“类型”(它代表它)只是相应类的名称。
这是JVM可以使用instanceOf
在运行时为检查存储类的信息的方案之一。
只有对象的引用,每个Java虚拟机都必须能够确定有关其类的信息。 这需要很多原因,包括类型安全的转换和instanceof运算符。
这是Java虚拟机实现可以将类信息与对象的实例数据相关联的一种方式。 在该图中,包含类信息的数据结构的本机指针与对象的实例变量一起存储。 JVM可以将对象数据与其类信息连接的各种方式的详细信息超出了本文的范围。 这里要理解的重要一点是,类信息将以某种方式与对象的实例数据相关联,并且实例数据包括对象类及其所有超类的字段。
Artima发布对象初始化
因此,当您执行instanceOf
检查时,通过此指针访问有关该类的信息。 但请记住,关于类信息存储的确切实现可能是特定于实现的。