一.好处
保证了Java程序的稳定运行,可以避免类的重复加载。保证了Java的核心API不被篡改。
二.源码
public Class<?> loadClass(String name) throws ClassNotFoundException {return loadClass(name, false);}protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 检查是否已经加载过Class<?> c = findLoadedClass(name);if (c == null) {try {// 存在父加载器,交给父加载器加载if (parent != null) {c = parent.loadClass(name, false);} else {// Bootstrap类加载器加载c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {}// 父加载器无法加载,自己加载if (c == null) {c = findClass(name);}}return c;}}
三.如何打破双亲委派机制
1.自定义类加载器,重写loadClass方法。
2.线程上下文类加载器。
public class Test {public static void main(String[] args) throws SQLException {Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("select * from t1");while(resultSet.next()) {System.out.println(resultSet.getString("name"));}}}
不用写Class.forName加载驱动类。
DriverManager.getConnection触发DriverManager的加载,类加载器是启动类加载器。
public class DriverManager {static {loadInitialDrivers();}private static void loadInitialDrivers() {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();try{while(driversIterator.hasNext()) {// 加载驱动类driversIterator.next();}} catch(Throwable t) {}return null;}});}}
ServiceLoader.load
public static <S> ServiceLoader<S> load(Class<S> service) {// AppClassLoaderClassLoader cl = Thread.currentThread().getContextClassLoader();return ServiceLoader.load(service, cl);}public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader){return new ServiceLoader<>(service, loader);}
加载驱动类
private S nextService() {Class<?> c = null;try {// cn:com.mysql.cj.jdbc.Driver(META-INF/services/java.sql.Driver)// loader:AppClassLoaderc = Class.forName(cn, false, loader);} catch (ClassNotFoundException x) {}}
四.tomcat类加载器
Tomcat允许同时运行多个Web程序,每个Web程序依赖的类必须是相互隔离的,因为可能会依赖同一个第三方类库的不同版本。使用WebappClassLoader加载应用程序中的Class,只对当前webapp可见,对Tomcat和其他Web应用程序不可见。
Common类加载器,负责加载Tomcat和Web应用都复用的类。
Catalina类加载器,负责加载Tomcat专用的类,而这些被加载的类在Web应用中将不可见。
Shared类加载器,负责加载Tomcat下所有的Web应用程序都复用的类,而这些被加载的类在Tomcat中将不可见。
commonLoader,catalinaLoader,sharedLoader 现在是同一个对象(URLClassLoader)。
