classloader是什么java
个人理解classloader就是加载咱们的类到内存的类,他主要就是寻找资源,即找到在他能搜索到的路径中,有没有咱们的类。有的话就加载到内存。web
系统的classloader数组
系统的classloader有三种tomcat
Bootstrap ClassLoader 负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等服务器
Extension ClassLoader 负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
app
App ClassLoader 负责加载当前java应用的classpath中的全部类。jvm
双亲委托机制ide
系统的classloader实行的是双亲委托机制,双亲委托机制就是在加载类的时候先去父类(此处的父类不是继承里面的父类,双亲委托机制是组合)里查找,若是父类加载到了就算子类的能够在本身的路径下找到,也不能加载。只会从父类中取到加到后的class。这样的好处就是不会重复加载类。测试
此处只是说系统的classloader,由于你本身写的classloader不必定要遵循这个机制,并且有些状况必须不能遵循,例如tomcat等服务器,加载的时候不会遵循双亲委托(他的classloder是本身实现的),他是优先本身加载,本身加载不到才会委托父类加载,他是必须容许,相同的类会被重复加载。由于你两个web应用用到了相同的类,加载的时候是加载了一个web应用的类,那么解部署的时候必须不能删除该类,由于另外一个web应用还在用。
加密
本身写classloader
知道这么多机制,确定是为了本身写classloader,本身写的classloder有不少用处,例如本身作点字节码增长功能(固然javaagent也能作),作对类的加密解密功能等等。
java提供了一个类帮助咱们实现classloader,这个类是URLClassLoader,咱们只须要继承这个类,覆写loadClass方法就能够,他必须调用父类的构造方法,传递url数组,这里的url数组里面就是这个classloader能寻找的路径。若是在你的路径中寻找,这是你须要实现的逻辑,大部分仍是直接调用父类的方法,由于他已经知道路径了,不少时候你不须要去处理,java已经帮你实现了。
public class Loader extends URLClassLoader { public Loader(URL[] urls) { super(urls); } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { return super.loadClass(name); } }
这就是一个遵循双亲委托机制的classloader。很简单。
如何破坏双亲委托呢?这个你们已经明了了。就是改loadClass方法里加载的过程。举个例子,若是你先写个本身查找的方法放在super.loadClass(name)以前,那么已经不是默认的双亲机制了。这里必须介绍一个方法,就是加载类到内存的方法defineclass。具体再怎么加载,这个就不须要咱们管了。由于确实用不到那么多。
如何使用classloader
Thread.currentThread().setContextClassLoader(loader);
经过设置当前线程classloader来更改classloader,这种方法最经常使用,这样就简单的更改了classloader,之后这个线程加载类就靠你设置的classloader,再也不直接是appclassloader。
第二种用法用来测试classloader不错,就是直接调用你本身写的classloder的loadclass方法获取Class对象。
本身写的classloader是谁来加载?
这个不用想了,是app classloader,虽然你是classloader,可是对jvm而言,他只是个字节码文件罢了。他在app classloader的加载路径上。
类A非类A
因为classloader会出现一个颇有意思的问题,相似古代白马非马的问题。举个例子当一个类被两个classloader加载时,第一个classloader产生类A对象,传递给另外一个classloderA的声明,结果就出现转换出错的问题。
在java里,只有被同一个classloader加载的类才会被认为是同一个类,两个classloader都加载了类A,那么就会被认为是两个彻底不相干的类。(可是两个类A都继承B,用B对象的引用去接收赋值没问题,只是两个相同的类赋值这个类的声明才会有这个问题)。
总结
classloader的重点是你加载类的路径和文件,若是保证了路径和文件,那么classloader也就没啥了,由于剩下的彻底依靠父类方法就能够,除非你的处理须要修改其余方法。