当前位置: 移动技术网 > IT编程>开发语言>Java > java 类加载与自定义类加载器详解

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

2019年07月22日  | 移动技术网IT编程  | 我要评论
类加载 所有类加载器,都是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

测试父类加载器:

 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);
  }
}

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网