JVM是如何知道java.lang包中的类的?JVM又是如何知道我们应用中的类的?我们的应用中明明是有某个类, 但是JVM却抛出ClassNotFoundException,这是为什么?XxxImpl类已经实现了接口Xxx,但是却抛出XxxImpl does not extend from Xxx,这是为什么?使用类型转换时,可能会抛出 aa.bb.cc.XXX can not cast to aa.bb.cc,这又是为什么?等等诸多看似诡异情况,其实都是因为ClassLoader。

了解反射的人都知道每一个类都有一个Class对象与之对应,那么这个Class对象又是哪来的呢?

如果要了解Class的基本知识,可以参考:

http://blog.csdn.net/irelandken/article/details/7048817

http://tyrion.iteye.com/blog/1958814

http://www.blogjava.net/lihuaxajh/articles/94371.html

http://www.javaworld.com/article/2077332/core-java/get-a-load-of-that-name.html

http://www.javaworld.com/article/2075796/java-platform/java-101--class-and-object-initialization.html

我对ClassLoader的理解

下面是我看了这些博客、文章后,并自定义了一个ClassLoader进行测试后的理解:

1)ClassLoader加载一个类时,不会加载类中所有的类,而是在运行时根据要使用的类动态加载的,即按需加载。

2)ClassLoader加载一个类时,也会加载其父类(包括接口)

3)当前类A在运行时,类中要使用的其它的类(B,C,D类等),默认是由当前类A的加载器来加载的。

4)类型强制转换时,先判定是不是同一个类加载器,如果不是,就不能进行转换。一个对象A但往由BootstrapCLassLoader加载的类(A的父类或者接口)转换时,好像不遵循这个过程。

5)Thread#contextClassLoader可以用于在切换类加载器。

6)默认情况下,线程的上下文加载器采用的与父线程的上下文加载器是同一个。

7)Class.forName(“xxx”)、Xxx.class 的加载器,使用的都是当前类的类加载器。

下面是自定义类加载器

代码清单:

下面就对这些类做一个简单的说明:

StringUtil.java

StringUtil中只有两个方法,用于判断字符串空值。写这个类实在是没有必要,但是在测试中也可以看到效果的。

DebugUtil.java

只是为了打出一些信息。

Person.java

这是一个典型的Java Bean,没有什么可说的。

ClassLoaderTestRunner.java

这是业务类。从代码上看也是很简单的,只是加载了Person类,创建一个Person对象,输出一些信息。

这个类 既可以使用系统默认的类加载器加载测试(main方法),也可以使用自定义的类加载器来测试。

自定义ClassLoader

目前常用的加载机制有两种:委托加载机制、子类优先加载

1)委托加载机制loadClass()的流程:

(1) 判断是否已经加载这个类

(2) 如果没有加载,当前类加载器的父加载器加载,即执行loadClass()方法。

(3) 如果当前类加载器的所有父加载器都没有加载到就让当前加载器调用 findClass()加载。

2)子类优先加载器的流程:

(1) 判断是否已经加载这个类

(2) 当前类加载器直接加载类

(3) 加载不到才走父类加载流程。

JDK中默认的加载方式是1),也就是委托加载机制。

自定义类加载器,一般会重写loadClass、findClass。

delegate字段是用于指定是否使用默认的委托加载机制。

这是自定义的加载类的方法。流程是:

1)判断该加载器是否已经加载了这个类,为了避免重复的加载。

2)如果delegate=true,委托加载,就使用默认的加载方式。

3)如果delegate=false, 排除受保护的类,然后使用下面的自定义的findClass来加载类。上述过程如果出现了异常,仍然会使用默认的加载方法。

findClass是根据类名加载并定义一个Class对象。这个方法写的很粗糙,只是为了测试ClassLoader。

接下来就可以使用ClassLoaderTest.java来测试了:

关于这个测试的简单说明:

1)这个测试中的相关类,如String, UrlClassLoader, ClassLoader,Object, Thread,Runnable,Exception等都是由默认的系统加载器(SystemClassLoader)或者其父类(ExtClassLoader、BootstrapClassLoader)来加载的。当前这个运行时,这个类(ClassLoaderTest)的加载器是SystemClassLoader。

2)加载ClassLoaderTestRunner类时,使用的自定义的类加载器(也就是SystemClassLoader的子加载器)。加载ClassLoaderTestRunner类时,还会加载其父类,也就是Object类和Runable接口。

3)这个测试执行的过程:

(1) 创建一个自定义加载器实例,指定其父加载器为系统加载器。

(2) 加载类ClassLoaderTestRunner。

(3) 启动一个线程执行相关任务。

4)根据上述所说,如果将Object task = myAppClassLoader .loadClass( classFullName) . newInstance();

改为:

ClassLoaderRunner task= (ClassLoaderRunner) myAppClassLoader. loadClass( classFullName ) . newInstance();就会出错。

ClassLoaderRunner 是系统加载器加载的,myAppClassLoader是一个自定义加载器。所以两者不能进行类型的转换。

如果直接在这个类中使用自定义类加载器来加载Person类,也会出现错误。

如果有兴趣的话,可以根据我上面总结的内容,已经我的这个测试,自己分析一下子线程t执行过程中,哪些类是被自定义的类加载器加载的,哪些类是被系统加载器加载的,上述task执行的结果是什么?

如果有不理解的也可以参考:

参考

http://blog.csdn.net/irelandken/article/details/7048817

http://tyrion.iteye.com/blog/1958814

http://www.blogjava.net/lihuaxajh/articles/94371.html

http://www.javaworld.com/article/2077332/core-java/get-a-load-of-that-name.html

http://www.javaworld.com/article/2075796/java-platform/java-101--class-and-object-initialization.html

Java Se:自定义ClassLoader的更多相关文章

  1. JAVA 利用JNI加密class文件/自定义ClassLoader 类

    利用 JNI 对bytecode 加密.不影响java程序员的正常开发.09年的时候写的,现在拿出来晒晒————————————————————————————混淆才是王道,如果混淆再加密就更酷了.. ...

  2. java自定义classloader引发的思考

    引用 java类的热替换 classloader机制 如下图所示,java的classloader是双亲委派机制.会首先从父classloader加载指定的class,如果加载不到才会从子classl ...

  3. Java高级进阶:自定义ClassLoader

    假如我们的类不在classpath下,而我们又想读取一个自定义的目录下的class,如果做呢? 读取自定义目录的类 示例读取c:/test/com/test.jdk/Key.class这个类. pac ...

  4. Java复习总结(二)Java SE 面试题

    Java SE基础知识 目录 Java SE 1. 请你谈谈Java中是如何支持正则表达式操作的? 2. 请你简单描述一下正则表达式及其用途. 3. 请你比较一下Java和JavaSciprt? 4. ...

  5. 使用自定义 classloader 的正确姿势

    详细的原理就不多说了,网上一大把, 但是, 看了很多很多, 即使看了jdk 源码, 说了罗里吧嗦, 还是不很明白: 到底如何正确自定义ClassLoader, 需要注意什么 ExtClassLoade ...

  6. 《写给大忙人看的java se 8》笔记

    现在才来了解java8,是不是后知后觉了点? 新的编程技术,个人不喜欢第一时间跟进. 待社区已有实践积淀再切入似乎更划算些? 一点点精明的考虑. 不多说,上代码. //读<写给大忙人看的java ...

  7. Java Se:Java Security

    Java API中有很多都使用了SecurityManager,这到底是什么玩意?最近看公司的产品的源码,也有不少SecurityManager.AccessControlContext等相关的代码, ...

  8. 图解classloader加载class的流程及自定义ClassLoader

    图解classloader加载class的流程及自定义ClassLoader 博客分类: JVM JavaJVM虚拟机EXTSUN /** *  转载请注明作者longdick    http://l ...

  9. Java SE 6 新特性: 对脚本语言的支持

    2006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马).跟 Tiger(Java SE 5)相比,Musta ...

随机推荐

  1. 【C#进阶系列】14 字符、字符串和文本编码

    本来写了蛮多的,结果因为重启了一下机器导致写的东西都没了. 然后再回想之前写了什么,反而更像是把知识提炼了一番. 关于字符 字符什么的只要记住.net里面都用的Unicode编码就好.字符和数字之间转 ...

  2. Document

    每个载入浏览器的 HTML 文档都会成为 Document 对象.Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问.提示:Document 对象是 Window 对象的一 ...

  3. Java并发编程:进程和线程之由来

    Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...

  4. HTML5开发IDE介绍

    开发html5的工具可供选择的有:Intellij Idea.Eclipse.WebStorm三个软件.在PC端与手机端,同步测试HTML5网页.测试发布软件:FileZilla JavaScript ...

  5. Struts 2.3.24源码解析+Struts2拦截参数,处理请求,返回到前台过程详析

    Struts2官网:http://struts.apache.org/ 目前最新版本:Struts 2.3.24 Struts1已经完全被淘汰了,而Struts2是借鉴了webwork的设计理念而设计 ...

  6. 关于JAVA堆栈的简单说明

    关于堆栈的说明: 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 堆栈的优劣势 栈: 优势:存取 ...

  7. Atitit. 获取cpu占有率的 java c# .net php node.js的实现

    Atitit. 获取cpu占有率的 java c# .net php node.js的实现 通过wmic接口获取cpu占有率 C:\Users\Administrator.ATTILAXPC188&g ...

  8. 使用异步存储提升 Web 应用程序的离线体验

    localForage 是一个 JavaScript 库,通过使用简单的.类似 localStorage 风格的 API 实现异步存储,帮助你提升 Web 应用程序的离线经验(通过 IndexedDB ...

  9. JS高程2.在HTML中使用Javascript(2)

    1.延迟脚本defer 在<script>元素中设置defer属性,相当于告诉浏览器立即下载,但是延迟执行.<script>中的脚本会延迟到浏览器遇到</html> ...

  10. border-radius如何兼容IE

    目前而言firefox,opera,chrome等主流浏览器都已经支持border-radius属性,唯独IE8以及之前. 解决办法就是在用的border-radius属性的后面加上:behavior ...