前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java类加载机制详解

Java类加载机制详解

作者头像
张申傲
发布2020-09-03 10:29:04
5750
发布2020-09-03 10:29:04
举报
文章被收录于专栏:漫漫架构路漫漫架构路

1.概述

Java类加载器负责加载所有的类,系统会为所有被载入内存的类生成一个java.lang.Class实例。对于同一个类,一旦被加载如内存中,就不会被再次加载。JVM使用一个类的权限的类名和该类的加载器唯一地标识一个类。因此即使两个类的包名、类名完全相同,但是使用不同的类加载器加载,这两个类也会被认为是不同的。 当程序首次使用某个类时,如果该类还未被加载,则系统会通过以下三个步骤加载该类:

  1. 加载:查找和载入Class字节码文件
  2. 连接:执行校验、准备和解析三个步骤 2.1校验:检查载入的Class文件的正确性,并和其他类协调一致 2.2准备:为类的静态变量分配内存,并设置默认初始值 2.3解析:将类的符号引用转换成直接引用
  3. 初始化:对类的静态变量、静态代码块执行初始化工作

有时,也将上述三个步骤统称为类的加载。

2.类加载器的层次结构

当JVM启动时,会形成由三个类加载器组成的初始化类加载器层次结构:

类加载器的层次结构
类加载器的层次结构
  1. Bootstrap CLassLoader:根类加载器,也称为引导类加载器,负责加载Java的核心类,如JRE目标下的tr.jar、charsets.jar等。根类加载器并不是ClassLoader的子类,它采用C++编写,在Java程序中无法获得。
  2. Extension ClassLoader:扩展类加载器,它负责加载JRE的扩展目录(%JAVA_HOME%/jre/lib/ext)下的jar包。
  3. Application ClassLoader:应用类加载器,也称为System ClassLoader(系统类加载器),主要负责加载classpath路径下的jar包。

三个类加载器之间存在父子层级关系,即Bootstrap ClassLoader是Extension ClassLoader的父类加载器,Extension ClassLoader是Application ClassLoader的父类加载器。这里类加载器的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码。 默认情况下,Java程序使用Application ClassLoader加载一个类。示例程序如下:

代码语言:javascript
复制
public class CLassLoaderTest {

    public static void main(String[] args) {
        //获取当前线程下的ClassLoader
        ClassLoader current = Thread.currentThread().getContextClassLoader();
        System.out.println("current:" + current);

        //获取父类加载器
        System.out.println("parent:" + current.getParent());
        System.out.println("grandparent:" + current.getParent().getParent());

    }

}

输出结果:

代码语言:javascript
复制
current:sun.misc.Launcher$AppClassLoader@56e88e24
parent:sun.misc.Launcher$ExtClassLoader@3dcc0a0f
grandparent:null

由此可见,Java程序默认采用Application ClassLoader,Extension ClassLoader为Application ClassLoader的父类加载器。由于Bootstrap CLassLoader由C++编写,在程序中无法获取,所以返回null。

3.类加载机制

JVM采用如下三种类加载机制:

  1. 全盘委托:当一个类加载器负责加载某个类时,该类所依赖和引用的其他类也将由该类加载器负责加载,除非显式指定另一个类加载器。
  2. 父类委托:加载一个类时,首先会让其父类加载器进行加载,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载。这一机制可以保证类加载的安全性。
  3. 缓存机制:JVM会缓存所有已经加载过的类,当程序使用某个类时,会首先在缓存中搜寻该类,只有缓存中不存在时才会加载。这也是为什么修改了一个类后,只有重启JVM才会生效。

为了更好地说明JVM的类加载机制,对ClassLoader的loadClass()方法的源码分析如下:

代码语言:javascript
复制
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 {
                            //如果该类未被加载,首先尝试获取父加载器,如果父加载器不为null,则使用父加载器进行加载(父类委托机制)
                            if (parent != null) {
                                c = parent.loadClass(name, false);
                            } else {

                                //如果父加载器为空,说明当前加载器为ExtensionClassLoader 或 BootstrapCLassLoader,则使用根类加载器进行加载
                                c = findBootstrapClassOrNull(name);
                            }
                        } catch (ClassNotFoundException e) {
                            //如果使用根类加载器加载失败,则抛出 ClassNotFoundException
                        }

                        if (c == null) {

                            //如果父加载器未能成功加载,则使用当前的类加载器进行加载
                            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;
                }
            }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-10-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.概述
  • 2.类加载器的层次结构
  • 3.类加载机制
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档