classloader总结

classloader是什么

      我的理解classloader就是加载我们的类到内存的类,他主要就是寻找资源,即找到在他能搜索到的路径中,有没有我们的类。有的话就加载到内存。

系统的classloader

系统的classloader有三种

Bootstrap ClassLoader     负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等

Extension ClassLoader      负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class

App ClassLoader           负责加载当前java应用的classpath中的所有类。

双亲委托机制

    系统的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也就没啥了,因为剩下的完全依靠父类方法就可以,除非你的处理需要修改其他方法。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的ClassLoader命名空间是指在Android应用程序中加载不同组件(如Activity、Service、BroadcastReceiver等)时的类加载环境和隔离机制。在Android中,每个应用程序组件都有自己的ClassLoader实例,用于加载和管理其依赖的类。 ClassLoader命名空间的主要作用是隔离不同应用程序组件之间的类加载,防止类的冲突和污染。每个应用程序组件运行在独立的ClassLoader实例中,这样它们就能够加载和使用自己的类,而不会被其他组件中的类所影响。 ClassLoader命名空间还提供了类加载的灵活性和扩展性。可以通过ClassLoader的机制在不同的ClassLoader实例中加载不同版本的同一个类,从而避免了类的冲突。也可以使用自定义的ClassLoader实现自定义的类加载逻辑,例如从网络等外部来源加载类文件。 Android应用程序中的ClassLoader命名空间是由Android系统提供的ClassLoader框架实现的。在Android中,应用程序组件的ClassLoader实例是基于父类加载器(Parent ClassLoader)进行的,这样可以继承和共享父类加载器加载的类,提高类的加载效率和资源利用率。 总结来说,Android中的ClassLoader命名空间是为了实现应用程序组件之间的类加载隔离和灵活性而设计的,每个应用程序组件都有自己的ClassLoader实例,可以加载和管理自己的类。这种ClassLoader命名空间的设计使得Android应用程序能够在多组件环境下更加稳定和可扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值