jvm 如何在Java中创建literal.class对象?

r7knjye2  于 7个月前  发布在  Java
关注(0)|答案(2)|浏览(80)

正如我们所知,当类加载器加载Java类X时,将创建一个文字对象X.class。这个对象(即X.class)是否创建?由“新”操作员创建?它是不是在堆内存上创建的?
我试图理解文字对象X.class和它与类加载器的关系,但是弄糊涂了

ssm49v7z

ssm49v7z1#

假设您正在谈论java.lang.Class对象,它实际上是在本机代码中创建的,并且 * 不 * 使用new运算符。

查看一下

如果我们看一下ClassLoader的实现,它使用defineClass方法来创建Class示例,并将其委托给defineClass1defineClass2。这些方法是native,因此是在原生(非Java)代码中实现的。

原生代码

这发生在ClassLoader.c中,然后重定向到jvm.cpp中的JVM_DefineClassWithSource,然后调用jvm_define_class_common
这引用了一个make_local函数,它在术语中引用了JNIHandleBlock::allocate_handle,它似乎用于Java堆**上的分配。

有一个构造函数

java.lang.Class实际上有一个私有构造函数。然而,这并不被使用,它的存在只是为了欺骗JIT并防止开发人员创建Class示例:
不使用此构造函数,它会阻止生成默认构造函数。

// Initialize final field for classLoader.  The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.

由于构造函数从不使用,因此不能使用new关键字创建。

总结

使用Hotspot,示例创建目前在本机代码中进行。即使它没有使用new关键字,它仍然在Java堆上分配。
但是,这部分是特定于JVM的,在其他JVM中可能会有所不同(例如OpenJ9)。

qvsjd97n

qvsjd97n2#

我们知道,当Java类X被类加载器加载时,将创建一个文本对象X.class
这大致是正确的,但你的术语不正确。所创建的是一个Class对象,而不是一个(类)“文字对象”。字面量是Java源代码中的东西。它在运行时 * 表示 * 一个对象,但它不是对象。
这个对象(即X.class)是否创建?
Java运行时创建它。当类装入器装入类时,它将装入并记录各种与类相关的信息(描述符、字节码块等)在 * 元空间 * 中。还创建了一个Class对象,作为程序可见的类的运行时表示。
加载类、表示它们的元数据和创建Class对象的机制都是特定于实现的。你不需要知道细节…而且它们可能在不同的Java版本之间有所不同。
是否由“new”操作符创建?
如果你指的是Java new关键字,那么No。创建将(通常)在本机代码中完成。
它是不是在堆内存上创建的?
这是特定于实现的,但对于当前的实现,答案是肯定的。例如,在Java 17中,java.lang.Class对象是一个堆对象,它是一个名为Klass的本机代码描述符的“java代理”。
“你不需要知道这种细节。即使是JNA / JNI程序员也不需要知道jclass是如何实现的。唯一需要知道这一点的人是那些编写和维护JVM代码库的人。(而如果你只是出于好奇而问,我强烈建议你自己做研究;即通过阅读OpenJDK源代码。

相关问题