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,这就是一个程序最基本的加载流程。 【bootstrap->extclassloader->application classloader】
------------------------------------------混个鸟------------------------------------------------

      什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用ApplicationClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B。JVM按照运行时的有效执行语句,来决定是否需要装载新类,从而装载尽可能少的类,这一点和编译类是不相同的。 
      
似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?
  因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到:
  1)在执行非置信代码之前,自动验证数字签名
  2)动态地创建符合用户特定需要的定制化构建类
  3)从特定的场所取得java class,例如数据库中
  4) 等等
  事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息。
-------------------------------------------混个先------------------------------------------
  当你决定创建你自己的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 interface may be unloaded if and only if its class loader is unreachable. Classes loaded by the bootstrap loadermay not be unloaded."【bootstrap加载的类是无法卸载的】

      其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate classdefinition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它,因为它可能还有实例正在被使用,只要相关的实例都被内存回收了。那么JVM就会在适当的时候把不会再使用的类卸载。【在jsp重新编译了之后,就是重新使用了一个classloader来加载这个新编译的jsp的class。】

-----------------------------------------------------------------------------------------------------

      【ext classloader 和app classloader 都继承了URLClassLoader。】

      既然有那么多加载器,那么它们的加载顺序是怎么样的呢?JVM当加载类的时候,会先看一下当前类是不是已经被加载了,如果加载了就返回。如果没,就调用父类的加载器来加载类。如果父类的类加载器是null就调用bootsttap classloader来加载。这就是父类委托,因此在加载的时候是先从bootstrap classloader开始查找,一层层往下找。【因为委托最终会到达bootstrap这一层】

-----------------------------------------------------------------------------------------------------------

      看了那么多源代码那么怎么实现自己的classloader呢,有什么作用呢,对于一些我们不想被反编译的类,我们可以调用加密技术将类加密。在使用的时候只要用自定义的classloader解密就好了。

      实现自己的classloader有两种方法:

第一种是继承ClassLoader方法主要是用FileInputStream读取class文件。然后用defineClass方法返回加载的类。

第二种是 URLClassLoader 加载jar文件,然后调用loaderclass查找类。

      记得不同的classloader加载的类,之间是有某种隔阂的。记得不是很清楚了,,,,慢慢再查查资料

------------------------------------------

还需要确认一下,defineclass和findclass的区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值