你能讲清楚Java类的整个生命周期吗?

想了很久,想把JVM这块了结一下,奈何知识实在是太多,随便拿出一个知识点都能写一篇文章了。今天就从Java类的生命周期讲吧,就跟人的一生一样,有太多的曲折和苦难,但是也有很温暖、很甜的时候,这就是人生百态,也是Java类的人生百态。

初次相见,你是否还记得HelloWorld

有多少人,还记得第一次写Java代码时候的情景?我想99%的人都是从HelloWorld开始Java这一段精彩的人生的。来,我们在看看那熟悉的Hello World吧!

public class MainTest {
    
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}

一别多年,你又回来看HelloWorld

从上一次写Hello World以后,你是不是很多年都没有写过Hello World呢?在与它分别的这些日日夜夜里面,你是不是已经开始使用Spring全家桶了?你是不是已经开始使用ORM框架了?你是不是已经开始使用NoSql数据库了?你是不是已经开始Redis了?你又是不是开始使用RPC了呢?
当你用过了越来越多的框架,你发现你也只是个使用级别的程序员,是不是内心很崩溃呢?
当你静下心来,回想当初步入这个行业的时候,回想起你写下第一行代码的时候,你是不是又想起了Hello World?你真的认识它吗?

重拾,再看HelloWorld

依稀记得,这几行简单的不能再简单的代码,可是,你了解它的生命周期吗?你知道它从静态编译到加载,再到连接,在到初始化,在到使用,在到卸载的这一生都要经历什么吗?
从.java文件,静态编译以后变成了.class文件,你知道class文件里面长什么样子吗?我们来一起看看吧!
在这里插入图片描述

用编辑器,打开class文件,你会看到这些16进制的字符,你是否认识它们啊?
这长图确实有难度,我们再换一张图,来看看。

类结构图

你是否看到了熟悉的身影:CA FE BA BE,这是不是你常常念叨的咖啡贝贝啊?这就是class文件的结构了。想想,你都会和这里面的哪些伙伴接触过呢?

  • 【魔术】magic,这东西,平时真没交集,只有在类生命周期的验证阶段才会用到它,只有.java文件编译后的.class才有这玩意,这算是一个唯一标识符了。记住了,下次,看见它,就要知道,这个咖啡贝贝是你用Java写得了。
  • 【副版本号】minor_version,说实在的,这玩意好像真没啥用,咱也不敢问当初开发的大牛,为什么要这玩意儿啊!哪位大牛知道,希望给普及一下知识盲区。
  • 【主版本号】,这玩意儿你要知道,怎么看呢?再给一幅图看看吧!
    在这里插入图片描述
    你找到最上面的那张图,看看是用什么版本写的,你是不是已经看到了【00 00 00 34】,这是16进制的,对应的十进制是52,对应jdk1.8.剩下的,就不一个一个说了。再来一张图片吧!
    在这里插入图片描述
    这里面有很多都是经常你经常使用的,比如:接口,字段,方法,属性等等。

这上面的太抽象了,在使用Java的过程中,怎么才能查看呢?

利器,javap命令

在这里插入图片描述

以后,有时间多用javap命令来看看你写的代码,有助于深入理解Java。
说了这么久,都没有提及Java类的生命周期,是不是觉得我在忽悠人啊?下面,就一起来看看吧!

Java类的生命周期

在这里插入图片描述
这应该是你熟悉的Java类的生命周期吧,我们上面聊的只是从.java文件编译为.class文件中涉及一点知识点而已。

Java类的生命周期,从大的范围可以划分为加载-连接-初始化-使用-卸载.从小的范围可以分为加载-验证-准备-解析-初始化-使用-卸载。

你有想过,类在生命时候初始化吗?类在哪里使用了?类在什么时候卸载?

Java类加载子系统,类加载器

你是否清楚,Java类是怎么加载?我们通过一张图,来看看

在这里插入图片描述

  • BootStrap ClassLoader[启动类加载器],这个加载器是由C++写的,它加载JAVA_HOME\lib目录下的jar包。注意,它不是ClassLoader的子类。
  • Extension ClassLoader[扩展类加载器],它加载JAVA_HOME\lib\ext目录下的jar包。
  • Application ClassLoader[应用类加载器],加载用户路径(classpath)目录下的jar包。
  • 自定义加载器,加载用户自定义目录下的jar包。
    从上面这张图,你应该知道类在加载的时候,有这么多关卡,箭头都是向上的,为什么呢?
    【双亲委派】,【自底向上检查类是否已经记载】,【自顶向下尝试加载类】,这就是双亲委派。你知道为什么叫【双亲委派】吗? 可能,就是应用类加载器上面有一个爹和一个爷爷吧。所以,才叫做【双亲委派】吧!
  • 【验证】,保证二进制字节流中的信息符合虚拟机规范,并没有安全问题。
  • 【准备】,仅仅为类变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值即零值。
  • 【解析】,解析是虚拟机将常量池的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法四类符号引用进行,分别对应于常量池中的
    CONSTANT_Class_info、CONSTANT_Fieldref_info 、CONSTANT_Methodref_info 、CONSTANT_InterfaceMethodref_info`四种常量类型。
  • 【初始化】,初始化是类加载过程的最后一步,到了此阶段,才真正开始执行类中定义的Java程序代码(初始化成为代 码设定的默认值)。其实初始化过程就是调用类初始化方法的过程,完成对static修饰的类变量的手动赋值还有主动调用静 态代码块。

当你步入社会【JVM运行时区域】,可就要靠自己了

jvm运行时区域,从大范围,可以分为两种区域,一种是线程共享区域,另外一种,就是线程独享区域了
线程共享区域,在不同的JDK版本中,大体相同,但是也有不同。有些区域,危险无比,有些区域也无比安全。随着JVM的启用生,随着JVM的死而销毁。
线程独享区域,随着线程的创建而生,随着线程的死亡而死亡。思想之下,这就是皇帝和爱妃啊,皇帝驾崩,爱妃陪葬啊!

  • 线程共享区域,在JDK1.6中包含堆和方法区(永久代的实现),在JDK1.7中也包含堆和方法区(永久代),在JDK1.8+以后只包含堆了。备注:【在JDK1.6中方法区中包含运行时常量池,在JDK1.7的时候运行时常量池挪到堆中了,在JDK1.8的时候真正实现了去除永久代。有人会说JDK1.8中有元空间,但是,元空间用的是对外内存,已经不再Java堆中了】

  • 【朝生夕死】年轻代,分为eden和两个交换区,在平时运行时工作的是eden和其中一块交换区。

  • 【长命百岁】老年代,老东西都是关系复杂的,有各种社会人脉和资源的,能活的很久。

  • 【与天同寿】永久代,JVM生它就生,JVM死它才死。【也有个例,会被带走】
    能活多久,全靠自己本事和那么一点点运气了。

总结:岁月静好,愿你一世安康快乐

不管你,是不是写代码的,还是高级写代码的,都要快乐!
写代码的时候,心情是美好的。改BUG的时候,是糟糕的。跟产品聊天的时候,是想拿刀的。
岁月静好,你要静下心来,聆听和感受这氛围,愿你一世安康快乐!

  • 42
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值