java 类加载过程

本文转载自 面试官:请你谈谈Java的类加载过程
一个Java文件从编码完成到最终执行,一般包括两个过程

  • 编译
  • 运行

编译:把我们写好的java文件,通过javac命令编译成字节码,也就是我们常说的.class文件
运行:则把编译生成.class文件交由Java虚拟机(JVM)执行。
而我们所说的类加载过程就是指JVM把.class文件中类信息加载到内存中,并进行解析生成对应的class对象的过程。
举个通俗的例子来说,JVM在执行某段代码时,遇到了class A,然后此时内存中并没有class A 的相关信息,于是JVM就会到相应的class文件中去寻找class A的类信息,并加载到内存中,这就是我们所说的类加载过程。
由此可见,JVM不是一开始就把所有的类加载到内存中,而是只有第一次遇到某个需要运行的类才会加载。

类加载

  • 加载
  • 连接
  • 初始化
    而连接又可以细分为三个小部分
  • 验证
  • 准备
  • 解析

加载

简单来说,加载指的是把class字节码文件从各个来源通过类加载器装载入内存中。
这里有两个重点:

  • 字节码来源。一般的加载来源包括从本地路径下编译生成的.class文件,从jar包中.class文件,从远程网络,以及动态代理实时编译
  • 类加载器。一般包括启动类加载器,扩展类加载器,应用类加载器,以及用户的自定义类加载器。

注:为什么会自定义类加载器?

  • 一方面是由于Java代码很容易被反编译,如果需要对自己的代码加密的话,可以对编译后的代码进行加密,然后再通过实现自己的自定义加载器进行解密,最后再加载。
  • 另一方面也有可能可能从非标准的来源加载代码,比如从网络来源,那就需要自己实现一个类加载器,从指定源进行加载。

验证

主要是为了保证加载进来的字节流符合虚拟机规范,不会造成安全错误。
包括对于文件格式的验证,比如常量中是否有不被支持的常量,文件中是否有不规范的或者附加的其他信息?
对于元数据的验证,比如该类是否继承了被final修饰的类?类中的字段,方法是否与父类冲突?是否出现了不合理的重载?
对于字节码的验证,保证程序语义的合理性,比如要保证类型转换的合理性。
对于符号引用的验证,比如校验符号引用中通过全限定名是否能够找到对应的类,校验符号引用中的访问性(private,public等)是否被当前类访问。

准备

主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。
特别需要注意,初值,不是代码中具体些的初始化的值,而是java虚拟机根据不同变量类型的默认初始值
比如8种引用类型,默认为0;引用类型的初值为null;常量的初值为代码中设置的值。

解析

将常量池内的符号引用替换为直接引用的过程。
两个重点:

  • 符号引用 即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个类的相关信息
  • 直接引用 可以理解为一个内存地址,或者一个偏移量。比如类方法,类变量的直接引用是指向方法区的指针,而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量。
    举个例子:现在调用方法hello(),这个方法的地址是1234567,那么hello就是符号引用,1234567就是直接引用。
    在解析阶段,虚拟机会把所有的类名,方法名,字段名这么符号引用替换为具体的内存地址或偏移量,也就是直接引用。

初始化

这个阶段主要是对类变量的初始化,是执行类构造器的过程。
换句话说,只对static修饰的变量或语句进行初始化。
如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。

总结

类加载过程只是一个类声明周期的一部分,在其前,有编译的过程,只有对源代码编译之后,才能获得能够被虚拟机加载的字节码文件;在其后还有具体的类使用过程,当使用完成之后,还会在方法区垃圾回收的过程中进行卸载。

类加载器

类加载器是用来加载Java类到java虚拟机中,一般来说,java虚拟机使用java类的方式如下:java源程序(.java文件)在经历java编译器之后就转为java字节代码(.class文件)。类加载器负责读取java字节码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个java类,通过此实例的newInstance()方法就可以创建该类的一个对象。

类加载器应用在很多方面,比如类层次划分,OSGI,热部署,代码加密等领域。
基本上所有的类加载器都是Java.lang.classLoader类的一个实例。

java.lang.ClassLoader类

java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节码,然后从这些字节码中定义出一个java类,即java.lang.class类的一个实例。除此之外,ClassLoader还负责加载Java应用所需的资源,如图像文件和配置文件等。

类与类加载器

类加载器虽然只用于实现类的加载动作,但它在java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一起确立其在java虚拟机中的唯一性。

类加载的种类

  • 启动类加载器: 负责加载JRE的核心类库,如jre目标下的rt.jar,charsets.jar等
  • 扩展类加载器:负责加载JRE扩展目录ext中的jar类包
  • 系统类加载器:负责加载classpath路径下的类包
  • 用户自定义加载器:负责加载用户自定义路径下的类包

双亲委派模型

如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈给自己无法完成这个加载请求时(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 类从 被加载到虚拟机内存中 开始,到 卸载出内存 为止,它的生命周期包括:加载(Loading)、验证(Verif...
    未名爪哇阅读 363评论 0 0
  • 干Android开发两年了,竟然不清楚Java类加载过程,都有点不好意思说自己会Java,这不赶快来恶补一下这方面...
    尼古拉斯_特仑苏阅读 1,119评论 0 7
  • 类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。 其中...
    码出高效阅读 208评论 0 0
  • 概述 Java类加载过程包括以下五个阶段: 加载 验证 准备 解析 初始化验证、准备和解析三个阶段统称连接阶段。加...
    0x70e8阅读 1,293评论 1 3
  • 1.java类加载过程 重新回顾了java的类的生命周期,主要有:加载、链接、初始化、使用、卸载。上述过程包括了一...
    冬天里的懒喵阅读 3,052评论 1 13