Reputation: 117
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?
Upvotes: 0
Views: 574
Reputation: 54611
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) :
getClassLoader0
method of Class
is bound to JVM_GetClassLoader
JVM_GetClassLoader
method eventually calls Klass::class_loader()
Klass::class_loader()
method only returns the result of ClassLoaderData::class_loader()
ClassLoaderData::class_loader()
method finally returns the field that you are looking forHowever, 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.
Upvotes: 1
Reputation: 34618
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.
Upvotes: 3
Reputation: 58848
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).
Upvotes: 1
Reputation: 272
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.
Upvotes: 0