java 详解类加载器的双亲委派及打破双亲委派
java 详解类加载器的双亲委派及打破双亲委派
一般的场景中使用java默认的类加载器即可,但有时为了达到某种目的又不得不实现自己的类加载器,例如为了达到类库的互相隔离,例如为了达到热部署重加载功能。这时就需要自己定义类加载器,每个类加载器加载各自的类库资源,以此达到资源隔离效果。在对资源的加载上可以沿用双亲委派机制,也可以打破双亲委派机制。
一、沿用双亲委派机制自定义类加载器很简单,只需继承classloader类并重写findclass方法即可。如下例子:
①先定义一个待加载的类test,它很简单,只是在构建函数中输出由哪个类加载器加载。
public class test { public test(){ system.out.println(this.getclass().getclassloader().tostring()); } }
②定义一个testclassloader类继承classloader,重写findclass方法,此方法要做的事情是读取test.class字节流并传入父类的defineclass方法即可。然后就可以通过自定义累加载器testclassloader对test.class进行加载,完成加载后会输出“testloader”。
public class testclassloader extends classloader { private string name; public testclassloader(classloader parent, string name) { super(parent); this.name = name; } @override public string tostring() { return this.name; } @override public class<?> findclass(string name) { inputstream is = null; byte[] data = null; bytearrayoutputstream baos = new bytearrayoutputstream(); try { is = new fileinputstream(new file("d:/test.class")); int c = 0; while (-1 != (c = is.read())) { baos.write(c); } data = baos.tobytearray(); } catch (exception e) { e.printstacktrace(); } finally { try { is.close(); baos.close(); } catch (ioexception e) { e.printstacktrace(); } } return this.defineclass(name, data, 0, data.length); } public static void main(string[] args) { testclassloader loader = new testclassloader( testclassloader.class.getclassloader(), "testloader"); class clazz; try { clazz = loader.loadclass("test.classloader.test"); object object = clazz.newinstance(); } catch (exception e) { e.printstacktrace(); } } }
二、打破双亲委派机制则不仅要继承classloader类,还要重写loadclass和findclass方法,如下例子:
①定义test类。
public class test { public test(){ system.out.println(this.getclass().getclassloader().tostring()); } }
②重新定义一个继承classloader的testclassloadern类,这个类与前面的testclassloader类很相似,但它除了重写findclass方法外还重写了loadclass方法,默认的loadclass方法是实现了双亲委派机制的逻辑,即会先让父类加载器加载,当无法加载时才由自己加载。这里为了破坏双亲委派机制必须重写loadclass方法,即这里先尝试交由system类加载器加载,加载失败才会由自己加载。它并没有优先交给父类加载器,这就打破了双亲委派机制。
public class testclassloadern extends classloader { private string name; public testclassloadern(classloader parent, string name) { super(parent); this.name = name; } @override public string tostring() { return this.name; } @override public class<?> loadclass(string name) throws classnotfoundexception { class<?> clazz = null; classloader system = getsystemclassloader(); try { clazz = system.loadclass(name); } catch (exception e) { // ignore } if (clazz != null) return clazz; clazz = findclass(name); return clazz; } @override public class<?> findclass(string name) { inputstream is = null; byte[] data = null; bytearrayoutputstream baos = new bytearrayoutputstream(); try { is = new fileinputstream(new file("d:/test.class")); int c = 0; while (-1 != (c = is.read())) { baos.write(c); } data = baos.tobytearray(); } catch (exception e) { e.printstacktrace(); } finally { try { is.close(); baos.close(); } catch (ioexception e) { e.printstacktrace(); } } return this.defineclass(name, data, 0, data.length); } public static void main(string[] args) { testclassloadern loader = new testclassloadern( testclassloadern.class.getclassloader(), "testloadern"); class clazz; try { clazz = loader.loadclass("test.classloader.test"); object object = clazz.newinstance(); } catch (exception e) { e.printstacktrace(); } } }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
推荐阅读
-
java 详解类加载器的双亲委派及打破双亲委派
-
JVM的类加载过程以及双亲委派模型详解
-
荐 JVM入门到精通系列 (一)类加载器加载类的完整过程与双亲委派原理
-
[五]类加载机制双亲委派机制 底层代码实现原理 源码分析 java类加载双亲委派机制是如何实现的
-
【java基础】面试常见问题:类和对象,封装继承多态,final关键字,static关键字,类加载过程,双亲委派模型
-
Java类加载器( CLassLoader ) : 神秘的双亲委托机制
-
类加载器和双亲委派模型
-
【深入理解JVM】1、在JVM类加载如何加载?双亲委派加载类及混合模式,代码演示【面试必备】
-
类加载器与双亲委派机制
-
荐 java类加载过程及双亲委派机制