Java wrt类加载器中的“新”功能是什么?

Java wrt类加载器中的“新”功能是什么?,第1张

Java wrt类加载器中的“新”功能是什么?

这等于

class A {    // ...    A.class.getClassLoader().loadClass("B's canonical

name”).newInstance();
// …
}

不,并非总是如此。

对于给定的名称空间,类加载仅执行一次,除非

Class
之前已卸载了该问题。因此,
A.class.getClassLoader().loadClass("B'scanonical name")
在大多数情况下,等效表达式将仅执行一次。换句话说,如果您有两个表达式-
newA()
loadClass
则将仅执行一次。

JVM将构造函数的调用视为方法调用,但这需要Java编译器的配合。JVM和编译器必须遵守Java虚拟机规范的3.9节,其中规定:

3.9特别命名的初始化方法

在Java虚拟机级别,每个构造函数(第2.12节)都作为具有特殊名称的实例初始化方法出现

<init>
。该名称由编译器提供。因为该名称
<init>

不是有效的标识符,所以不能直接用Java编程语言编写的程序中使用它。实例初始化方法只能由 invokespecial 指令在Java虚拟机内调用
,并且只能在未初始化的类实例上调用。实例初始化方法具有从其获得构造函数的访问权限(第2.7.4节)。

一个类或接口最多具有一个类或接口初始化方法,并通过调用该方法进行初始化(第2.17.4节)。类或接口的初始化方法是静态的,不带参数。它有特殊的名字

<clinit>
。该名称由编译器提供。因为该名称
<clinit>
不是有效的标识符,所以不能直接用Java编程语言编写的程序中使用它。Java虚拟机隐式调用类和接口初始化方法。绝对不能从任何Java虚拟机指令直接调用它们,而只能在类初始化过程中间接调用它们。

本节假定

Class
与该类有关的对象可用于当前线程。一旦
Class
对象是可用的,该方法
<init>
对应于与右组参数的构造,将被调用。

使用哪个类加载器加载类(如果尚未加载)的问题有些不同,并且与new关键字无关。它取决于一个类如何引用另一个类,即是否需要在运行时常量池中解析符号引用?Java虚拟机规范的第5.3节定义了这种情况下的行为:

5.3创建和加载

用名称N表示的类或接口C的创建包括Java虚拟机的方法区域(第3.5.4节)中特定于实现的内部C表示的构造。类或接口的创建由另一个类触发或接口D,它通过其运行时常量池引用C。

Java虚拟机使用以下三个过程之一来创建由N表示的类或接口C:

  • 如果N表示非数组类或接口,则使用以下两种方法之一来加载并创建C:

    • 如果D由引导类加载器定义,则引导类加载器将启动C的加载(第5.3.1节)。

    • 如果D是由用户定义的类加载器定义的,则该用户定义的类加载器将启动C的加载(第5.3.2节)。

  • 否则,N表示数组类。数组类是由Java虚拟机(第5.3.3节)而不是由类加载器直接创建的。但是,在创建数组类C的过程中使用D的定义类加载器。

注意

If D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C
上面引用中的句子。在表达式的上下文中
newA()
,加载了封闭类的类加载器将
A
根据VM Spec 进行加载;当然,假设引导类加载器未加载该封闭类。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5106239.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存