关于java类加载器理解及畅谈

来源:互联网 发布:office2007卸载软件 编辑:程序博客网 时间:2024/06/05 17:53

每一种技术的出现无一不例外都是有现实的需求,就像java这门语言的诞生,正是因为互联网的发展,移动智能设备的诞生,网民数量的爆炸式增加,随之而来的就是软件业的兴起。此时传统汇编,C语言的复杂性就成了制约软件发展的门槛,于是跨平台,面向对象的java应运而生;同理web技术的诞生,90年代互联网诞生之初,那时候的互联网还只属于少数人(科研机构),当时的web只是用来彼此交流一些静态文档,随之诞生了HTTP协议,到今天的servlet动态网页技术,以及web基础设施tomcat,jetty等web服务器。

上面说的有点跑题,每次写博客总能勾起我对一些技术变化的感慨,哈哈。因为最近公司项目的需求,最近对java的类加载机制恶补了一下,下面做一些记录,希望同样对此感兴趣的小伙伴有所受益,也方便自己以后查阅(希望csdn永存)。

首先我们列举一下哪些需求可能会用到java classLoader技术(通常情况下,我们开发中很少直接去操作类加载器),以下是我目前能想到的一些用到classLoader 的场合,大家可以在评论里面补充(工作时间越长越发现独学不如众学,欢迎大家拍砖)

场景一:热部署

场景二:代码加密

场景三:类层次划分



在讲解类加载器之前我们心里一定要对类加载的机制有一个感性的认识:
(1)虚拟机把描述类的数据从(2)Class文件加载到内存,并对(3)数据进行校验,转化解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制。
上面这句话的信息量很大呦(如果读完上面这句话你没有任何感觉,那你就需要学习一下虚拟机了,虽然平时编码很少用到,它比较偏底层。但是如果你了解了上层的内功心法,各家功夫不过是招式套路而已。)。为了更好的理解下面将要说的ClassLoader,有必要对上面的概念详细理解一下:
(1):虚拟机:什么叫虚拟机?限于篇幅,这里简单介绍。虚拟机是java生态中非常重要的一环,它是连接源码跟机器码的桥梁。没有它,java所谓的夸平台就是一句空话。打个比方:你会多国语言,当你用多种语言交流时如何让不同国家的人都听懂呢,那我们就需要多个翻译或者一个会多国语言的翻译。这里面的翻译就是虚拟机,不同的平台都有自己的虚拟机(翻译),所以我们java只跟虚拟机打交道,具体平台的虚拟机跟平台打交道,这也是我们平时写程序一贯主张的松耦合,提高系统扩展性思想的体现。
(2):class文件:在java技术体系中对class文件的格式,内容有相关规定,这里不在详细说。你只需要知道,我们写的java文件经编译以后都转化为了该平台对应虚拟机的字节码(class文件),里面记录了我们的类信息(继承,接口,访问权限...).jvm规范中说加载class文件,只要是符合class格式标准的文件就可以被虚拟机所用,对class文件的来源并没有做限制。此处可以做很多文章呦,好多很炫玩法依据都在于此呦!

类加载器的双亲委派模型:

双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都必须有自己的父类加载器,类加载器间的父子关系不会以继承关系实现,而是以组合的方式来复用父类加载的代码。


双亲委派模型的工作过程:

当一个类加载器收到类加载请求的时候,它会首先把这个请求委托给父类加载器去执行,因此所有的类加载请求最终都会传送到顶层的启动类加载器中(注意:启动类加载器默认只会加载%JAVA_HME%/lib下的jar,而且是按照文件名字识别,自定义jar包不会加载,安全考虑!),只有当父类加载器也无法找到时才会交给自己去加载。
  加载逻辑可以通过ClassLoader类中的loadClass找到,所以在自定义类加载器时需要继承ClassLoader或者通过继承URLClassLoader来间接继承ClassLoader,但是建议不要重写loadClass方法,破坏双亲委派的加载逻辑。

ClassLoader类中标准类加载逻辑:
protected synchronized Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException{//是否已经加载过Class c = findLoadedClass(name);if(c == null){try{ if(parent != null){ c= parent.loadClass(name,false);}else{c = findBootstrapClassOrNull(name);//委托启动类加载器}}catch(ClassNotFoundException e){//如果父类加载抛出异常,使用自己加载c= findClass(name);}if(c == null){c = findClass(name);}if(resolve){resolveClass(name);}return c;

如果要自定义类加载器,用户可以重写findClass方法,不建议重写loadClass方法(会破坏双亲委派模型)

 写这部分发现涉及的东西很多,这篇就先写到这里,随后关于类加载器这块我会继续写。。。。。。。。


























0 0