如何检查一个类是否已初始化?

发布于 2024-09-18 10:16:06 字数 137 浏览 9 评论 0原文

您可能会问,为什么我要这样做 - 这是因为我正在使用一个类(来自外部库),该类在其静态初始化程序中执行操作,并且我需要知道它是否已完成。

我查看了 ClassLoader,但没有找到任何看起来有用的东西。有什么想法吗?

You'll probably ask, why would I want to do that - it's because I'm using a class (from an external library) which does stuff in its static initializer and I need to know whether it's been done or not.

I looked at ClassLoader, but didn't find anything that looked useful. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

指尖微凉心微凉 2024-09-25 10:16:06

您可以使用ClassLoader.findLoadedClass()方法。如果它返回 null,则该类未加载。这样,如果该类尚未加载,则不会加载该类。


警告:这段代码在这里不起作用,在系统ClassLoader中,findLoadedClass()是受保护的,你需要用自己的ClassLoader覆盖它。

检查下面的链接同一主题,检查类是否已使用系统 ClassLoader 加载

if(ClassLoader.getSystemClassLoader().findLoadedClass("java.lang.String") != null){
    System.out.println("Yepee, String is loaded !");
}

@irreputable 的观点非常好:

“已加载”并不意味着“已初始化”。初始化仅发生在 JLS3 $12.4.1 定义的精确时刻

,我引用:

类或接口类型T将在第一次出现以下任一情况之前立即初始化:

  • T 是一个类,并且创建了 T 的实例。
  • T 是一个类,并且调用 T 声明的静态方法。
  • 分配了 T 声明的静态字段。
  • 使用T声明的静态字段,并且该字段不是常量(§4.12.4)
  • T 是一个顶级类,以及一个 assert 语句 (§14.10) 词法嵌套在 T 中的内容被执行。

调用类Class和包java.lang.reflect中的某些反射方法也会导致类或接口初始化。在任何其他情况下都不会初始化类或接口。


资源:

同一主题:

You can use the ClassLoader.findLoadedClass() method. If it returns null, then the class isn't loaded. This way you don't load the class if it wasn't already loaded.


WARNING : This code doesn't really work here, in the system ClassLoader, findLoadedClass() is protected, you need to override it with your own ClassLoader.

Check the link below On the same topic to check if a class is loaded with the system ClassLoader

if(ClassLoader.getSystemClassLoader().findLoadedClass("java.lang.String") != null){
    System.out.println("Yepee, String is loaded !");
}

Very good point from @irreputable :

"loaded" doesn't mean "initialized". initialization only happens at precise moments defined by JLS3 $12.4.1

And I quote :

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.

Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.


Resources :

On the same topic :

水水月牙 2024-09-25 10:16:06

为什么不直接引用该类(通过创建引用、创建实例或访问静态成员)?如果类型初始值设定项尚未触发,这将启动类型初始值设定项,如果已触发,那么您仍然可以继续。

Why don't you just reference the class (by creating a reference, creating an instance, or accessing a static member)? That will kick off the type initializer if it hasn't already fired and if it has then you are still good to go.

烏雲後面有陽光 2024-09-25 10:16:06

我知道已经很晚了,但我认为这个答案可能有用。如果您不太害怕(并且可以)使用 sun.misc.Unsafe 类,则有一个方法可以准确地执行此操作:该方法

sun.misc.Unsafe.shouldBeInitialized(Class)

返回 true 当且仅当作为参数提供的Class 已(已加载但)未初始化。

I know it is very late, but I think this answer might be useful. If you are not too scared (and you are allowed) to use the sun.misc.Unsafe class there is a method that precisely does that: The method

sun.misc.Unsafe.shouldBeInitialized(Class)

returns true if and only if the Class provided as parameter is (loaded but) not initialized.

或十年 2024-09-25 10:16:06

你可以尝试这样的事情:

Class c = new ClassLoader() { Class c = findLoadedClass(className); }.c;

You can try something like this:

Class c = new ClassLoader() { Class c = findLoadedClass(className); }.c;

复古式 2024-09-25 10:16:06

您可以使用 -verbose 标志让 JVM 在加载类时打印出类。这可能对你有帮助。

java -verbose Dummy|head
[Opened C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.String from C:\Program Files\Java\jre6\lib\rt.jar]

(顺便说一句,刚刚在 Hello World 程序上尝试过,它加载了 309 个类!哇)

You can get the JVM to print out classes as it loads them, using the -verbose flag. This might be of help to you.

java -verbose Dummy|head
[Opened C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre6\lib\rt.jar]
[Loaded java.lang.String from C:\Program Files\Java\jre6\lib\rt.jar]

(btw, just tried this on a Hello World program and it loaded up 309 classes! wow)

最舍不得你 2024-09-25 10:16:06
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())

它将阻塞,直到类被初始化(由它自己或其他线程)

Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())

It will block until the class has been initialized (by itself or some other thread)

寄人书 2024-09-25 10:16:06

如果还不算太晚的话......这应该可以正常工作,

 Class.forName().newInstance();

newInstance() 创建一个由此 Class 对象表示的类的新实例。该类被实例化,就像通过带有空参数列表的新表达式一样。如果该类尚未初始化,则对该类进行初始化。

If its not too late.. This should work fine as well

 Class.forName().newInstance();

the newInstance() creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文