11

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?

mik01aj
  • 11,928
  • 15
  • 76
  • 119

7 Answers7

14

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 :

Community
  • 1
  • 1
Colin Hebert
  • 91,525
  • 15
  • 160
  • 151
  • Won't this cause `String` to be loaded when you make the method call as it has to evaluate the `String` literal `"java.lang.String"`? – Nate W. Sep 09 '10 at 16:43
  • Well, the code doesn't really works at all, we can't call findLoadedClass() on the default class loader. So consider this as a simple example. – Colin Hebert Sep 09 '10 at 16:45
  • Sure, a contrived simple example, but nonetheless, won't your `if` statement always evaluate to `true`? – Nate W. Sep 09 '10 at 16:47
  • Well, if it would work then it would be always `true` (or explode in a ClassNotFoundException since the literal String wouldn't be understandable :P ). – Colin Hebert Sep 09 '10 at 16:48
  • 1
    "loaded" doesn't mean "initialized". initialization only happens at precise moments defined by JLS3 $12.4.1 – irreputable Sep 09 '10 at 17:11
  • Since you have the top-voted answer, and your original answer does not actually answer the question about class initialization (but your edit sort of does), why not remove your initial incorrect answer? – Luke Hutchison Sep 28 '21 at 12:00
4

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.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • Because this library reads parameters with `System.getProperty` and I need to know whether I can still change them or not. – mik01aj Sep 09 '10 at 19:20
3

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.

Pietro Braione
  • 1,123
  • 8
  • 22
2

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)

dogbane
  • 266,786
  • 75
  • 396
  • 414
2

You can try something like this:

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

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67
0
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())

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

irreputable
  • 44,725
  • 9
  • 65
  • 93
0

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.

Zuko
  • 2,764
  • 30
  • 30
  • Note: this will _only_ work if there is a parameterless constructor available. This is not always the case (if you define one or more constructors with parameters but do not explicitly define a parameterless constructor as well). – Per Lundberg Aug 13 '19 at 11:45