黑马程序员-类加载器

来源:互联网 发布:unity3d ui界面 编辑:程序博客网 时间:2024/04/30 07:03

------- android培训java培训期待与您交流 ----------

类加载器:

系统默认有3个类加载器 AppClassLoader >> ExtClassLoader >> BootStrap

  AppClassLoader:加载CLASSPATH指定的所有jar或目录

  ExtClassLoader:加载jre/lib/ext/*.jar,加载ext下所有的jar

  BootStrap:加载jre/lib/rt.jar ,加载lib下的rt.jarBootStrap不是java类,所以BootStrap的字节码为null,他是用C++写的一段二进制代码

Java虚拟机要加载一个类时:

  首先用当前线程的类加载器去加载线程中的第一个类。

  如果说这个类中还引用了其他类,那也是用加载这个类的加载器去加载。

  也可以用ClassLoader.loadClass();方法来指定一个类加载器去加载。

委托机制:

  类加载器在加载的时候有一个委托机制,也就是说当前加载器不会马上在自己的范围内找类加载,而是委托上级进行加载,一直委托到BootStrap,如果BootStraprt.jar中没找到就又一级一级的返回在其他加载器查找加载,如果返回到当前加载器也没有找到该类的话就抛出异常: ClassNotFoundException,即使当前加载器下还有加载器也不会向下查找了。

  委托机制还有个一个好处就是可以保证一个类只被加载一次,如果还要去加 载的话会先根据这个委托机制上下看一看这个类被加载过没有,如果加载过 了直接返回一份字节码就是了。

自定义类加载器加密class文件:

  创建一个类继承ClassLoader,创建一个加密的class文件的方法,重写finadClass方法(类加载器内部在加载类的时候是自动调用loadClass方法,而loadClass方法内部会自动的调用上级类加载器加载,以此类推,如果最后返回回来上级类加载器都没找到,则又loadClass()又调用本类的fiandClass方法,所有只重写fiandClass就行了)

 

public class ClassLoaderAttachment extends Date {public String toString(){return "hello,itcast heima";}}
public class MyClassLoader extends ClassLoader {public static void main(String[] args) throws Exception {//接收传入的参数 ,一个为原class文件的地址,另一个为加密后文件的地址String srcPath = args[0];String destPath = args[1] + "\\" + srcPath.substring(srcPath.lastIndexOf("\\"));//读取文件FileInputStream fis = new FileInputStream(srcPath);//写入FileOutputStream fos = new FileOutputStream(destPath);//调用加密方法,对class文件进行加密cypher(fis,fos);fis.close();fos.close();}//加密public static void cypher(InputStream is, OutputStream os) throws Exception{//System.out.println("jiami");int b = -1;while((b = is.read()) != -1){os.write(b ^ 0xff);}}private String classDir;MyClassLoader(){}MyClassLoader(String classDir){//接收地址this.classDir = classDir;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {//拼接class文件地址name = classDir + "\\" + name + ".class";try {FileInputStream fis = new FileInputStream(name);ByteArrayOutputStream bos = new ByteArrayOutputStream();//对class文件进行解密cypher(fis,bos);fis.close();//获得字节数组byte[] buf = bos.toByteArray();bos.close();//把字节数组传入defineClass()方法 返回一个Class文件return defineClass(buf, 0, buf.length);} catch (Exception e) {e.printStackTrace();}return super.findClass(name);}}

public class ClassLoaderTest {public static void main(String[] args) throws Exception {// TODO Auto-generated method stub//使用自定义加载器加载文件//Class clazz = new MyClassLoader("bin\\test\\enhance\\classloader").loadClass("ClassLoaderAttachment");Class clazz = new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");//这里不能用ClassLoaderAttachment类接收,因为现在classPath里的class文件是被加了密的。Date date = (Date)clazz.newInstance();System.out.println(date.getClass().getClassLoader());System.out.println(date);}}

问题:

rt.jar中有java.lang.System类,我可不可以自己再写一个java.lang.System来用?

答:rt.jar本来有System类的,而加载的时候又有委托机制,也就是说会最先找最上级,按照普通的方式的话自己写的System类是没有机会被加载到的,但是我们可以撇开委托机制,用特殊方法写一个类加载器去加载


原创粉丝点击