zoukankan      html  css  js  c++  java
  • classloader类加载器

      与普通程序不同的是,Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。   JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,BootstrapClassLoader是用本地代码实现的,它负责加载核心JavaClass(即所有 java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由BootstrapClassLoader加 载;其中Extension ClassLoader负责加载扩展的Javaclass(例如所有javax.*开头的类和存放在JRE的ext目录下的 类),ApplicationClassLoader负责加载应用程序自身的类。   当运行一个程序的时候,JVM启动,运行bootstrapclassloader,该 ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加载),然后调用 ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的 加载流程。   注: 学ClassLoader看OSGI

    编辑本段什么时候加载类?

       什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用ApplicationClassLoader加 载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这 个ClassLoader来加载类B。JVM按照运行时的有效执行语句,来决定是否需要装载新类,从而装载尽可能少的类,这一点和编译类是不相同的。   Why use your own ClassLoader?   似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?   因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到:   1)在执行非置信代码之前,自动验证数字签名   2)动态地创建符合用户特定需要的定制化构建类   3)从特定的场所取得java class,例如数据库中   4) 等等   事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息。   目前的应用服务器大都使用了ClassLoader技术,即使你不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用。

    编辑本段类加载器的树状结构 & 委托代理模式

       当你决定创建你自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个 ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定 ClassLoader.getSystemClassLoader()为父对象。   所以当创建自己的Class Loader时,只需要重载findClass()这个方法。

    编辑本段卸载? 重载?

       当一个javaclass被加载到JVM之后,它有没有可能被卸载呢?我们知道Win32有FreeLibrary()函数,Posix有 dlclose()函数可以被调用来卸载指定的动态连接库,但是Java并没有提供一个UnloadClass()的方法来卸载指定的类。   在Java中,java class的卸载仅仅是一种对系统的优化,有助于减少应用对内存的占用。既然是一种优化方法,那么就完全是JVM自行决定如何实现,对Java开发人员来说是完全透明的。   在什么时候一个java class/interface会被卸载呢?Sun公司的原话是这么说的:"class or interfacemay be unloaded if and only if its class loader is unreachable. Classesloaded by the bootstrap loader may not be unloaded."   事实上我们关心的不是如何卸载类的,我们关心的是如何更新已经被加载了的类从而更新应用的功能。JSP则是一个非常典型的例子,如果一个JSP文件被更改了,应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求。   其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一 个类,就会得到异常(java.lang.LinkageError: duplicate classdefinition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它, 因为它可能还有实例正在被使用,只要相关的实例都被内存回收了,那么JVM就会在适当的时候把不会再使用的类卸载。   使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类.   典型的例子有, 通过线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派.   大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。   当然, 好东西都有利弊. 使用线程上下文加载类, 也要注意, 保证多根需要通信的线程间的类加载器应该是同一个, 防止因为不同的类加载器, 导致类型转换异常(ClassCastException).

  • 相关阅读:
    利用相关的Aware接口
    java 值传递和引用传递。
    权限控制框架Spring Security 和Shiro 的总结
    优秀代码养成
    Servlet 基础知识
    leetcode 501. Find Mode in Binary Search Tree
    leetcode 530. Minimum Absolute Difference in BST
    leetcode 543. Diameter of Binary Tree
    leetcode 551. Student Attendance Record I
    leetcode 563. Binary Tree Tilt
  • 原文地址:https://www.cnblogs.com/carbs/p/2576841.html
Copyright © 2011-2022 走看看