JavaWeb学习之——ClassLoader
博客专区 > lizo 的博客 > 博客详情
JavaWeb学习之——ClassLoader
lizo 发表于10个月前
JavaWeb学习之——ClassLoader
  • 发表于 10个月前
  • 阅读 13
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   

概述

在java中,ClassLoader负责把一个java类加载进Java虚拟机。为了防止重复加载和安全性方便的考虑,ClassLoader是具有层次结构的。

1.ClassLoader类

ClassLoader的主要方法包括:

1.1 defineClass

    protected final Class<?> defineClass(String name, byte[] b, int off, int len)
        throws ClassFormatError
    {
        return defineClass(name, b, off, len, null);
    }

通过defineClass是将byte数组转换为JVM能够识别的对象,可以看出,字节数组可以来自本地,网络等途径

1.2 findLoadedClass

    protected final Class<?> findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }

通过类的全名来加载一个类

1.3 loadClass

    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先检查class是否已经加载
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // 当父classLoader没有加载的成功的时候抛出异常
                }

                if (c == null) {
                    // 如果还还加载成功,试图调用findClass来加载类
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // 记录状态
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

可以看出,加载类的时候都是先从父类中加载

1.3 findClass

    protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }

findClass默认是没有任何实现的,只是抛出异常,因此我们可以覆盖该方法, 重写我们自己的类加载途径

代码例子:怎么使用classLoader加载自定义byte数组并通过反射调用其中方法

https://git.oschina.net/null_584_3382/java-web-example/tree/master

2. ClassLoader等级加载机制

从文章前面的描述中,可以看出 class loader在加载类的时候,优先是从其父加载器中加载,并且每个Class Loader 都有一个字段指向其父加载器(如果没有指定默认为AppClassLoader)

ClassLoader的层次结构:

上面的图是随便找的,下面简单介绍一下

2.1 BootStrap ClassLoader

这个类是为JVM自己服务的,加载JVM自身工作所需要的类,这个类完全是由JVM自己控制的。该类其实并不遵守前面所规定的等级加载制度。这个类即没有父加载器,也没有子加载器。

2.2 ExtClassLoader 

这个加载器主要用于加载 java.ext.dirs目录下的类,也算是一种特殊的类加载器,他是往上能追溯到的最高加载器

2.3 AppClassLoader

这个类就是专门为我们使用的,他的父加载器ExtClassLoader ,所有在ClassPath下的类都由他加载(前提你没有定义其他自己的ClassLoader)。我们自己实现的ClassLoader的父加载器就是这个类。

ExtClassLoader 和AppClassLoader都是Launch的内部类,都继承URLClassLoader,而URLClassLoader又继承ClassLoader。

2.4 java加载ClassLoader 的方式

第一种方式是隐式加载方式,加载一个类的时候,如果他的父类没有加载,就会先加载其父类(顺带说一句,自己实现ClassLoader 的时候,也要准守先从父加载器中加载,不然加载到Java.xxx 的类的时候,就会提示报错,因为 java.xxx 的类是不允许从其他地方加载的)

第二种方式是显示加载,也就是我们自己显示使用loadClass方法加载

// TODO

标签: Java
共有 人打赏支持
粉丝 56
博文 39
码字总数 48903
×
lizo
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: