类加载流程图
1.创建引导类加载器(C语言实现)(bootstrapClassLoader)
2.创建JVM启动器
3.实例化启动器过程中,初始化extClassLoader、AppClassLoader。
一、JVM启动器结构预览
扩展与应用类加载器都是启动器内部类
package sun.misc;
public class Launcher {
private static URLStreamHandlerFactory factory = new Launcher.Factory();
//加载是实例化
private static Launcher launcher = new Launcher();
private static String bootClassPath = System.getProperty("sun.boot.class.path");
private ClassLoader loader;
private static URLStreamHandler fileHandler;
public static Launcher getLauncher() {
return launcher;
}
public Launcher() {
Launcher.ExtClassLoader var1;
try {
//获取扩展类加载器对象。(扩展类加载器,是Launcher的一个内部类)
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
//扩展类加载器作为入参,最终为AppClassLoader中parent属性赋值,即标识父加载器
//(应用类加载器,是Launcher的一个内部类)
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
Thread.currentThread().setContextClassLoader(this.loader);
String var2 = System.getProperty("java.security.manager");
if (var2 != null) {
SecurityManager var3 = null;
if (!"".equals(var2) && !"default".equals(var2)) {
try {
var3 = (SecurityManager) this.loader.loadClass(var2).newInstance();
} catch (IllegalAccessException var5) {
;
} catch (InstantiationException var6) {
;
} catch (ClassNotFoundException var7) {
;
} catch (ClassCastException var8) {
;
}
} else {
var3 = new SecurityManager();
}
if (var3 == null) {
throw new InternalError("Could not create SecurityManager: " + var2);
}
System.setSecurityManager(var3);
}
}
/***
*获取应用类加载器appClassLoader
**/
public ClassLoader getClassLoader() {
return this.loader;
}
public static URLClassPath getBootstrapClassPath() {
return Launcher.BootClassPathHolder.bcp;
}
private static File[] getClassPath(String var0) {
File[] var1;
if (var0 != null) {
int var2 = 0;
int var3 = 1;
boolean var4 = false;
int var5;
int var7;
for (var5 = 0; (var7 = var0.indexOf(File.pathSeparator, var5)) != -1; var5 = var7 + 1) {
++var3;
}
var1 = new File[var3];
var4 = false;
for (var5 = 0; (var7 = var0.indexOf(File.pathSeparator, var5)) != -1; var5 = var7 + 1) {
if (var7 - var5 > 0) {
var1[var2++] = new File(var0.substring(var5, var7));
} else {
var1[var2++] = new File(".");
}
}
if (var5 < var0.length()) {
var1[var2++] = new File(var0.substring(var5));
} else {
var1[var2++] = new File(".");
}
if (var2 != var3) {
File[] var6 = new File[var2];
System.arraycopy(var1, 0, var6, 0, var2);
var1 = var6;
}
} else {
var1 = new File[0];
}
return var1;
}
static class AppClassLoader extends URLClassLoader {
final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);
public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
final String var1 = System.getProperty("java.class.path");
final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
public Launcher.AppClassLoader run() {
URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
return new Launcher.AppClassLoader(var1x, var0);
}
});
}
AppClassLoader(URL[] var1, ClassLoader var2) {
super(var1, var2, Launcher.factory);
this.ucp.initLookupCache(this);
}
public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
int var3 = var1.lastIndexOf(46);
if (var3 != -1) {
SecurityManager var4 = System.getSecurityManager();
if (var4 != null) {
var4.checkPackageAccess(var1.substring(0, var3));
}
}
if (this.ucp.knownToNotExist(var1)) {
Class var5 = this.findLoadedClass(var1);
if (var5 != null) {
if (var2) {
this.resolveClass(var5);
}
return var5;
} else {
throw new ClassNotFoundException(var1);
}
} else {
return super.loadClass(var1, var2);
}
}
protected PermissionCollection getPermissions(CodeSource var1) {
PermissionCollection var2 = super.getPermissions(var1);
var2.add(new RuntimePermission("exitVM"));
return var2;
}
private void appendToClassPathForInstrumentation(String var1) {
assert Thread.holdsLock(this);
super.addURL(Launcher.getFileURL(new File(var1)));
}
private static AccessControlContext getContext(File[] var0) throws MalformedURLException {
PathPermissions var1 = new PathPermissions(var0);
ProtectionDomain var2 = new ProtectionDomain(new CodeSource(var1.getCodeBase(), (Certificate[]) null), var1);
AccessControlContext var3 = new AccessControlContext(new ProtectionDomain[]{var2});
return var3;
}
static {
ClassLoader.registerAsParallelCapable();
}
}
private static class BootClassPathHolder {
static final URLClassPath bcp;
private BootClassPathHolder() {
}
static {
URL[] var0;
if (Launcher.bootClassPath != null) {
var0 = (URL[]) AccessController.doPrivileged(new PrivilegedAction<URL[]>() {
public URL[] run() {
File[] var1 = Launcher.getClassPath(Launcher.bootClassPath);
int var2 = var1.length;
HashSet var3 = new HashSet();
for (int var4 = 0; var4 < var2; ++var4) {
File var5 = var1[var4];
if (!var5.isDirectory()) {
var5 = var5.getParentFile();
}
if (var5 != null && var3.add(var5)) {
MetaIndex.registerDirectory(var5);
}
}
return Launcher.pathToURLs(var1);
}
});
} else {
var0 = new URL[0];
}
bcp = new URLClassPath(var0, Launcher.factory, (AccessControlContext) null);
bcp.initLookupCache((ClassLoader) null);
}
}
static class ExtClassLoader extends URLClassLoader {
public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
final File[] var0 = getExtDirs();
try {
return (Launcher.ExtClassLoader) AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {
public Launcher.ExtClassLoader run() throws IOException {
int var1 = var0.length;
for (int var2 = 0; var2 < var1; ++var2) {
MetaIndex.registerDirectory(var0[var2]);
}
return new Launcher.ExtClassLoader(var0);
}
});
} catch (PrivilegedActionException var2) {
throw (IOException) var2.getException();
}
}
void addExtURL(URL var1) {
super.addURL(var1);
}
//因为bootstrapClassLoader是C++实现,没有具体java对象,故ExtClassLoader对象parent属性为空。
public ExtClassLoader(File[] var1) throws IOException {
super(getExtURLs(var1), (ClassLoader) null, Launcher.factory);
SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
}
private static File[] getExtDirs() {
String var0 = System.getProperty("java.ext.dirs");
File[] var1;
if (var0 != null) {
StringTokenizer var2 = new StringTokenizer(var0, File.pathSeparator);
int var3 = var2.countTokens();
var1 = new File[var3];
for (int var4 = 0; var4 < var3; ++var4) {
var1[var4] = new File(var2.nextToken());
}
} else {
var1 = new File[0];
}
return var1;
}
private static URL[] getExtURLs(File[] var0) throws IOException {
Vector var1 = new Vector();
for (int var2 = 0; var2 < var0.length; ++var2) {
String[] var3 = var0[var2].list();
if (var3 != null) {
for (int var4 = 0; var4 < var3.length; ++var4) {
if (!var3[var4].equals("meta-index")) {
File var5 = new File(var0[var2], var3[var4]);
var1.add(Launcher.getFileURL(var5));
}
}
}
}
URL[] var6 = new URL[var1.size()];
var1.copyInto(var6);
return var6;
}
public String findLibrary(String var1) {
var1 = System.mapLibraryName(var1);
URL[] var2 = super.getURLs();
File var3 = null;
for (int var4 = 0; var4 < var2.length; ++var4) {
URI var5;
try {
var5 = var2[var4].toURI();
} catch (URISyntaxException var9) {
continue;
}
File var6 = (new File(var5)).getParentFile();
if (var6 != null && !var6.equals(var3)) {
String var7 = VM.getSavedProperty("os.arch");
File var8;
if (var7 != null) {
var8 = new File(new File(var6, var7), var1);
if (var8.exists()) {
return var8.getAbsolutePath();
}
}
var8 = new File(var6, var1);
if (var8.exists()) {
return var8.getAbsolutePath();
}
}
var3 = var6;
}
return null;
}
private static AccessControlContext getContext(File[] var0) throws IOException {
PathPermissions var1 = new PathPermissions(var0);
ProtectionDomain var2 = new ProtectionDomain(new CodeSource(var1.getCodeBase(), (Certificate[]) null), var1);
AccessControlContext var3 = new AccessControlContext(new ProtectionDomain[]{var2});
return var3;
}
static {
ClassLoader.registerAsParallelCapable();
}
}
private static class Factory implements URLStreamHandlerFactory {
private static String PREFIX = "sun.net.www.protocol";
private Factory() {
}
public URLStreamHandler createURLStreamHandler(String var1) {
String var2 = PREFIX + "." + var1 + ".Handler";
try {
Class var3 = Class.forName(var2);
return (URLStreamHandler) var3.newInstance();
} catch (ReflectiveOperationException var4) {
throw new InternalError("could not load " + var1 + "system protocol handler", var4);
}
}
}
}
二、自定义类加载器
打破双亲委派,改写ClassLoader中查找父类加载器的逻辑即可,避免加载自定义类时,被委派给应用类加载器。(注意jdk核心代码需要,仍然使用双亲委派,不能使用自定义类加载器加载jdk核心包)