When does Class#getClassLoader return null? - java

Say I have some Java code:
public class Widget {
...whatever
}
And some code that classloads the Widget:
ClassLoader widgetLoader = Widget.class.getClassLoader();
Can widgetLoader ever be null? Why/why not? If so, under what circumstances?

According to this method javadoc:
Returns the class loader for the class. Some implementations may use
null to represent the bootstrap class loader. This method will return
null in such implementations if this class was loaded by the bootstrap
class loader.

Related

How to understand "Every Class object contains a reference to the ClassLoader that defined it. "?

I know I can get a the classloader of a class by
xxxclass.class.getClassLoader(), but where exactly does the xxxclass
hold the reference of its classloader who defines it?
e.g.
public class ClassA {
System.out.println("I am class A");
}
I don't see any clue of the classloader reference in ClassA. However,
I can get the classloader of ClassA by using
ClassA.class.getClassLoader().
How does ClassA.class.getClassLoader() work?
The sentence as it appears in the documentation of ClassLoader is:
Every Class object contains a reference to the ClassLoader that defined it.
Note the two links? What they tell you is that the documentation refers to the Class object, not to the plain object of class ClassA.
Every class that you define in Java has a Class object associated with it, which allows you to look at that class in the meta level. That is, treat the class itself as an object, pass it as parameter, use reflection on it etc.
As you have noticed, one way to access the Class object is use ClassA.class. If you have a reference to an object of type ClassA:
ClassA myObj = new ClassA();
Then you can get the Class object using myObj.getClass().
So there is no reference to the ClassLoader in the myObj object, Only in its associated Class object.
Now, the other link tells you how to get the reference to the ClassLoader object once you have a Class object - through the getClassLoader() method.
Now, if you look at the source code of the Class class, you will see:
#CallerSensitive
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
So it calls getClassLoader0() to get the class loader. Its source is:
native ClassLoader getClassLoader0();
That is, the class loader reference is actually part of the native structure of this Java class, and it is not available to see using Java language tools. Nevertheless, it exists there, and available to you through the aforesaid method.
If you write this:
public class Ball {
private Person thrower;
public Ball(Person thrower) {
this.thrower = thrower;
}
public Person getThrower() {return thrower;}
}
then every Ball object contains a reference to the Person that threw it, right?
Similarly, the Class class has something like this: (although I'm not showing how classLoader gets assigned)
public class Class {
... other stuff ...
private ClassLoader classLoader;
public ClassLoader getClassLoader() {return classLoader;}
... other stuff ...
}
and so every Class object has a reference to the ClassLoader that loaded it.
In your example, ClassA is not a Class object, so the statement doesn't apply to it. It does apply to ClassA.class which is a Class object (or refers to one at least).
In fact, it's not so simple in this case.
(Or at least, it was not so simple, until a recent update)
Java is a very high-level language, and the JVM is a rather complex beast, which is (fortunately!) hiding many details that you don't want to be concerned with when using a high-level, object-oriented language.
As already pointed out in the other answers, the Class#getClassLoader() method delegates to a private native method getClassLoader0(). Usually, you simply don't know (and should not have to care about) what a private native method does.
But thanks to the open source JDK, one can trace the path of this method call (here, for a recent version of the JDK8) :
The native getClassLoader0 method of Class is bound to JVM_GetClassLoader
The JVM_GetClassLoader method eventually calls Klass::class_loader()
The Klass::class_loader() method only returns the result of ClassLoaderData::class_loader()
The ClassLoaderData::class_loader() method finally returns the field that you are looking for
However, note that this has changed in a recent commit of the JDK9: Now, the ClassLoader is stored as a private instance field in the Class class, in order to improve performance.
If you look at the source code of java.lang.Class it appears that it delegates to a native method called getClassLoader0. So the implementation details are down to the JVM.
I'm no expert on this, but I suppose this might allow garbage collection to work by not having reference cycles in Java.

Difference static behaviour between MyClass.class and Class.forName(“MyClass”)

I'm not sure what's the difference of loading static variables/blocks between MyClass.class and Class.forName("MyClass"), for example, I have below class:
package test;
public class SampleClass{
public static SampleClass instance = new SampleClass();
private SampleClass(){
System.out.println("SampleClass Instance Created");
}
}
Then, in another class, I accessed the class object of above SampleClass by using:
System.out.println(SampleClass.class);
Then, the output will be:
class test.SampleClass
If I changed to use class.forName(), as below:
System.out.println(Class.forName("test.SampleClass"));
Then, the output will be:
SampleClass Instance Created
class test.SampleClass
Does anybody can give me an explanation?
Thanks a lot.
The call to the Class.forName("MyClass") causes the class to be loaded at runtime. JVM also initializes that class after the class has been loaded by the classloader, so static blocks get executed.
In your case you have a static field which is the instance of your class, as this static block get executed your object is being initialized. That's why you are seeing the System.out get printed.
The .class syntax is used to get the Class of the called class. It doesn't not load the class actually.
Reference:
What does Class.forname method do?
Java Doc
Retrieving Class Object
Class.forName() uses the ClassLoader and tries to resolve class name at runtime, while .class is resolved at compile time.
class.forName() loads the class using the "caller's" class loader if the class is not already loaded.
.class doesn't load the class.
Its is just because of Class.forName() is dynamically loaded at run time your class into memory(RAM). and it will execute all static block within this class without creating reference of that class,
From offical doc:
A call to Class.forName("X") causes the class named X to be dynamically loaded (at runtime). A call to forName("X") causes the class named X to be initialized (i.e., JVM executes all its static block after class loading). Class.forName("X") returns the Class object associated with the "X" class. The returned Class object is not an instance of the "x" class itself.
Class.forName("X") loads the class if it not already loaded. The JVM
keeps track of all the classes that have been previously loaded. This
method uses the classloader of the class that invokes it. The "X" is
the fully qualified name of the desired class.
here is more information about it: http://www.xyzws.com/Javafaq/what-does-classforname-method-do/17
Thank you all above for your answers and discussions.
I thought the class will be loaded no matter using Class.forName() or MyClass.class, obviously I'm wrong. But I don't understand why it doesn't load the class when using MyClass.class.

Java ClassLoader not caching the class

I am trying to force some of the classes to be loaded using my custom class loader, the problem is after the loading the calling class still doesn't know about the class definition and tries to load it again, of course after that we have two different definitions of the class and assigning one to the other results in class cast exception.
Any pointers or ideas how this can be fixed?
This is the calling class:
CustomClassLoader loader = new CustomClassLoader(this.getPackageCodePath());
Class<?> midletClass = loader.loadClass(className);
midletClass.getMethod("InitEngine", Class.forName("android.app.Activity")).invoke(null, this);
ms_MIDlet = (MIDlet)midletClass.newInstance();//ClassCastException
And this is the class loader itself
public class CustomClassLoader extends PathClassLoader
{
public CustomClassLoader(String path)
{
super(path, getSystemClassLoader());//we set the parent to be the system class loader so the loading gets done in this class
}
#Override
public InputStream getResourceAsStream(String resName)
{
//...do some resource loading here
}
}
The calling class is running in some ClassLoader A. This classloader knows where to find and load MIDlet.class. Otherwise line 4 would produce a ClassNotFoundException for the cast.
You also use an instance of CustomClassLoader to load the Midlet.class.
On line 4 this blows up because you are casting the Midlet instance loaded by CustomClassLoader to a Midlet instances loaded by the ClassLoader A.
One solution is to make the CustomClassLoader logic delegate to ClassLoader A before loading a class itself. Something along the lines of first delegating a loadClass call to parentLoader.loadClass or getResourceAsStream to parentLoader.getResourceAsStream. If those calls fail then you can do your custom resource lookup.
This approach will make sure that all Midlet.class'es are actually loaded by the same classloader. You can check the delegation example at Java ClassLoader delegation model?

Class & ClassLoader

I have a Custom Classloader : CustomClassLoader(extends ClassLoader)
I have a class : IntegerPrint
I load my class with my Custom ClassLoader. I was expecting SOPs in the below code to return the same value. But the first SOP prints "sun.misc.Launcher$AppClassLoader#.." & second SOP prints "CustomClassLoader#.."
Why it happens so? Please advise.
public class IntegerPrinterTest {
public static void main(String[] args) throws Exception {
CustomClassLoader loader = new CustomClassLoader(IntegerPrinterTest.class.getClassLoader());
Class<?> clazz = loader.loadClass("IntegerPrinter");
System.out.println(IntegerPrinter.class.getClassLoader());
System.out.println(clazz.getClassLoader());
}
}
What did you expect?
In
System.out.println(IntegerPrinter.class.getClassLoader());
you create a
Class<IntegerPrint>
object, and surely, its class (Class) must have been loaded by some class loader. It takes no genius to imagine that Class must have been loaded very early, even before your code even gains control.
Please run your example with
java -verbose:class ....
to see which classes are laoded in what order.
The first call:
IntegerPrinter.class.getClassLoader()
Will actually do:
IntegerPrinterTest.class.getClassLoader().loadClass("IntegerPrinter")
So it totally ignores your custom classloader.
In other words: your own classloader is not actually used for any objects you create using native calls like "new" etc. To do that it should be responsible for loading the IntegerPrinter class as well.
It is rather circumspect (and in general useless) to do it in the same class but you could do:
Class<?> clazz = loader.loadClass("IntegerPrinterTest");
clazz.getMethod("main").invoke(null);
(note this code is not tested but should approximate something that works)

java : ClassLoaders

Say, I have a class A, loaded by ClassLoader CL1.
I have another class B, loaded by ClassLoader CL2.
Assume both classes are now loaded by their respective ClassLoaders.
From A, if I execute the following statement, what would be the result : B.class.getClassLoader();
Will it return CL2? Please clarify.
Thanks
HV
Will it return CL2?
In the case where it has permission to do so then yes - why wouldn't it? The result has no bearing on what class you execute the method from, it is to do with what class you execute the method on (which in this case, is B.class which was loaded by CL2.)
From the docs:
Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader.
If a security manager is present, and the caller's class loader is not null and the caller's class loader is not the same as or an ancestor of the class loader for the class whose class loader is requested, then this method calls the security manager's checkPermission method with a RuntimePermission("getClassLoader") permission to ensure it's ok to access the class loader for the class.
So assuming it's an actual class that you've loaded (rather than a primitive), and the security manager says that you have permission to check the class, yes - it will return the corresponding classloader (CL2 in this instance.)
It does return the classloader which loaded class B but caller should have permission on that class loader.
Check the API doc
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getClassLoader()

Categories

Resources