黑马程序员之类加载器
2013-06-16 11:22
134 查看
------- android培训、java培训、期待与您交流! ----------
一,类加载器:加载类的工具。
在java程序里,用到一个类,出现类名,JVM首先要把类的字节码加载到内存中,通常类的字节码的原始信息存放在classpath指定目录下,把.classpath加载到硬盘中,再对它进行一些处理,处理成字节码。
把.class文件从硬盘加载进来,然后进行一些处理,这些工作由类加载器完成。
类加载器本身也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。这个类加载器很特殊,它不是java类,不需要被其他类加载器加载,它是嵌套在JVM内核里的,JVM一启动的时候,它就已经在里面了。它是由C++语言写的一段二进制代码。
二,ExtClassLoaer专门加载JRE/lib/ext/*.jar的jar包。
父亲能够找到,则由父亲加载,否则再由子类加载。
每一个类加载器都会有一个父亲,才能挂到JVM的类树上去,组成树状结构。
三,类加载器的委托机制:
①当JVM用到一个类,那么它到底派出哪个类加载器去加载呢?
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,JVM将使用加载A的类加载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上一级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
②面试题:能不能自己写一个类叫java.lang.System?可以,写了也是白写,自己写了放在classPath下。但是委托机制会委托给祖宗类,祖宗类就会加载上System类,这样总是使用系统提供的System类,永远不会用到自己写的System类。当然可以自己编写类加载器,绕过系统的类加载器。
四,自定义类加载器必须继承一个抽象类ClassLoader。它有一个loadClass方法,这个方法内部会去找它的父类,返回后再执行findClass。子类只需要覆盖findClass方法。
父类ClassLoader-->loadClass/findClass/得到class文件的二进制数据-->使用defineClass方法转换成字节码(也就是class对象)
五,模板方法设计模式:父类中规定大体框架,所有子类都需要实现的代码,写在父类中,各个子类需要实现不同的功能的代码,父类中定义为抽象的,具体实现的由子类实现。
六,类加载器的一个高级问题分析:
新建一个web工程,建一个servlet,打印当前类的类加载器的名字及它的祖辈类。代码如下:
部署项目后,运行结果:
org.apache.catalina.loader.WebappClassLoader
org.apache.catalina.loader.StandardClassLoader
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
可见,当前类是被tomcat自己的类加载器加载的,org.apache.catalina.loader.WebappClassLoader
然后,再做个试验,把刚才的MyServlet导成jar包,放到当前使用的jdk目录下,也就是tomcat使用的jdk目录下,我自己的是C:\Program Files\Java\jdk1.6.0_02\jre\lib\ext\MyServlet.jar,然后再在IE地址栏输入http://localhost:8080/fightingweb/servlet/MyServlet运行,结果报错如下:
如图所示,提示HttpServlet类找不到,分析原因:
先明确一点:如果类A中引用了类B,JVM将使用加载A的类加载器来加载类B。
刚开始,MyServlet是由tomcat自己的类加载器加载的,即用WebAppClassLoader加载的,在加载的过程中发现MyServlet引用了HttpServlet,所以需要加载HttpServlet,WebAppClassLoader类可以成功加载HttpServlet,所以程序正常,没有报错。
后来为什么报错了呢?
后来把MyServlet导出jar包到ext目录下,则使用ExtClassLoader加载,而ExtClassLoader加载HttpServlet的过程中,先委托自己的父类,父类没有找到,所以自己加载,自己又不能加载,所以就报错了。
如何解决呢?
把HttpServlet所在的jar包也放到ext目录下,重启tomcat,就可以了。
运行结果:sun.misc.Launcher$ExtClassLoader
一,类加载器:加载类的工具。
在java程序里,用到一个类,出现类名,JVM首先要把类的字节码加载到内存中,通常类的字节码的原始信息存放在classpath指定目录下,把.classpath加载到硬盘中,再对它进行一些处理,处理成字节码。
把.class文件从硬盘加载进来,然后进行一些处理,这些工作由类加载器完成。
类加载器本身也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。这个类加载器很特殊,它不是java类,不需要被其他类加载器加载,它是嵌套在JVM内核里的,JVM一启动的时候,它就已经在里面了。它是由C++语言写的一段二进制代码。
二,ExtClassLoaer专门加载JRE/lib/ext/*.jar的jar包。
父亲能够找到,则由父亲加载,否则再由子类加载。
每一个类加载器都会有一个父亲,才能挂到JVM的类树上去,组成树状结构。
三,类加载器的委托机制:
①当JVM用到一个类,那么它到底派出哪个类加载器去加载呢?
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,JVM将使用加载A的类加载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上一级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
②面试题:能不能自己写一个类叫java.lang.System?可以,写了也是白写,自己写了放在classPath下。但是委托机制会委托给祖宗类,祖宗类就会加载上System类,这样总是使用系统提供的System类,永远不会用到自己写的System类。当然可以自己编写类加载器,绕过系统的类加载器。
四,自定义类加载器必须继承一个抽象类ClassLoader。它有一个loadClass方法,这个方法内部会去找它的父类,返回后再执行findClass。子类只需要覆盖findClass方法。
父类ClassLoader-->loadClass/findClass/得到class文件的二进制数据-->使用defineClass方法转换成字节码(也就是class对象)
五,模板方法设计模式:父类中规定大体框架,所有子类都需要实现的代码,写在父类中,各个子类需要实现不同的功能的代码,父类中定义为抽象的,具体实现的由子类实现。
六,类加载器的一个高级问题分析:
新建一个web工程,建一个servlet,打印当前类的类加载器的名字及它的祖辈类。代码如下:
package cn.itcast.itcastweb.web.servlets; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); ClassLoader loader = this.getClass().getClassLoader(); while(loader!=null){ out.println(loader.getClass().getName()+"<br />"); loader=loader.getParent(); } out.close(); } }
部署项目后,运行结果:
org.apache.catalina.loader.WebappClassLoader
org.apache.catalina.loader.StandardClassLoader
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
可见,当前类是被tomcat自己的类加载器加载的,org.apache.catalina.loader.WebappClassLoader
然后,再做个试验,把刚才的MyServlet导成jar包,放到当前使用的jdk目录下,也就是tomcat使用的jdk目录下,我自己的是C:\Program Files\Java\jdk1.6.0_02\jre\lib\ext\MyServlet.jar,然后再在IE地址栏输入http://localhost:8080/fightingweb/servlet/MyServlet运行,结果报错如下:
如图所示,提示HttpServlet类找不到,分析原因:
先明确一点:如果类A中引用了类B,JVM将使用加载A的类加载器来加载类B。
刚开始,MyServlet是由tomcat自己的类加载器加载的,即用WebAppClassLoader加载的,在加载的过程中发现MyServlet引用了HttpServlet,所以需要加载HttpServlet,WebAppClassLoader类可以成功加载HttpServlet,所以程序正常,没有报错。
后来为什么报错了呢?
后来把MyServlet导出jar包到ext目录下,则使用ExtClassLoader加载,而ExtClassLoader加载HttpServlet的过程中,先委托自己的父类,父类没有找到,所以自己加载,自己又不能加载,所以就报错了。
如何解决呢?
把HttpServlet所在的jar包也放到ext目录下,重启tomcat,就可以了。
运行结果:sun.misc.Launcher$ExtClassLoader
相关文章推荐
- 黑马程序员之类加载器
- 黑马程序员_高新技术之类加载器
- 黑马程序员-JAVA基础加强之类加载器
- 黑马程序员---java高新技术之类加载器
- 黑马程序员————JAVA之类加载器
- 黑马程序员之类加载器和动态代理
- 黑马程序员——java加强之类加载器
- 黑马程序员--【强哥笔记】系列之Java高新技术笔记之类加载器(第7天)
- 黑马程序员----JAVASE高级部分之类加载器
- 黑马程序员-Java高新技术之类加载器和代理
- 黑马程序员-----java提高之类加载器&代理
- 黑马程序员_java基础之类加载器解析
- 黑马程序员_基础加强之类加载器
- 黑马程序员_ java高新之类加载器
- 黑马程序员之Java基础加强之类加载器
- 18--黑马程序员--基础加强之类加载器
- 黑马程序员---java高新技术之类加载器
- 黑马程序员---高新技术之类加载器
- 黑马程序员-Java基础加强之类加载器
- 黑马程序员—JAVA高新技术之类加载器、动态代理