JVM部分--类加载运行全过程

JVM知识梳理

一、类加载运行全过程

当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。通过下例程序讲解

package com.tuling.jvm;

public class Math {
    public static final int initData = 666;
    public static User user = new User();

    public int compute() { //一个方法对应一块栈帧内存区域
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        math.compute();
    }
}

通过Java命令执行程序的流程大致如下:在这里插入图片描述

其中通过LoadClass加载类时的类加载过程有如下几步:在这里插入图片描述

加载>>验证>>准备>>解析>>初始化>>使用>>卸载

  • 加载:在磁盘中查找并且通过IO读入字节码文件,使用到类时才会加载,比如调用这个类的main
    方法,通过new这个对象,在加载阶段会在内存中生成一个代表整个类的java.lang.Class对象,作
    为方法区整个类的各种数据的入口。

  • 验证:验证字节码文件的格式是否正确,也就是字节码文件的正确性,如是否cafe babe开头等等

  • 准备:给类的静态变量分配内存,并且赋予默认值,整个默认值并不是在类中定义的指定值,而是
    说基础数据结构的默认值,比如int默认时0这样的。

    • final修饰的变量和static修饰变量在类加载中的赋值情况?
      • final修饰的实例属性,在实例创建的时候才会赋值。
      • static修饰的类属性,在类加载的准备阶段赋数据结构的默认初值,初始化阶段最终赋
        值。
      • static+final修饰的String类型或者基本类型常量,JVM规范是在初始化阶段直接赋值,
        但是HotSpot VM直接在准备阶段就赋值了。
      • static+final修饰的其他引用类型常量,赋值步骤和第二点的流程是一样的
  • 解析:将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main方法)替换
    为指向数据所存内存的指针或者句柄(这个就是直接引用),这就是所谓的静态链接过程(在类加
    载期间完成)。而动态链接是指在程序运行期间完成的符号引用(或者说是指向运行时常量池的方
    法引用,比如一个方法调用另一个方法,这种可能一个接口存在多个实现,这个只能在运行时才能
    知道,所以只能动态链接)替换为直接引用。可以通过javap -v Math.class查看

  • 初始化:对类的静态变量进行赋指定值,并且执行静态代码块

类加载到方法区之后主要包含运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应
class实例的引用等信息。

  • 类加载器的引用:这个类到类加载器实例的引用
  • 对应class实例的引用:类加载器在加载类信息到方法区后,会创建一个对应的class类型的对象实
    例放到堆(heap)中,作为开发人员访问方法区中类定义的入口和切入点。

注意:主类在运行过程中如果使用到其他类,会逐步加载这些类,使用懒加载机制,并且war包或者jar
包中的类并不是一次性加载的,而是在使用的时候才会加载

import java.net.URLClassLoader;

public class TestDynamicLoad {
    static {
        System.out.println("*************load TestDynamicLoad************");
    }
    public static void main(String[] args) {
        new A();
        System.out.println("*************load test************");
        B b = null; //B不会加载,除非这里执行 new B()
    }
}
class A {
    static {
        System.out.println("*************load A************");
    }
    public A() {
        System.out.println("*************initial A************");
    }
}
class B {
    static {
        System.out.println("*************load B************");
    }
    public B() {
        System.out.println("*************initial B************");
    }
}
运行结果:
        *************load TestDynamicLoad************
        *************load A************
        *************initial A************
        *************load test************

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值