一文浅析JVM类加载机制

一、背景

在现在工作中,一次让我熟悉下线上更新版本流程,各种因素原因,公司更新版本流程没有CI/CD,比较原始手工操作,需要自己手动本地打包,备份线上正在运行的jar,上传到对应的位置直接覆盖,然后重启。然而,当我提前做准备备份工作时,我心中就产生疑问:还没到更新时间,此时直接把要更新的jar包覆盖了对现在正在运行的应用有何影响?想起最开始工作微服务没有兴起时,使用SpringMVC,不像springboot内嵌tomcat,一个tomcat只能部署一个应用,都是需要自己部署一个tomcat容器,项目打成war包比较大丢到对应目录下,并且可以同时部署多个应用,当代码改动小的时候,不会全量更新,只需要覆盖对应的class文件就行啦,也不用重启,这又是怎么做到的呢?

二、JVM基础知识体系

image.png

jvm主要模块

一、类加载器ClassLoader

我们自己写的.java文件到最终运行需要经过编译类加载这两个阶段,才能够被加载到JVM里去运行

  • 编译:.java文件编译成.class二进制字节码文件
  • 类加载:.class文件经过类加载器ClassLoader加载到JVM内存中,装载完成以后会得到一个class对象,我们就可以使用new关键字来实列化这个对象

二、内存结构

  1. 类放在方法区
  2. 类创建的实例即对象放在堆中
  3. 堆里面的对象在调用方法时会用到虚拟机栈,程序计数器,本地方法栈

三、执行引擎

方法执行时每行代码是由执行引擎中的解释器逐行进行执行 方法里的热点代码(被频繁调用的代码)会被即使编译器进行优化后的执行 GC对堆中一些不再被引用的对象进行垃圾回收

四、本地方法接口

java不方便实现的功能会调用底层操作系统的功能,通过本地方法接口(常见Object类带有native修饰的方法,没有方法体)调用操作系统提供的功能方法

三、类加载过程

类加载过程有三个阶段:加载链接初始化;其中链接阶段有可以细分为:验证、准备和解析

image.png

1 加载

加载过程会执行三个操作:

  1. 通过一个类的全限定名来获取定义此类的字节码(二进制字节流)
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中创建类的Class对象,作为方法区这个类的各种数据的访问入口

说明:方法区的字节码(C++的数据结构,instanceKlass描述Java类),我们java代码不能直接访问,java通过类对象相应的方法(反射)获取相应的成员属性和方法

类的父类没有加载,先加载父类(接口同理,加载实现类时如果父接口没有加载,优先加载接口,在加载实现类),加载和连接两个阶段可能是交替运行的

  • 类的加载是懒惰的,首次用到才加载,并且类的加载只会执行一次

触发类加载条件: 1:使用类.class 2: 用类加载器的loadClass方法加载类

demo验证

java复制代码package com.mall.portal.study;

import java.util.Scanner;

public class LazyTest {
    public static void main(String[] args) {
        System.out.println("未加载Student类");
        System.out.println("第一次接收到控制台输入" + new Scanner(System.in).next());
        //使用类对象,触发类的加载,这里前后观察内存中shi
        System.out.println(Student.class);
        System.out.println("已加载Student类");
        System.out.println("第二次接收控制台输入" + new Scanner(System.in).next());
        //创建对象,会触发类的初始化,也会触发类加载,但是类加载只会执行一次,前面已加载过不会在重复加载
        Student student = new Student();
    }
}

class Student {
    static {
        System.out.println("已初始化Student类");
    }
}


在等待第一次接收到控制台输入的时候通过arthas去查看加载的类信息如下:可并没有加载Student类

image.png

键盘输入后的类加载信息如下:发现已经加载 Student类

image.png

顺便提前说明静态代码块的执行在初始化阶段,下面讲解

image.png

2 链接(验证-->准备-->解析)

验证(Verify) 验证类是否符合class规范,合法性,安全性检查

准备(Prepare) 为static修饰的类变量分配内存并设置初始值,这里初始值指数据类型的初始值(比如int类型初始值为0,Integer 类型初始值为null),不会执行赋值语句,对于数据的赋值会在初始化阶段进行;但对于final修饰的常量会在准备阶段就完成赋值

java复制代码st
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值