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?
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 :
Javadoc - ClassLoader.findLoadedClass()
Internals of Java Class Loading
JLS - §12.4.1 When Initialization Occurs
On the same topic :
In Java, is it possible to know whether a class has already been loaded?
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.
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.
You can try something like this:
Class c = new ClassLoader() { Class c = findLoadedClass(className); }.c;
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)
Class.forName("com.abc.Xyz", true, this.getClass().getClassLoader())
It will block until the class has been initialized (by itself or some other thread)
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.
Related
According to the Java 8 Language Spec §15.8.2 (quote):
[...]
A class literal evaluates to the Class object for the named type (or for void) as defined by the defining class loader (§12.2) of the class of the current instance.
[...]
Mainly, 'the Class object' insinuates that this is or should be a singleton. Also §12.2 says:
[...]
Well-behaved class loaders maintain these properties:
Given the same name, a good class loader should always return the same class object.
[...]
In fact, using Java 8*, the following** prints true and true:
class Main {
public static void main(String[] args) {
Main main1 = new Main();
Main main2 = new Main();
System.out.println(main1.getClass().equals(main2.getClass()));
System.out.println(main1.getClass() == main2.getClass());
}
}
Is the class loader always 'well-behaved' and why (not)? In other words: are Class instances singleton? The other way around: can a Class of the same type be a different instance?
Notes: I do not refer to the singleton pattern here. However, if the Class implementation follows that pattern, that would be interesting. As a side-step, but by no means the main question: because the singleton pattern's legitimate uses are point of debate, would Java's Class be a good candidate to apply the singleton pattern to?
*:
$ java -version
openjdk version "1.8.0_262"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_262-b10)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.262-b10, mixed mode)
**: my IDE even warns me that the printed expressions are always true.
You are using the term singleton incorrectly.
A singleton implies the existence of only one object of its own class. A Class object is an instance of the class java.lang.Class and there is more than one instance of this class. It’s actually impossible to have only one Class object, as the existence of a Class object does already imply the existence of at least two classes, java.lang.Object and java.lang.Class, so there must be at least two Class objects in the runtime.
Your example is not capable of spotting whether the class loader is well behaved or not. You already mentioned JLS §12.2
Well-behaved class loaders maintain these properties:
Given the same name, a good class loader should always return the same class object.
If a class loader L1 delegates loading of a class C to another loader L2, then for any type T that occurs as the direct superclass or a direct superinterface of C, or as the type of a field in C, or as the type of a formal parameter of a method or constructor in C, or as a return type of a method in C, L1 and L2 should return the same Class object.
A malicious class loader could violate these properties. However, it could not undermine the security of the type system, because the Java Virtual Machine guards against this.
Mind the last sentence. A JVM will guard against violations of these requirements. With the repeated occurrences of the same symbolic references within your example code, there are two possibilities
The JVM remembers the result of the first resolution of this symbolic reference within this context and just reuses it on the next occurrence without asking a class loader again.
The JVM remembers the result of the first resolution of this symbolic reference within this context and compares it with the result of subsequent resolutions of the same reference and throws an error if they mismatch.
Since both approaches imply remembering the result, the first approach is usually used when it comes to resolving the same reference within the same context, as it is simpler and more efficient. When it comes to different symbolic references that resolve to classes using the same reference, the JVM will indeed throw an error when the class loader constraints are violated.
So expressions like Main.class == Main.class or new Main().getClass() == new Main().getClass() will never evaluate to false. Most likely, the resolution of the symbolic reference to Main will go a short-cut, using the same runtime class regardless of what the class loader would do. But even when it does not take the short-cut and the ClassLoader is misbehaving, returning a different class object for the next query, the JVM would detect it and throw an error, so the expression would not evaluate to a boolean result at all. In neither case could it result in false.
In a single classloader, the Class object is the same.
Is the class loader always 'well-behaved' and why (not)?
It really depends on the implementation. If it is done deliberately that always the classloader always returns a new Class-Object, it won't be well-behaved.
At least all classloaders of OpenJDK are well-behaving.
In other words: are Class instances singleton? The other way around: can a Class of the same type be a different instance?
In one single classloader, every Class instance is a singleton. With multiple classloaders, following will evaluate to false:
ClassLoaderA.getInstance().loadClass("foo.Bar")==ClassLoaderB.getInstance().loadClass("foo.Bar");
The other way around: can a Class of the same type be a different instance?
Only if loaded by two different, conforming,well-behaved classloaders.
As a side-step, but by no means the main question: because the singleton pattern's legitimate uses are point of debate, would Java's Class be a good candidate to apply the singleton pattern to?
This is quite opinion-based, but I think, it's no good candidate to apply the singleton pattern, as most singletons are implemented like this:
class Foo{
public static final Foo INSTANCE=new Foo();
private Foo(){
ìf(INSTANCE!=null)
throw new IllegalAccessException("No Foo instances for you!");
}
}
So more that it is really ONE object of a Class, many that only differ by some small things like a different Classloader.
I have the below method in class A. All classes A,B,C and the main class from which 'A' is invoked are in the same jar.
public class A {
private static void init() {
if (!init) {
synchronized (B.class) {
if (!init) {
map = C.creat();
init = true;
}
}
}
}
}
The code is throwing a Throwable, java.lang.NoClassDefFoundError at the synchronized block (Line no.4).
What can be the reason as all the classes are in the same jar, there is no chance for not finding a class during run time.
I have gone through the solution in Existing Question but could not find a solution. Please help.
There are static initialization blocks and static variables in class B.
The issue can be fixed, if I use a static object/class A to Synchronize the piece of code instead of 'B'. I am curious to know why i faced the exception and how to fix it using class B only.
If you really compiled that code into a JAR; and that JAR contains B.class; then this can't happen.
The only options are: the JAR you are using got corrupted; or it doesn't contain what you assume it should contain.
Thus: verify your JAR. Something must be wrong about it. For example, use jar tf jarfile.jar to list the complete content; and check if B.class is really in.
Classes object or the metadata are loaded by the classloaders while bringing launching the Java App.
The above code may end up in the java.lang.NoClassDefFoundError due to the following.
1> The above static method init is invoked from within a static block in class A. It may happen that the class B is still not loaded before class A and the classloader tries to get lock on the class object (metadata) of class B and fails to find the definition of the class.
It works if you syncronise on A.class because the classloader has the class meta reference of it
In order to make work with class B.class you may have to lazily invoke the init method in class A and allow the classloader to load the meta information of the classes. Please avoid invoking the init() method in the class A from any static initializer block.
Had anything referred to any method or variable in B prior to the use of B.class? If not, then B has not, repeat, not been initialized. Reference to the class literal does not trigger class initialization. "Static block" is an incorrect term. It's "static initializer block". Which didn't get run.
Use a final Object member of either A or B to synchronize, not the class literal.
When I read the documentation about Class, as to forName() method, the documentation said:
Class.forName ("Foo")
is equivalent to:
Class.forName ("Foo", true, this.getClass().GetClassLoader())
I don't know what the meaning of this.getClass().GetClassLoader() and why it works in this way, I just know it is a ClassLoader to load class when JVM complier the code.
A ClassLoader is an object capable of loading bytecode as a class into the VM. See here for the offical docs.
Class.forName(String name) allows you to load a class at runtime - the supplied String can by determined at runtime. To actually load a class one needs a ClassLoader thus it was chosen that the ClassLoader the class of the calling object was loaded with is the default one. You access that ClassLoader with this.getClass().getClassLoader().
The second parameter - defaulting to true - determines if static intialization is performed for the class if necessary (if it hasn't been performed earlier).
class.forName returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
Is it possible to define my own String class which has the exact same name as java.lang.String? My assumption is that after I have defined it, I can use it directly or load it with a class loader.
Sorry, the code I wrote has a mistake. The String class of the parameter String[] args of the method main() was incorrectly referenced to my own defined String. That is why it occured a compile error.
My working result is that we can define a class named String in my own namespace or java.lang. But since JVM has loaded the default java.lang.String, we can't load our own String and use it.
Yes, you can define that class, but you won't be able to use it. The class java.lang.String will be loaded out of the JRE at bootstrap, and you can't reload a class in the bootstrap classloader. If you try to use your own classloader, the JVM will notice that java.lang.String is already loaded and just use that one.
From the JLS section on class loading:
Given the same name, a good class loader should always return the same class object. (This means that the java.lang.String class that gets pulled in a bootstrap will be the authoritative class.)
If a class loader L1 (the bootstrap loader) delegates loading of a class C to another loader L2 (your own loader), then for any type T (java.lang.String) that occurs as the direct superclass or a direct superinterface of C, or as the type of a field in C, or as the type of a formal parameter of a method or constructor in C, or as a return type of a method in C, L1 and L2 should return the same Class object. (Your own java.lang.String would be conflicting with all of the parameters and fields in anything else loaded by the bootstrap loader and would cause virtually anything past the loading of your rogue class to come crashing down with link or cast errors.)
What exactly are you trying to do, anyhow? java.lang.String has very strictly defined semantics, and changing its behavior at all would break an enormous amount of code.
We can get class Class object by 3 methods:
MyClass.class
obj.getClass
Class.forName("className")
I don't understood the difference between: MyClass.class and Class.forName("className").
Because both will need Class Name.
Class.forName("className");
forName is a static method of class "Class".
we require to provide the fully qualified name of the desired class.
this can be used when name of class will come to known at runtime.
ClassName.class;
.class is not a method it is a keyword and can be used with primitive type like int.
when Name of Class is known in advance & it is added to project, that time we use ClassName.class
I don't understood the difference between: MyClass.class and Class.forName("className").
Because both will need Class Name.
The big difference is when they need it. Since Class.forName accepts a string, the class name can be determined at runtime. Whereas of course, MyClass.class is determined at compile-time. This makes Class.forName useful for dynamically loading classes based on configuration (for instance, loading database drivers depending on the settings of a config file).
Rounding things out: obj.getClass() is useful because you may not know the actual class of an object — for instance, in a method where you accept an argument using an interface, rather than class, such as in foo(Map m). You don't know the class of m, just that it's something that implements Map. (And 99% of the time, you shouldn't care what its class is, but that 1% crops up occasionally.)
Class.forName("className");
It dynamically load the class based on fully qualified class name string.
obj.getClass
Returns the java.lang.Class object that represents the runtime class of the object.
MyClass.class:
A class literal is an expression consisting of the name of a class, interface, array,
or primitive type, or the pseudo-type void, followed by a'.' and the token class.
The type of C.class, where C is the name of a class, interface, or array type is Class<C>.
http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf
One important difference is:
A.class will perform loading and linking of class A.
Class.forName("A") will perform loading, linking and initialization of class A.