I was reading this article,and it says that :
If we have two instances of Student class loaded by these CustomClassLoaders say student1 and student2, then student1 and student2 are not type-compatible. In other words,
Student student3 = (Student) student2;
will throw ClassCastException, because the JVM sees these two as separate, distinct class types, since they are defined by different ClassLoader instances.
Now I understand what it wants to convey:that is if we load same class by using two different class loader then then they will not be type compatible.So far so good.
But the example it has used is what confusing me, ie
Student student3 = (Student) student2;
Isn't it that when we declare a reference variable like Student student ,all what compiler looks for is that this Studnet is present at its proper location in compliance with its package structure.Now when at run time we assign this reference variable to a real loaded class,does it really matter which class loader we use to load the said class?I doubt ,because from my understanding,a class loader comes into play only when we do a 'new' or we call a static field on it and not when we simply declare a type of it.
Please clarify me on this and help me rectify my understanding in this regards.
Thanks, Mawia
There can be multiple classloaders in a normal Java program. The one that loads your main class, ClassLoader , is the default one, and from your code, you can create and use as many classloaders as you like.
When the JVM is started, three class loaders are used: Bootstrap class loader. Extensions class loader. System class loader.
A class is always identified using its fully qualified name (package. classname). So when a class is loaded into JVM, you have an entry as (package, classname, classloader). Therefore the same class can be loaded twice by two different ClassLoader instances.
So why three class loaders? Because they represent three levels of trust. The classes that are most trusted are the core API classes. Next are installed extensions, and then classes that appear in the classpath, which means they are local to your machine.
That is mostly correct but when the assignment happens, the JVM needs to make sure it's correct. So it checks: Can I assign the right hand side (RHS) to the left hand side (LHS).
The rules say that this is allowed when you can downcast the runtime type of the RHS to the type of the LHS.
So at compile time, the code above looks OK. But at runtime, the call isAssignableFrom()
returns false because the the two types are different.
The method equals()
in Class
returns true
if the qualified names are equal and when the classloader is the same. That's why you get a ClassCastException
in this case.
The methods used are implemented as native code, so you can't see what is happening. But the methods isInstance()
and isAssignableFrom()
only return true when the classloader for both classes is the same.
Yes, at runtime it really does matter which class loader did load a class. And the class loader is inspected every time a class has to be loaded. That is not only when a new
or a static field is encountered. That happens every time there the class name appears in the Java code, or to be more precise, when a class name is referenced in the byte code and the byte code is executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With