类的加载器的各种方式总结

 水平有限,欢迎更正

类加载的原理:就是通过一个类包的全限定名来加载某个类。

至于类的加载原理及加载顺序,可以上网查找,在这里就不累述了。

类加载加载类的方式

1.      直接new 一个ClassLoader ,实现内部匿名类

要实现加载类,可以重写loadClass方法,然后调用ClassLoader的defineClass方法;比如:

ClassLoader  myClassLoader = new ClassLoader() {

           @Override

           public Class<?> loadClass(String name) throwsClassNotFoundException{

       try {

                  String fileName = name.substring(name.lastIndexOf(".")+1)+".class";

                  InputStream is = LoadClass.class.getResourceAsStream(fileName);

                  if (is==null) {

                     return super.loadClass(name);

                  }

                  byte[] b = new byte[is.available()];

                  is.read(b);

                  return defineClass(name, b, 0, b.length);

              } catch (Exception e) {

                  throw new ClassNotFoundException(name);

              }

           }

       };

如果要想加载package下面的某个类,需要这样写

Object obj =myClassLoader.loadClass(PackageName+类名);

例如:myClassLoader.loadClass("feinno.proxy.entityClass."+”Flags”);

此时类加载器的结构为

myClassLoaderà sun.misc.Launcher$AppClassLoader@1bcfbeàsun.misc.Launcher$ExtClassLoader@3f3fbd

解释为本类的加载器,它的父加载器为AppClassLoader,AppClassLoader的父加载器为ExtClassLoader。

这个加载器的加载顺序是myClassLoader要加载某个类,就会请求父加载器加载,若此时父加载器也找不到,则会请求父加载器的父加载器加载,如此下去仍找不到会抛出异常ClassNotFoundException,然后自己再去尝试加载。

2.      通过URL来加载,可以加载指定的URL下的类

String  filePath =”xxxxxxxxxx”;

URL[] urls = new URL[] {new URL(filePath)};(这个里面可以放多个URL)

URLClassLoader ul = new URLClassLoader(urls);

Class c =ul.loadClass("feinno.proxy.entityClass"+"."+name);

这样就可以通过指定的URL,然后通过查找整个package+name就可以找到自己要加载的类。最后ul要关闭。

3.      继承ClassLoader ,类似方法2,也是通过URL来加载类,但是获取类又采用方法1的形式

例如:

    String filePath = “xxxxxxxxxxxxxxxxxx”;

    File file = new File(filePath);

    URL url = file.toURL();

    URLConnection con =url.openConnection();

    InputStream is =con.getInputStream();

    if (is==null) {

        System.out.println("null");

        getSystemClassLoader();

    }

    ByteArrayOutputStreambaos = new ByteArrayOutputStream();

    bytebuf[] = new byte[1024];

    //读取文件流

    for(int i = 0; (i = classIs.read(buf)) != -1; ) {

          baos.write(buf, 0, i);

      }

    classIs.close();

    baos.close();

                  

                  

   //创建新的类对象

  byte[]data = baos.toByteArray();

  defineClass(name, data, 0, data.length);

4.      可以获取到类的字节流,但是要第三方类包asm-all-3.3.1.jar,很简单的两句代码就可以获取到类的字节流,然后打印出该类变量,如下:

ClassReader reader = new ClassReader(newFileInputStream(filePath+"main/java/feinno/proxy/entityClass/"+name+".class"));

 ClassNodecn = new ClassNode();

                  

 reader.accept(cn,0);

 Field[]fiels=cn.getClass().getDeclaredFields();

 System.out.println("@@"+fiels.length);

 for(inti=0;i<fiels.length;i++){

                   

    System.out.println(fiels[i]);

 }

5.      其他方法获取类如Class.forName(“xxx”)等等,可以看jdk API文档

6.      一般用URLClassLoader时,它的类加载结构为java.net.URLClassLoader@13e846f,父加载器为AppClassLoader,ExtClassLoader,null。Web工程的类加载器的结构为WebappClassLoader,StandardClassLoader,AppClassLoader,ExtClassLoader,null(事实上是启动类加载器,也就是启动时的bootstrap classloader)。而上层类加载器能加载的jar包是一定的,所以一个web工程里如果用到URLClassLoader时,很可能会包类与类转换错误等,此时解决办法就是把URLClassLoader类加载器直接定位到WebappClassLoader,然后再反射到addURL(),再把指定的URL加到URLClassLoader中,方法如下:

privatestatic Method addURL = initAddMethod();

private static  URLClassLoader classLoader = (URLClassLoader) ResolveJAR.class.getClassLoader();//为了和把类加载器调成同一个



/**

     * 初始化addUrl 方法.

     * @return 可访问addUrl方法的Method对象

     */

 privatestatic Method initAddMethod() {

        try{

           Method add = URLClassLoader.class.getDeclaredMethod("addURL",new Class[] { URL.class });

           add.setAccessible(true);

           return add;

        }

        catch(Exception e) {

           throw new RuntimeException(e);

        }

    }

           /**

     * 通过filepath加载文件到classpath。

     * @paramfilePath 文件路径

     * @returnURL

     * @throwsException 异常

     */

    privatestatic void addURL(URL url) {

        try{

           addURL.invoke(classLoader, new Object[] { url });

        }

        catch(Exception e) {

        }

    }

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值