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
测试父类加载器:
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); } }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!