最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
java详解类加载器的双亲委派及打破双亲委派
时间:2017-01-16 编辑:简简单单 来源:一聚教程网
一般的场景中使用Java默认的类加载器即可,但有时为了达到某种目的又不得不实现自己的类加载器,例如为了达到类库的互相隔离,例如为了达到热部署重加载功能。这时就需要自己定义类加载器,每个类加载器加载各自的类库资源,以此达到资源隔离效果。在对资源的加载上可以沿用双亲委派机制,也可以打破双亲委派机制。
一、沿用双亲委派机制自定义类加载器很简单,只需继承ClassLoader类并重写findClass方法即可。如下例子:
①先定义一个待加载的类Test,它很简单,只是在构建函数中输出由哪个类加载器加载。
代码如下 | 复制代码 |
publicclassTest {
publicTest(){ System.out.println(this.getClass().getClassLoader().toString()); }
} |
②定义一个TestClassLoader类继承ClassLoader,重写findClass方法,此方法要做的事情是读取Test.class字节流并传入父类的defineClass方法即可。然后就可以通过自定义累加载器TestClassLoader对Test.class进行加载,完成加载后会输出“TestLoader”。
代码如下 | 复制代码 |
publicclassTestClassLoaderextendsClassLoader {
privateString name;
publicTestClassLoader(ClassLoader parent, String name) { super(parent); this.name = name; }
@Override publicString toString() { returnthis.name; }
@Override publicClass findClass(String name) {
InputStream is =null; byte[] data =null; ByteArrayOutputStream baos =newByteArrayOutputStream(); try{ is =newFileInputStream(newFile("d:/Test.class")); intc =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(); } } returnthis.defineClass(name, data,0, data.length); }
publicstaticvoidmain(String[] args) { TestClassLoader loader =newTestClassLoader( 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类。
代码如下 | 复制代码 |
publicclassTest { publicTest(){ System.out.println(this.getClass().getClassLoader().toString()); } } |
②重新定义一个继承ClassLoader的TestClassLoaderN类,这个类与前面的TestClassLoader类很相似,但它除了重写findClass方法外还重写了loadClass方法,默认的loadClass方法是实现了双亲委派机制的逻辑,即会先让父类加载器加载,当无法加载时才由自己加载。这里为了破坏双亲委派机制必须重写loadClass方法,即这里先尝试交由System类加载器加载,加载失败才会由自己加载。它并没有优先交给父类加载器,这就打破了双亲委派机制。
代码如下 | 复制代码 |
publicclassTestClassLoaderNextendsClassLoader {
privateString name;
publicTestClassLoaderN(ClassLoader parent, String name) { super(parent); this.name = name; }
@Override publicString toString() { returnthis.name; }
@Override publicClass loadClass(String name)throwsClassNotFoundException { Class clazz =null; ClassLoader system = getSystemClassLoader(); try{ clazz = system.loadClass(name); }catch(Exception e) { // ignore } if(clazz !=null) returnclazz; clazz = findClass(name); returnclazz; }
@Override publicClass findClass(String name) {
InputStream is =null; byte[] data =null; ByteArrayOutputStream baos =newByteArrayOutputStream(); try{ is =newFileInputStream(newFile("d:/Test.class")); intc =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(); } } returnthis.defineClass(name, data,0, data.length); }
publicstaticvoidmain(String[] args) { TestClassLoaderN loader =newTestClassLoaderN( TestClassLoaderN.class.getClassLoader(),"TestLoaderN"); Class clazz; try{ clazz = loader.loadClass("test.classloader.Test"); Object object = clazz.newInstance(); }catch(Exception e) { e.printStackTrace(); } } } |
-
上一个: Java中对象的序列化方式克隆详解
-
下一个: Java多线程实现的两种方式
相关文章
- 分析Tomcat 类加载机制触发的 Too many open files 问题 11-18
- Java类加载原理及类加载器 04-28
- Tomcat4.1.x以上中类的加载 01-12
- SpringBoot测试配置属性与web启动环境解析 10-24
- vue中将el-switch值true、false改为number类型的1和0解析 10-24
- Vue中的路由配置项meta使用解读 10-24