qfile.remove 删除已经被加载的文件_jvm篇-初识类加载器

89c0efcb0610442a972ff575307f21af.png

类加载器是做什么的,类需要加载到虚拟机中,类加载器负责将Java类加载到内存中,并生成Class类的实例对象。

一、简单使用类加载器

首先让我们一起通过一个例子来简单的使用类加载器加载class文件,并获取class对象

首先创建一个对象类

public class DemoItem {
    public void demo()
    {
        System.out.println("demo!!");
    }
}

将编译生成的class复制到E:/cltmp/路径下,并删除DemoItem这个类,防止会被默认加载,然后创建类加载器,并获取class文件加载类。

URL url = new URL("file:/E:/cltmp/");
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
Class cl = classLoader.loadClass("DemoItem");
System.out.println(cl.equals(cl));

二、类加载器常用函数解析

现在已经使用类加载器获取到了DemoItem的class对象了。让我们一起看下类加载器中一个核心的函数loadClass(String name),这个函数负责获取全名为name的类,返回对象为Class实例,代码如下

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        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) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

loadClass中首先调用findLoadedClass查询类是否被当前类加载器加载,如果没有找到,则去父级类加载器,即扩展类加载器中parent.loadClass(name, false)查询是否已经加载,如果还是没有就到BootstrapClassLoader中查询是否加载,如果还是找不到,则类还没有加载,调用findClass()函数,查找加载路径下的class文件,如果还是找不到在findClass()函数中抛出ClassNotFoundException异常。

findClass这个函数负责将制定加载路径的class文件加载进虚拟机中,URLClassLoader中findClass函数代码如下

protected Class<?> findClass(final String name) throws ClassNotFoundException
{
    final Class<?> result;
    try {
        result = AccessController.doPrivileged(
            new PrivilegedExceptionAction<Class<?>>() {
                public Class<?> run() throws ClassNotFoundException {
                    String path = name.replace('.', '/').concat(".class");
                    Resource res = ucp.getResource(path, false);
                    if (res != null) {
                        try {
                            return defineClass(name, res);
                        } catch (IOException e) {
                            throw new ClassNotFoundException(name, e);
                        }
                    } else {
                        return null;
                    }
                }
            }, acc);
    } catch (java.security.PrivilegedActionException pae) {
        throw (ClassNotFoundException) pae.getException();
    }
    if (result == null) {
        throw new ClassNotFoundException(name);
    }
    return result;
}

已经基本搞清楚类加载器怎么工作的了,下一篇我们一起研究下类加载器的分类和加载器的双亲委派模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值