温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么破坏Java双亲委派模型

发布时间:2021-11-16 13:48:13 来源:亿速云 阅读:220 作者:iii 栏目:大数据

本篇内容主要讲解“怎么破坏Java双亲委派模型”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么破坏Java双亲委派模型”吧!

自定义示例一

重写findClass不会破坏双亲委派模型,同时也验证了双亲委派模型的正确性。

package com.example.classloader;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class TestClassLoader {

	@Test
	public void test() {
		Class<?> class0 = TestClassLoader.class;
		try {
			// false
			System.out.println(class0.getClassLoader() instanceof MyClassLoader);
			Class<?> class1 = class0.getClassLoader().loadClass("com.example.classloader.TestClassLoader");
			ClassLoader classLoader = new MyClassLoader();
			Class<?> class2 = classLoader.loadClass("com.example.classloader.TestClassLoader");
			// true
			System.out.println(class0.equals(class1));
			// true
			System.out.println(class1.equals(class2));
			// sun.misc.Launcher$AppClassLoader@18b4aac2
			System.out.println(class0.getClassLoader());
			// sun.misc.Launcher$AppClassLoader@18b4aac2
			System.out.println(class1.getClassLoader());
			// sun.misc.Launcher$AppClassLoader@18b4aac2
			System.out.println(class2.getClassLoader());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 *  自定义一个类加载器从指定磁盘目录加载类
	 *  重写findClass不破坏双亲委派模型
	 */
	public class MyClassLoader extends ClassLoader {
		@Override
		protected Class<?> findClass(String name) {
			String myPath = "/Users/lsx/code/demo/target/classes/" + name.replace(".", "/") + ".class";
			byte[] classBytes = null;
			FileInputStream in = null;

			try {
				File file = new File(myPath);
				in = new FileInputStream(file);
				classBytes = new byte[(int) file.length()];
				in.read(classBytes);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length);
			return clazz;
		}
	}
}

自定义示例二

重写loadClass破坏双亲委派模型,父类的加载(Object)也会交由我们自自定义的类加载器加载。而很明显在我们自定义的加载目录下是不会有Object.class这个文件的,所以会抛出异常。

/**
	 *  重写loadClass破坏双亲委派模型
	 * java.io.FileNotFoundException: /Users/lsx/code/demo/target/classes/java/lang/Object.class (No such file or directory)
	 */
	public class MyClassLoader extends ClassLoader {
		@Override
		public Class<?> loadClass(String name) {
			String myPath = "/Users/lsx/code/demo/target/classes/" + name.replace(".", "/") + ".class";
			System.out.println(myPath);
			byte[] classBytes = null;
			FileInputStream in = null;

			try {
				File file = new File(myPath);
				in = new FileInputStream(file);
				classBytes = new byte[(int) file.length()];
				in.read(classBytes);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			System.out.println();
			Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length);
			return clazz;
		}
	}

总结:如果不想打破双亲委派模型就重写ClassLoader类中的findClass()方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。而如果想打破双亲委派模型则需要重写loadClass()方法。

JDBC对双亲委派模型的破坏(加载SPI接口实现类)

原生的JDBC中Driver驱动本身只是一个接口,并没有具体的实现,具体的实现是由不同数据库类型去实现的。例如,MySQL的mysql-connector-.jar中的Driver类具体实现的。 原生的JDBC中的类是放在rt.jar包的,是由启动类加载器进行类加载的,在JDBC中的Driver类中需要动态去加载不同数据库类型的Driver类,而mysql-connector-.jar中的Driver类是用户自己写的代码,那启动类加载器肯定是不能进行加载的,既然是自己编写的代码,那就需要由应用程序启动类去进行类加载。于是乎,这个时候就引入线程上下文件类加载器(Thread Context ClassLoader)。有了这个东西之后,程序就可以把原本需要由启动类加载器进行加载的类,由应用程序类加载器去进行加载了。通过线程上下文加载器去加载所需要的SPI代码,也就是父类加载器请求子类加载器去完成类加载的动作,实际是通过打破了双亲委派模型的层次结构来逆向使用类加载器,违背了双亲委派模型的一般性原则。具体参考以JDBC为例谈双亲委派模型的破坏

OSGI对双亲委派模型的破坏

双亲委派模型的第三次“被破坏”是由于用户对程序的动态性的追求导致的。为了实现热插拔、热部署、模块化,意思是添加一个功能或减去一个功能不用重启,只需要把这模块连同类加载器一起换掉就实现了代码的热替换。例如OSGi的出现,在OSGi环境下类加载器不再是双亲委派模型中的树状结构,而是进一步发展为网状结构

到此,相信大家对“怎么破坏Java双亲委派模型”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI