资讯专栏INFORMATION COLUMN

【Java】类的生命周期简述

qpwoeiru96 / 401人阅读

摘要:一多个类的初始化在进入正文前首先根据上面的例子试图猜测为了类中的函数能够运行需要做哪些前置工作呢这些工作是以什么顺序展开的呢为了更好的描述多个类的情形可以先试图描述一个更简单的例子把行和行和行注释掉二类从到一句话把类从介质中复制到方法区通过

一)Example: 多个类的初始化
package me;
class A {
    static int a = 1;
    static {
        a = 2;
        System.out.print("A init");
    }
    static int getA(){
        return a;
    }
}
class B extends A{
    static int b = 1;
    static {
        b = 2;
        System.out.print("B init");
    }
}
class Main {
    static public void main(String... args){
        System.out.print(A.a);//0
        System.out.print(B.a);//1
        System.out.print(B.getA());//2
        System.out.print(B.b);//3
    }
}

在进入正文前,首先根据上面的例子试图猜测:为了Main类中的main()函数能够运行,JVM需要做哪些前置工作呢?这些工作是以什么顺序展开的呢?
为了更好的描述多个类的情形,可以先试图描述一个更简单的例子:把行1和行2和行3注释掉.

二)类:从0到1

一句话: 把类从介质中复制到JVM方法区,通过各种规则验证和符号解析,最后根据程序员的逻辑赋值或其他语句完成初始化

Step1.类的加载(Loading)

加载是把存储类的实体从各类介质(文件/网络/数据库/内存中实时生成等)加载到JVM的方法区中的过程,主要包含2步:

根据类的全限定名"me.B"通过 _ApplicationClassLoader_(或者是自己定义的ClassLoader)获得B类的二进制流

把流读入内存中,并转化为JVM规定的方法区结构,生成对应的java.lang.Class对象

现在,你可以在程序中访问到这个类~(≧▽≦)/~啦

Step2.类的连接(Linking)

JVM中的连接细分为独立的3步:验证/准备/解析
验证和准备的开始是有严格的顺序的,但是JVM可以自由选择解析发生的时机,甚至放到初始化之后

连接可以理解为把源代码转化为可执行程序的过程,当然不同于C/C++连接生成的.exe程序,JVM中的可执行程序一般是字节码(bytecode)程序

Step3.验证(Validation)

验证过程较为复杂,JVM主要验证了class文件格式/java语义限制/java程序逻辑正确性和安全性,其主要技术为静态的字节码分析,所以不能保证100%的可靠

Step4.准备(Preparation)

me.B类中的静态变量int b在堆中分配内存,并设置其初始值0

Step5.解析(Resolution)

简单地说,是将符号引用转化为直接引用的过程,所有符号引用都必须转化为直接引用

符号引用: 如方法名/变量名/类等等的符号
直接引用: 直接指向一块内存区域

Step6.类的初始化(Initialization)

在初始化之前,程序已经可以在内存中访问到me.B类和其类变量了

初始化所做的事情也很简单:JVM从上到下收集类变量赋值语句和类静态初始化块中的语句,把它放到JVM生成的()方法中,再执行之

对于初始化的时机,JVM有严格的规范:只有在主动引用时才会触发类的初始化

主动引用有5种情况:大致可以理解为以下几种

以各种方式读静态变量/写静态变量/触发静态方法时(包括出现相应的字节码指令/反射/invokedynamic)类却没有初始化

包含入口方法main()的类

初始化子类时父类还没初始化
其他情况都是被动引用

可以看到,me.B()方法中执行了下列代码:

b = 1;
b = 2;
System.out.print("B init");
三)类:从1到n再到0 类的使用(Using)

类的实例化过程,包括new/反射等方法

类的卸载(Unloading)

当程序中无论什么方法都无法引用该类时,类从方法区被回收,大致可以理解为

类的所有实例被回收

类的ClassLoader被回收

没有地方引用Class对象,也无法通过反射访问

四)Example:执行过程简述

回到最初的例子,可以列出预计的执行顺序为:

初始化me.Main

加载me.B

初始化me.A: 输出"A init"

System.out.print(A.a);:输出2

System.out.print(B.a);:输出2

System.out.print(B.getA());:输出2

初始化me.B:输出"B init"

System.out.print(B.b);:输出2

实际执行结果验证:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67281.html

相关文章

  • 金三银四,2019大厂Android高级工程师面试题整理

    摘要:原文地址游客前言金三银四,很多同学心里大概都准备着年后找工作或者跳槽。最近有很多同学都在交流群里求大厂面试题。 最近整理了一波面试题,包括安卓JAVA方面的,目前大厂还是以安卓源码,算法,以及数据结构为主,有一些中小型公司也会问到混合开发的知识,至于我为什么倾向于混合开发,我的一句话就是走上编程之路,将来你要学不仅仅是这些,丰富自己方能与世接轨,做好全栈的装备。 原文地址:游客kutd...

    tracymac7 评论0 收藏0
  • Activity 使用详解

    摘要:极力推荐文章欢迎收藏干货分享阅读五分钟,每日十点,和您一起终身学习,这里是程序员本篇文章主要介绍开发中的部分知识点,通过阅读本篇文章,您将收获以下内容生命周期简介必须在中注册启动的方法启动带返回值的结束方法状态保存,恢复的方法面 showImg(https://upload-images.jianshu.io/upload_images/5851256-0b56fc8e812963d7...

    Caicloud 评论0 收藏0
  • 前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    pumpkin9 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<