Java之ClassLoader

.class文件需要被ClassLoader加载到JVM内存中的Method Area形成一个Class实例。

public final class Class<T> {
    //不含PacakageName
    public String getSimpleName();
    //完整类名,包含PackageName
    public String getName();
    public Field[] getFields() throws SecurityException;
    public Method[] getMethods() throws SecurityException;
    .......
    //获取ClassLoader
    public ClassLoader getClassLoader();
}

public abstract class ClassLoader {

    public Class<?> loadClass(String name) throws ClassNotFoundException;

    public final ClassLoader getParent();

    public URL getResource(String name);

    public InputStream getResourceAsStream(String name);

    ....
}

JVM中默认有三个ClassLoader

  • Bootstrap ClassLoader

    C语言编写,加载sun.boot.class.path下的类,包括resource.jar、rt.jar、charsets.jar等核心jar,可通过-Xbootclasspath指定其值, jinfo pid | grep boot可查看sun.boot.class.path值

  • Extension ClassLoader

    sun.misc.Launcher.ExtClassLoader, rt.jar中定义,继承自java.lang.ClassLoader,加载java.ext.dirs目录下的jar,一般为$JAVA_HOME/jre/lib/ext/

  • App ClassLoader

    sun.misc.Launcher.AppClassLoader, rt.jar中定义,继承自java.lang.ClassLoader,加载java.class.path目录下的jar, 也就是启动JVM时通过-classpath指定的jar,我们自定义的类基本都是通过AppClassLoader加载。

这些ClassLoader之间具有父子关系,AppClassLoader父亲是ExtClassLoader, ExtClassLoader父亲是Bootstrap ClassLoader,自定义ClassLoader父亲是AppClassLoader,可通过ClassLoader.getParent()获取父ClassLoader.

class加载过程

一个class只有在被使用时才会加载进内存,JVM先自底向上搜寻ClassLoader,看是否有ClassLoader已加载此类,如果没有加载,则采用双亲委派模式进行加载,即自底向上委托加载,只有其父ClassLoader无法加载时,子ClassLoader才会加载,因此首先会递归到顶部Bootstrap ClassLoader,然后再回溯至第一个可成功加载的ClassLoader,如果无ClassLoader成功加载则抛出ClassNotFoundException。

双亲委派模式可避免重复加载,当父ClassLoader加载了该类的时候,子ClassLoader不必再加载一次。此外这种委托模式更安全,双亲委派可避免那我们使用自定义的String来动态替代java核心api中定义的类型,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一个自定义String。

class的ClassLoader可通过Class.getClassLoader()获取,在JVM启动参数中添加 -verbose:class 可查看类从那个jar包加载的。

ClassLoader加载.class时需经过以下步骤:

1、找到 .class 文件并把这个文件包含的字节码加载到内存中

2、分三步,字节码验证,以确保格式正确、行为正确;class类中定义的字段、方法和实现接口所必须的数据结构及相应的内存分配;最后的符号表的链接,装入类所引用的其他所有类

3、类中静态属性和初始化赋值,以及静态块的执行等

Custom ClassLoader

有时我们需要的类并不在classpath下,比如在网路上或者说有版本冲突时在自定义路径上,此时可自定义ClassLoader,指定class的路径,从对应路径上读取.class文件转换成byte[]进行加载。

自定义ClassLoader分两步:

1、继承java.lang.ClassLoader

2、重写父类的findClass方法

Ref

http://www.importnew.com/15362.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值