java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
本文主要介绍了 java 类加载与自定义类加载器。具有一定的参考价值,下面跟着小编一起来看下吧
类加载
所有类加载器,都是 ClassLoader 的子类。
类加载器永远以. class 运行的目录为准。
读取 classpath 根目录下的文件有以下几种方式:
1 在 Java 项目中可以通过以下方式获取 classspath 下的文件:
- public void abc() {
- //每一种读取方法,使用某个类获取Appclassloader
- ClassLoader cl = ReadFile.class.getClassLoader();
- URL url = cl.getResource("a.txt");
- System.err.println("url1 is:" + url.getPath());
- //第二种方式,直接使用ClassLoader
- URL url2 = ClassLoader.getSystemResource("a.txt");
- System.err.println("url2 is:" + url2.getPath());
- }
在 Tomcat 中 tomcat 又声明了两个类载器:
StandardClassLoader– 加载 tomcat/lib/*.jar - serlvetapi.jar
webappclassloader / 加载 tomcat/webapps/project/web-inf/lib/*.jar && web-inf/classes/*.class
在任何的项目中,获取类的加载器都应该使用以下方式:
SomeClass(你写的).class.getClassLoader().getResource ;获取到这个类的类加载器
在 java 项目中是:AppClassLoader
在 Web 项目中:WebAppClassLoader
测试父类加载器:
- public class OneServlet extends HttpServlet {
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- ClassLoader loader = OneServlet.class.getClassLoader();//WebAppClassLoader
- int index=1;
- while(loader!=null){
- System.err.println((index++)+"类加载器是:"+loader.getClass());
- loader=loader.getParent();//获取父类加载器
- }
- }
- }
运行的结果:
- 类加载器是:class org.apache.catalina.loader.WebappClassLoader
- 类加载器是:class org.apache.catalina.loader.StandardClassLoader
- 类加载器是:class sun.misc.Launcher$AppClassLoader
- 类加载器是:class sun.misc.Launcher$ExtClassLoader
自定义类加载器
JDK 以哪一个类加载器读取 A 类的字节码,则 A 类就是被哪一个类加载器加载 的。
一个同名的类,是否可以相互转换,要看是否是在同个类加载器中。
- package cn.hx.demo;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.InputStream;
- import java.net.URL;
- public class MyClassLoader2 extends ClassLoader {
- /**
- * name:cn.itcast.demo.Person
- * 根据包名找到.class文件
- * cn.itcast.demo.person = > cn/itcast/demo/Person.class
- */
- public Class < ?>findClass(String name) throws ClassNotFoundException {
- String classNameWithPackage = name;
- Class < ?>cls = null;
- try {
- //先将
- name = name.replace(".", "/");
- name += ".class";
- //确定目录
- URL url = MyClassLoader2.class.getClassLoader().getResource(name);
- System.err.println(">>:" + url.getPath());
- File file = new File(url.getPath());
- InputStream in =new FileInputStream(file);
- //读取这个.class文件的字节码
- byte[] b = new byte[ in .available()]; //直接声明这个字节大小为这个文件的大小
- int len = in.read(b); //len=621
- System.err.println(len);
- /**
- * 第一个参数是类名
- */
- cls = defineClass(classNameWithPackage, b, 0, len);
- } catch(Exception e) {
- e.printStackTrace();
- }
- return cls;
- }
- }
测试类自定义类加载器
- public class ClassLoaderDemo {
- public static void main(String[] args) throws Exception {
- MyClassLoader2 mc = new MyClassLoader2();
- Class cls = mc.findClass("cn.itcast.demo.Person");
- Object o = cls.newInstance();
- System.err.println("toString:" + o + "," + o.getClass().getClassLoader());
- //直接使用peron是 AppClassLoader
- System.err.println(">>:" + Person.class.getClassLoader());
- //由于o是由mc加载的。而Person是由App加载的,所有不可以转换=来自于两个不同的加载器
- //Person p = (Person) o;//类型转换错误ClassCastException
- //System.err.println(p);
- }
- }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持 PHPERZ!
来源: http://www.phperz.com/article/17/1218/358728.html