专栏首页慕容千语的架构笔记Java架构师必备技能之类加载机制

Java架构师必备技能之类加载机制

对于架构师很多做技术的人都十分向往,也默默超这个方向去努力,在技术这条线架构师已经是处在顶尖一群人。

我们该如何成为架构师呢?除了机缘,技术基本功是必须够硬的。

架构师一定要在一个语言体系中成长起来,特别是前期阶段要专注一个语言体系深入细节,打磨基本功。对于Java架构师是一定要具备构建工具的能力,在这之上就是构建框架能力,这些能力的基础就是 jvm的类加载机制 。

在jdk1.8基础上来聊“虚拟机类加载机制”。

一般我们在idea中编写.java文件,以project方式大家这些java文件组织关系,在用maven这样工具build成class文件,大多情况下这些.class文件封装在jar包里面,最终有jvm来加载这些jar也就是class文件。类加载就是jvm解析class这些字节码文件的过程,这是核心,包括在java文件中的逻辑关系、对象、还有内存。

类加载

一个类在jvm中分为7个阶段,分别是“加载、验证、准备、解析、初始化、使用、卸载”,其中“验证、准备、解析”又称为连接,7个阶段的顺序是固定的,必须按部就班进行,这就是规范。

加载

这个阶段jvm主要完成三件事:

  • 通过一个类的全路径名获取此类的二进制字节流。就是按位置读取class文件。
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口。

验证

确保class文件的字节流中包含的信息符合《java虚拟机规范》的全部约束,保证代码运行后不会危害虚拟机的安全。先验证class文件的格式规范,再对字节码描述信息进行语义分析,之后进一步进行数据流分析和控制流分析,最后是符合引用转化直接引用(该类是否被禁止访问它依赖的某些外部类等等)。

准备

正式为类中的静态(static修饰)变量分配内存并设置类变量的初始值,一般都放在虚拟机方法区内。

解析

将常量池内的符号引用替换为直接引用,主要是“类、接口、字段、类方法、接口方法、方法类型、方法句柄、调用电限定符”。

这里说明一下“符号引用”是啥?class在前面几步中不是直接的内存引用,而是一些特征性字符串代替的,如“CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info”等等,解析的过程就是替换指针的过程。这个过程还存在一些检测,比如“java.lang.NoSuchMethodError”就是这里报出的。

初始化

前面阶段都是jvm自己主导,自定义类加载器可以局部参与。到了初始化阶段就是开始执行类中编写的java程序代码,这个时候是应用程序开始主导,这个时候按编码逻辑开始初始化变量和其他资源。

直接些说这个初始化过程就是执行类构造器 <clinit>() 方法的过程,而这个类构造器不是自己编写的类构造器,是由javac编译器自动生成的。

类加载器

类加载器就是“通过一个类的全限定名来获取描述该类的二进制字节流”的代码,这块代码在jdk中。

比较两个类是否“相等”,只有在这两个类由同一个类加载器加载的前提下才有意义,否则它们必定不相等。

三层类加载器

  • Bootstrap Class Loader:启动类加载器,负责加载存放在<java_home>\lib目录,或者-Xbootclasspath参数指定路径的jar,并且是虚拟机 可识别 的jar(白名单)。这个启动加载器是顶级加载器,应用不可控,只能通过委托方式给它加载。
  • Extension Class Loader:扩展类加载器,加载<java_home>\lib\ext目录,或者java.ext.dirs参数指定路径的jar。
  • Application Class Loader:应用程序类加载器,加载应用classpath上所有jar,如何没有自定义默认是这个类在加载class文件。

双亲委派模型

双亲委派模型要求除了顶层的启动类加载器外,其余类加载器都应该有自己的父类加载器,它不是通过extends方式控制,而是写在代码中通过判断逻辑实现的。

双亲委派的整个过程:如果一个类加载器收到类加载的请求,它首先不会自己尝试加载这个类,而是把这个请求委派给父类加载器去加载完成,每个层次的加载器都是如此,所以所有加载器的加载请求最终都会传送到最顶层(启动类)加载器中,只有当父类加载器表示无法完成这个请求是(返回null),子加载器才会自己尝试完成加载。

java.lang.ClassLoader的loadClass()方法代码:

protected sychronized Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException{
    Class c = findLoadedClass(name);
    if(c==null){
        try{
            if(parent != null){
                c = parent.loadClass(name,false);
            } else {
                c = findBootstrapClassOrNull(name);
            }
        } catch(ClassNotFoundException e){
            //...
        }
        if(c==null){
            c = findClass(name);
        }
    }
    if(resolve){
        resolveClass(c);
    }
    return c;
}

技术之路永无止尽

本文分享自微信公众号 - 慕容千语(mrqy_1507153110),作者:关注我→

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

原始发表时间:2021-03-13

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java架构之路-(九)JVM类的加载机制

    ***.class文件执行大概就是这样来走的。我们都知道我们的java文件经过编译以后会生成对应的class文件。先经过类装载子系统,然后塞进运行时内存模型的...

    小菜的不能再菜
  • 连 JVM 类加载机制都扯不清楚,还想成为架构师?

    类加载器把class文件中的二进制数据读入到内存中,存放在方法区,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

    本人秃顶程序员
  • 还未成为优秀的安卓工程师,是差在时代还是败在机遇?看了这份进阶指南后,我茅塞顿开

    移动研发火热不停,越来越多人开始学习Android开发。但很多人感觉入门容易成长很难,对未来比较迷茫,不知道自己技能该怎么提升,到达下一阶段需要补充哪些内容。市...

    Android技术干货分享
  • 面试被吊打,是因为你的知识体系零乱!值得收藏的全方面覆盖Android知识结构总结

    2017年初Android市场饱和的传言一度甚嚣尘上。2018年经济寒潮,2020年疫情打压下,众多大厂和曾经风口上的互联网企业也不得不裁员自保,通过小程序、前...

    Android技术干货分享
  • Android完整知识体系路线

    移动研发火热不停,越来越多人开始学习Android 开发。但很多人感觉入门容易成长很难,对未来比较迷茫,不知道自己技能该怎么提升,到达下一阶段需要补充哪些内容。...

    Android技术干货分享
  • Android 架构师研发技术进阶之路:不同阶段需要掌握的那些技术及软技能

    移动研发火热不停,越来越多人开始学习android开发。但很多人感觉入门容易成长很难,对未来比较迷茫,不知道自己技能该怎么提升,到达下一阶段需要补充哪些内容。市...

    Android技术干货分享
  • Java程序员拿阿里、京东、腾讯的offer指南

    我开始投递简历(世界那么大,我想去外面的世界看看)。这次看机会与往常不同,我决定好好准备一番,然后开始投递简历,主要渠道是 “X钩”,辅助渠道是猎头。

    java架构师
  • 转:成为Java高级程序员需要掌握哪些?

    1、Core Java,就是Java基础、JDK的类库,很多童鞋都会说,JDK我懂,但是懂还不足够,知其然还要知其所以然,JDK的源代码写的非常好,要经常查看,...

    技术zhai
  • 一位资深Java架构师的晋级心得

    Java 架构师是什么?是一个既需要掌控整体又需要洞悉局部瓶颈并依据具体的业务场景给出解决方案的团队领导型人物。一个架构师得需要足够的想像力,能把各种目标需求进...

    Debian中国

扫码关注云+社区

领取腾讯云代金券