专栏首页Coding DiaryJava类加载机制

Java类加载机制

Java的程序要运行需要将编译好的class文件加载到JVM运行时数据区。

在了解类的加载机制之前,我们需要了解一下类的生命周期。Java类从被加载到JVM内存开始,到卸载出内存为止,它的整个生命周期包括了:加载(Loading),验证(Verification),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)七个阶段。

类加载器

Java类的加载需要用到类加载器。类加载器负责装入类,搜索网络,jar,zip,文件夹,二进制数据,内存等指定位置的资源。一个Java程序运行,至少有3个不同的类加载器实例,负责加载不同的类。这三个类加载器分别为,启动类加载器(Bootstrap ClassLoader),扩展类加载器(Extension ClassLoader),应用程序类加载器(Application ClassLoader)。

通过JDK提供的API:java.lang.Class.getClassLoader() 可以进行类加载器的查看,该API会返回装载类的类加载器,如果这个类是由Bootstrap ClassLoader加载的,那个这个方法会返回null。

代码示例:

public class ClassLoaderView {
  public static void main(String[] args) throws Exception {
    // 加载核心类库的 BootStrap ClassLoader
    System.out.println(
        "核心类库加载器:"
            + ClassLoaderView.class
                .getClassLoader()
                .loadClass("java.lang.String")
                .getClassLoader());
    // 加载拓展库的 Extension ClassLoader
    System.out.println(
        "拓展类库加载器:"
            + ClassLoaderView.class
                .getClassLoader()
                .loadClass("com.sun.nio.zipfs.ZipCoder")
                .getClassLoader());
    // 加载应用程序的 Application ClassLoader
    System.out.println("应用程序库加载器:" + ClassLoaderView.class.getClassLoader());
  }
}
//运行结果:
核心类库加载器:null
拓展类库加载器:sun.misc.Launcher$ExtClassLoader@7f31245a
应用程序库加载器:sun.misc.Launcher$AppClassLoader@18b4aac2

JVM如何知道我们的类在何方

class信息可以存在不同的地方,那么JVM是如何知道我们的类存在什么地方的哪?通过查看sun.misc.Launcher.AppClassLoader的源码我们可以看到,它会读取java.class.path这个配置来获取那些地址加载类资源。参考以下代码示例,利用jsp和jcmd两个命令可以进行验证。

代码示例:

public class HelloWord {
  public static void main(String[] args) throws IOException {
    System.out.println("Hello Word");
    System.in.read();
  }
}

jsp命令可以查看本机Java进程,jcmd命令可以查看运行时配置:jcmd 进程号 VM.system_properties

双亲委派模型

Java中的类并不会重复加载,同一类加载器,同一类名,代表的是同一个类。而避免类重复加载的主要原因在于JVM在加载类时默认采用的是双亲委派模型。所谓的双亲委派模型,就是某个特定的类加载器在接到类的加载请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,就成功返回;只有父加载器无法完成此加载任务时,才自己去加载。由下到上逐级委托,由上到下逐级查找,双亲委派模型保证了Java核心库的类型安全

类的卸载

JVM中的类不可能一直存在,在满足一定条件的情况下类会被卸载掉。在满足该Class的所有实例都已被垃圾回收,同时加载该类的ClassLoader实例也已经被垃圾回收,那么这个类会被JVM卸载掉。在JVM启动中增加-verbose:class参数,可以输出类加载和卸载的日志信息。

本文分享自微信公众号 - Coding Diary(gh_7e1f05090980),作者:Joey

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java中实现线程的方式

    Java中实现多线程的方式的方式中最核心的就是 run()方法,不管何种方式其最终都是通过run()来运行。

    CodingDiray
  • 线程的通信和封闭

    要想实现线程之间的协同, 如: 线程先后执行顺序, 获取某个线程的执行结果等, 涉及线程之间的相互通信, 分为下面四类

    CodingDiray
  • Java内存模型以及线程安全的可见性问题

    首先Java内存模型(JMM)和JVM运行时数据区并不是一个东西,许多介绍Java内存模型的文章描述的堆,方法区,Java虚拟机栈,本地方法栈,程序计数器这东西...

    CodingDiray
  • 【随笔】JVM核心:JVM运行和类加载

    本篇博客将写一点关于JVM的东西,涉及JVM运行时数据区、类加载的过程、类加载器、ClassLoader、双亲委派机制、自定义类加载器等,这些都是博主自己的一点...

    用户2890438
  • 类加载常见错误总结,写得非常好!

    作者:fredalxin 地址:https://fredal.xin/classloader-error

    肉眼品世界
  • jvm的类加载器(classloader)及类的加载过程

    类加载简单的说就是JVM通过类加载器ClassLoader,把.class文件中的信息,拼装成Class对象放入内存中。

    逍遥壮士
  • JVM --- 结构体系介绍

    JVM是运行在操作系统之上的虚拟机,跟硬件没有直接交互。这也就体现了它跨平台的优越性。只要你这个操作系统能运行JVM,那么就可以运行java程序。

    贪挽懒月
  • Java面试-类加载

    任何程序都需要加载到内存才能与CPU进行交流.字节码.class文件统一需要加载到内存中,才能实例化类,而ClassLoader正是关键,它的使命就是提前加载....

    颍川
  • 深入理解Java类加载机制-类加载器

    加载作为类加载的第一个阶段,是开放的,它允许Java程序员通过自定义的类加载器去加载特定的类。

    shysh95
  • 今天我们来聊聊JVM类加载机制

    说到jvm 那么不得不提类的加载过程.我们先来了解下类是如何被一步一步加载到jvm的

    Java宝典

扫码关注云+社区

领取腾讯云代金券