JAVA 双亲委派及如何打破

JAVA 双亲委派及如何打破

    • 双亲委派原则解释
    • 双亲委派模型图
    • 如何打破这种加载模型
    • 总结

双亲委派原则解释

java为了类加载安全定义了一个原则,那就是双亲委派原则
解释:所有类的加载都被委派给父类加载,只有父类不能加载的时候才由子类加载
由此才能保证java类的安全,因为用户不能随便自定义修改java类库中的类

双亲委派模型图

如何打破这种加载模型

  1. 继承ClassLoader类
  2. 重写loadClass方法
package com.bamdow.util;

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

public class TestClassLoader {
	static{
        System.out.println("static block init");
     }
	public TestClassLoader() {
		System.out.println("constructer init");
	}

	public static void main(String[] args) {
		//自定义类加载器
		ClassLoader classLoader = new ClassLoaderDelegate(TestClassLoader.class.getResource("/").getPath());
		try {
			Class b = TestClassLoader.class.getClassLoader().loadClass(TestClassLoader.class.getName());
			b.newInstance();
			Class a = classLoader.loadClass(TestClassLoader.class.getName());
			a.newInstance();
			System.out.println("a="+a+",hash="+a.hashCode());
			System.out.println("b="+b+",hash="+b.hashCode());
			System.out.println(a==b);
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		
	}
	
	static class ClassLoaderDelegate extends ClassLoader{
		 private String path;
    	 protected ClassLoaderDelegate(String path) {
    		 super();
    		 this.path = path; 
    	 }
        public Class<?> loadClass(String name)
        	    throws ClassNotFoundException {
        	      //System.out.println("loadclass..."+name);
 	        	  if(!TestClassLoader.class.getName().equals(name)){
 	       	    	  return super.loadClass(name);
	        	  }
        	      byte[] classBytes = null;
        	      try( InputStream in = new FileInputStream(path+name.replaceAll("\\.", "/")+".class")){
        	    	  classBytes = new byte[(int)in.available()];
  	        	      in.read(classBytes);
        	      } catch (FileNotFoundException e) {
					e.printStackTrace();
				  } catch (IOException e) {
					e.printStackTrace();
				  }
        	      Class<?> clazz = defineClass(name, classBytes, 0, classBytes.length);
        	      return clazz;
        	}
	}
}

总结

  1. 双亲委派漏洞是jdk早起版本出现的,后面sun公司为了自己的API承诺为屏蔽方法重写。如果要自定义类加载请重写findclass方法
  2. 因为所亲委派的出现,因此所有的类只会有一个类加载加载,也因此static静态模块只会执行一次,但是当我们重写loadClass方法之后,类肯能被多个类加载器执行,也因此类的静态模块就可以执行多次。

你可能感兴趣的:(JAVA)