黑马程序员_高新技术四(类加载器ClassLoader,自定义类加载器,类加载器高级实验应用)

来源:互联网 发布:zabbix windows不稳定 编辑:程序博客网 时间:2024/06/05 04:13

--------- android培训java培训、期待与您交流!---------

一.类加载器


 1.类加载器
  1)类加载器及其作用:
  字节码的原始信息存放在硬盘上的classpath指定的目录下,java程序用到某个类,虚拟机要先
  将该类的字节码加载到内存里,进行处理后得到的就是字节码。实现这个过程的机制就是类加载器,
  其作用就是加载类。
  2)类加载器BootStrap
  类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有
  第一个不是java类的类加载器,它就是BootStrap.
  BootStrp是JVM里的第一个类加载器,它不是java类,不需要被加载,它是嵌套在JVM内核里的,
  它是用C++写的二进制代码。
  3)java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定
  位置的类:
  1)类加载器及其作用:
  字节码的原始信息存放在硬盘上的classpath指定的目录下,java程序用到某个类,虚拟机要先
  将该类的字节码加载到内存里,进行处理后得到的就是字节码。实现这个过程的机制就是类加载器,
  其作用就是加载类。
  2)类加载器BootStrap
  类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有
  第一个不是java类的类加载器,它就是BootStrap.
  BootStrp是JVM里的第一个类加载器,它不是java类,不需要被加载,它是嵌套在JVM内核里的,
  它是用C++写的二进制代码。
  3)java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定
  位置的类:

    BootStrap,ExtClassLoader,AppClassLoader


  4)类加载器的树形结构
   BootStrap   -------> JRE/lib/rt.jar
     |
   ExtClassLoader -----> JRE/lib/ext/*.jar
     |
   AppClassLoader -----> CLASSPATH指定的所有jar或目录
     |
  MyClassLoader     --> 传智播客指定的特殊目录
 
2.类加载器的委托加载机制
  1)当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
  <1>首先当前线程的类加载器去加载线程中的第一个类。
  <2>如果类A中引用了类B,java虚拟机将使用加载类A的类装载器来加载类B。
  <3>还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。  
 2)每个类加载器加载类时,又先委托给其上级类加载器。
当所有父类包括BootTrap类加载器没有加载到类,回到发起者加载器,还加载不了,则抛出ClassNoFoundException,
3.ClassLoader类(java.lang)
  1) <1>类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。
    每个 Class 对象都包含一个对定义它的 ClassLoader 的引用。
    数组类的 Class 对象不是由类加载器创建的,而是由 Java 运行时根据需要自动创建
  <2>构造方法摘要 
    protected  ClassLoader() 
     使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器,将该加载器作为父类加载器。     protected             ClassLoader(ClassLoader parent) 
     使用指定的、用于委托操作的父类加载器创建新的类加载器。
    ClassLoader getParent() 
     返回委托的父类加载器。 
 2) 构造方法摘要 
   protected  ClassLoader() 
   使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器,将该加载器作为父类加载器。 
   protected  ClassLoader(ClassLoader parent) 
   使用指定的、用于委托操作的父类加载器创建新的类加载器。  
3) 方法摘要 
  protected  Class<?> defineClass(String name, byte[] b, int off, int len) 
      将一个 byte 数组转换为 Class 类的实例。 
  
  protected  Class<?> findClass(String name) 
      使用指定的二进制名称查找类。 
  protected  Class<?> findClass(String name) 
   使用指定的二进制名称查找类。 
   ClassLoader getParent() 
      返回委托的父类加载器。 
   static ClassLoader getSystemClassLoader() 
      返回委托的系统类加载器。 
   Class<?> loadClass(String name) 
      使用指定的二进制名称来加载类。 

3.自定义类加载器
1)定义原理:
  ClassLoader中的loadClass()方法是保证委托机制流程的方法,故只能继承,不能复写,查找类要用到
  的findClass需要复写,将得到的class文件的内容转成字节码的方法是defineClass().也不需要复写。
2)编写一个自定义的ClassLoader 对文件进行加密,解密。
public class MyClassLoader extends ClassLoader {               public MyClassLoader(String classDir){this.classDir = classDir;}public static void main(String[] args)throws Exception {// 从主函数的参数中获取源Class文件,和目标地址String srcPath = args[0];String desDir = args[1];FileInputStream fis = new FileInputStream(srcPath);String desFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);String desPath = desDir+"\\"+desFileName;FileOutputStream fos = new FileOutputStream(desPath);cypher(fis,fos);fis.close();fos.close();}//加密 解密方法public static void cypher(InputStream ips ,OutputStream ops)throws Exception{int b = 0;while((b = ips.read())!= -1){ops.write(b^0xff);}}private String classDir;@Override//重写findClass方法,loadClass不需要覆盖。protected Class<?> findClass(String name) throws ClassNotFoundException {String classFileName = classDir+"\\"+name.substring(name.lastIndexOf("."))+1 +".class";try {FileInputStream fis = new FileInputStream(classFileName);ByteArrayOutputStream bos = new ByteArrayOutputStream();cypher(fis,bos);byte[] bytes = bos.toByteArray();//把字节数组通过defineClass方法返回Class文件,return defineClass(bytes, 0, bytes.length);} catch (Exception e) {e.printStackTrace();}return super.findClass(name);}}

二.类加载器的一个高级问题的实验分析


Serverlet是由Tomcat自己的类加载器加载的。
他的目录关系是 
ExtClassLoader
AppClassLoader
StandardClassLoader
WebappClassLoader
 在eclipse中的演示步骤:
 1.创建web项目itcastweb
  右键--->New-->Web Project-->itcastweb
 2.创建web中的类Servlet(web中的类是特殊的类,其父类是Servlet,故可直接创建Servlet)
  在src上右键-->New-->Servlet-->
    package:cn.itcast.itcastweb.web.servlets(界面层)
    Name: MyServlet
    Superclass:javax.servlet.http.HttpServlet
 3.配置服务器
  选择web工程-->点击Project Deployments(在工具栏环表箭头的图标)-->Add-->Server:Tomcat 6.x -->Finish-->OK
  (配置完后在目录apache-tomcat-6.0\webapps下就有itcastweb文件夹)
 4.启动Tomcat,即双击startup.bat
 5.在浏览器中访问Tomcat服务器
  http://localhost:8080/itcastweb/servlet/MyServlet(这是项目内的路径)
  (查看内容:itcastweb-->webRoot-->WEB-INF-->web.xml-->source)
  -->访问的结果打印到了后台
 6.重载Tomcat,则会在浏览器显示Tomcat自己的类加载器:WebappClassLoader
 7.将MyServlet.java打成jar包输出到JDK下
  MyServlet.java-->右键-->Export-->java--JAR file-->Next-->Next-->Finish
  (输出的JDK版本要和Tomcat配置的JDK一致,可查看Tomcat的配置,即将startup.bat放在
   编辑器中打开:set JAVA_HOME=c:\java\JDK6.0)
 8.重启Tomcat
 9.在浏览器中再次查看,报错:没找到HttpServlet.
  (这是因为,这时的发起者加载器是ExtClassLoader,而HttpServlet不在Ext目录下)
 10.将HttpServlet的jar包也放在Ext目录下。
  HttpServlet是Tomcat提供的,在apache-tomcat-6.0\lib\servlet-api.jar,复制到JDK6.0\jre\lib\ext下。
 11.重启Tomcat(即将JVM重启)
 12.再在浏览器中访问
  此时显示的加载器便是ExtClassLoader了。
 注:要特别掌握配置服务器


 
原创粉丝点击