Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.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
Java JVM如何在运行时知道对象的类_Java_Jvm - Fatal编程技术网

Java JVM如何在运行时知道对象的类

Java JVM如何在运行时知道对象的类,java,jvm,Java,Jvm,jvm如何知道对象在运行时是哪个类的实例。我知道我们可以使用getClass方法来获取类名,但是getClass方法是如何工作的呢? 谢谢, 我不知道JVM的细节,但是在大多数面向对象语言+运行时系统(Delphi,C++,.NET)中,一个隐藏字段被添加到对象实例数据中,指向对象实例的类型信息。p> 在将对象实例直接映射到外部数据结构时,必须注意这一点,因为对象实例数据中的隐藏类型信息或虚拟方法表指针将与外部数据结构中的字段不对齐 您通常可以通过查看对象实例的大小来查看此工件。Sizeof()

jvm如何知道对象在运行时是哪个类的实例。我知道我们可以使用getClass方法来获取类名,但是getClass方法是如何工作的呢? 谢谢,
我不知道JVM的细节,但是在大多数面向对象语言+运行时系统(Delphi,C++,.NET)中,一个隐藏字段被添加到对象实例数据中,指向对象实例的类型信息。p> 在将对象实例直接映射到外部数据结构时,必须注意这一点,因为对象实例数据中的隐藏类型信息或虚拟方法表指针将与外部数据结构中的字段不对齐

您通常可以通过查看对象实例的大小来查看此工件。Sizeof()或同等产品。没有声明字段的对象的内存占用仍将大于零。这就是类型信息魔法的来源。

答案是什么?魔法


不,说真的,它是实现定义的,JVM的实现不需要使用单一的简单技术,比如将类作为引用存储在实例数据中以恒定偏移量的字段中。它所需要做的就是确保
getClass
方法可以按照文档中的方式工作。例如,使用,JVM可能会在堆上静态分配实例,因为它知道该实例不会超过堆栈框架。在这种情况下,它可以选择将
getClass()
调用转换为
Class
实例的直接加载,而不是方法调用!类似地,由于
getClass()
在逻辑上是一个虚拟方法(我知道它是final的,但它的返回值在任何给定类装入器的类的所有实例中都是常量,但对于每个不同的类都不同,就好像它是一个返回常量值的虚拟方法一样),它可能会进行类似的优化。

正如前面的答案所建议的,没有指定实现

为了了解实现的外观,我研究了最近一个热点JVM的运行时部分。 在Hotspot中,每个对象都以一个标记字(用于GC和其他用途)和一个klass指针开始。 如果调用getClass,Object.c中的本机实现将被调用:

JNIEXPORT jclass JNICALL
Java_java_lang_Object_getClass(JNIEnv *env, jobject this)
{
    if (this == NULL) {
        JNU_ThrowNullPointerException(env, NULL);
        return 0;
    } else {
        return (*env)->GetObjectClass(env, this);
    }
}
GetObjectClass是JNIAPI的一部分。() JNI GetObjectClass的内部实现实际上只是解析对象指针,从类指针读取klass, 并返回该类的Java表示形式:

JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
  JNIWrapper("GetObjectClass");

  HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);

  Klass* k = JNIHandles::resolve_non_null(obj)->klass();
  jclass ret =
    (jclass) JNIHandles::make_local(env, k->java_mirror());

  HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
  return ret;
JNI_END

类文件格式是类定义的序列化格式。它实际上与JVM如何通过
getClass()
方法将任何给定的对象实例与
Class
对象实例连接起来无关。它确实解释了JVM在创建对象时的操作。它的一部分是让类元信息可用,实际上,它不可用。JVM规范只定义似乎发生了什么。例如,它以堆栈机器的形式定义代码的含义;但不需要存在任何实际的堆栈机器,它们在运行时具有相同的逻辑插槽、相同的逻辑值。相反,JVM可能选择JIT所有内容,而不是进行解释。但这个问题与JVM如何在运行时知道堆栈何时可能不存在有关。唯一的答案是,这完全取决于JVM,只要它看起来像文档一样工作。