欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java 类加载与自定义类加载器详解

程序员文章站 2024-03-08 16:51:22
类加载 所有类加载器,都是classloader的子类。 类加载器永远以.class运行的目录为准。 读取classpath根目录下的文件有以下几种方式: 1 在j...

类加载

所有类加载器,都是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

java 类加载与自定义类加载器详解

测试父类加载器:

 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();//获取父类加载器
    }
  }
}

运行的结果:

1类加载器是:class org.apache.catalina.loader.webappclassloader
2类加载器是:class org.apache.catalina.loader.standardclassloader
3类加载器是:class sun.misc.launcher$appclassloader
4类加载器是: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);
  }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!