在普通的Main程序中,
某个类是被哪个加载器所加载的?
print(String.class.getClassLoader()); //打印null, 这在HotSpot里代表Bootstrap ClassLoader,它负责加载$JAVA_HOME/lib里的类库
print(List.class.getClassLoader()); // 同上
print(learn.classloader.WhoLoadsMe.class.getClassLoader()); // 打印sun.misc.Launcher$AppClassLoader,它在HotSpot里代表System Class Loader, 负责加载用户类路径上的类库
print(learn.classloader.Friend.class.getClassLoader()); //同上
//看看sun.misc.Launcher$AppClassLoader的父加载器和祖父加载器是哪些
print(learn.classloader.Friend.class.getClassLoader().getParent()); //打印sun.misc.Launcher$ExtClassLoader,它在HotSpot里用于加载$JAVA_HOME/lib/ext下的类库
print(learn.classloader.Friend.class.getClassLoader().getParent().getParent()); //打印null, 即Bootstrap ClassLoader
Class<?> remoteFriendClass = new learn.classloader.RemoteClassLoader().loadClass(
"learn.classloader.RemoteFriend");
print(remoteFriendClass.getClassLoader()); //打印 learn.classloader.RemoteClassLoader,即自写的class loader(后文有这个class loader的代码)
//看看自写加载器的父加载器是哪个
print(remoteFriendClass.getClassLoader().getParent()); //打印sun.misc.Launcher$AppClassLoader,即System ClassLoader
print(remoteFriendClass.getField("friendOfFriend").getType()
.getClassLoader()); //同上, 这意味着在"RemoteFriend"里直接引用的类(后文附上了代码描述这个引用)是由RemoteFriend的加载器所加载的
//最后看下context class loader
print(Thread.currentThread().getContextClassLoader()); //打印sun.misc.Launcher$AppClassLoader,即system classloader
附:
RemoteClassLoader
package learn.classloader;
public class RemoteClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(name);
if (clazz != null) {
return clazz;
}
clazz = letParentLoad(name);
if (clazz != null) {
return clazz;
}
String classDir = "/home/kent/another-project/classes/";
String classFile = classDir + name.replaceAll("\\.", "\\/") + ".class";
byte[] bytes = readToBytes(classFile);
return defineClass(name, bytes, 0, bytes.length);
}
...
}
附:
RemoteFriend类里的FriendOfFriend
package learn.classloader;
public class RemoteFriend {
public static FriendOfFriend friendOfFriend = new FriendOfFriend();
}