classloader总结

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也就没啥了,由于剩下的彻底依靠父类方法就能够,除非你的处理须要修改其余方法。

相关文章
相关标签/搜索