Java提供了规范,各个厂商去实现这些规范,比如JDBC/JNDI,这写都是SPI(service provider interface),与api的区别是是否提供实现
这就出现一个问题,SPI的代码被定义在java基础库中,厂商提供的实现第三方jar,SPI会加载实例化第三方jar
java默认的类加载机制是双亲委派模型
,即先通过父加载器加载,如果父加载器找不到,再通过子加载器加载
加载器之间的关系:BootstrapClassLoader > ExtensionClassLoader > AppClassLoader > CustomerClassLoader
- BootstrapClassLoader: rt.jar
- ExtensionClassLoader: JAVA_HOME/lib/ext/
- AppClassLoader: ClassPath
- CustomerClassLoader: 自定义加载器
接着讨论刚才的问题,BootstrapClassLoader中的SPI找不到了AppClassLoader中的mysql.jar的实现类 为了解决这种问题引入了ThreadContextClassLoader
当前线程ThreadContextClassLoader
默认存放了AppClassLoader
,这种做法破坏了双亲委派模型
通过DriverManager我们可以看到ClassLoader在JDBC中的使用逻辑
// DriverManager
private static void loadInitialDrivers() {
...
String[] driversList = drivers.split(":");
println("number of Drivers:" + driversList.length);
for (String aDriver : driversList) {
try {
println("DriverManager.Initialize: loading " + aDriver);
Class.forName(aDriver, true,
ClassLoader.getSystemClassLoader());//这里获取AppClassLoader
} catch (Exception ex) {
println("DriverManager.Initialize: load failed: " + ex);
}
}
...
}
// ClassLoader
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();// 系统初始化在这里
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
private static synchronized void initSystemClassLoader() {
if (!sclSet) {
if (scl != null)
throw new IllegalStateException("recursive invocation");
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();// 系统初始化在这里
if (l != null) {
Throwable oops = null;
scl = l.getClassLoader();// 这里获取
try {
scl = AccessController.doPrivileged(
new SystemClassLoaderAction(scl));
} catch (PrivilegedActionException pae) {
oops = pae.getCause();
if (oops instanceof InvocationTargetException) {
oops = oops.getCause();
}
}
if (oops != null) {
if (oops instanceof Error) {
throw (Error) oops;
} else {
// wrap the exception
throw new Error(oops);
}
}
}
sclSet = true;
}
}
// Launcher
public Launcher() {
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);//获取AppClassLoader
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
Thread.currentThread().setContextClassLoader(this.loader);//set ContextClassLoader= AppClassLoader
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);
}
}