JVM简笔—类的加载

什么是JVM?

JVM基本概念

  • JVM是Java虚拟机(Java Virtual Machine)的缩写,是java运行环境的一部分
  • 是可运行java代码的假想计算机,包括一套字节码指令集(用来解释字节码文件)、栈、堆、垃圾回收、程序计数器等
  • 是运行在操作系统之上的,没有与硬件系统直接交互!

运行过程:

我们在编译器中写的java程序都是以.java后缀的,通过编译器会将.java文编译为.class字节码文件,java虚拟机中的解释器会将class文件转变为机器可识别的机器码。

如下:
在这里插入图片描述
JVM所在位置
在这里插入图片描述

JVM的体系结构

在这里插入图片描述

类加载机制:

当程序用到还未被加载到内存中的类时,系统会对该类进行初始化(三个步骤)
在这里插入图片描述
详细过程:

  • 类的加载

    将class文件字节码加载到内存中,将这些数据转换成方法区运行时数据,并生成一个代表这个类的java.lang.Class对象。注意这里不一定非得从.class文件中获取,可以从zip包(jar 和 war…)中获取,也可以运行时生成

  • 类的链接:

    1、验证:确保加载的类信息符合JVM规范,保证Class文件的字节流中包含的信息符合虚拟机的要求,不会危害虚拟机本身

    2、准备:正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量 所使用的内存空间

    3、解析:虚拟机常量池内的符号引用(变量名)替换为直接引用(地址)的过程

  • 类的初始化:

    1、执行类构造器< clinit> ()方法。类构造器< clinit> ()方法的作用是在编译期自动收集类中所有类变量(静态变量)的赋值动作和静态代码块中的语句。 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成< clinit> ()方法

    2、当初始化类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化

    3、虚拟机会保证一个类的< clinit> ()方法在多线程环境中被正确加锁和同步。

类加载器(ClassLoader)

Java类加载器(Java Classloader)是Java运行时环境的一部分,负责动态加载Java类到Java虚拟机的内存空间中

我们知道,Java 语言是一种具有动态性的解释型语言,类只有被加载到 JVM 后才能运行。当运行指定程序时,JVM 会将编译生成的 Class 文件按照一定的规则加载到内存中。这个加载过程是由类加载器完成的,具体来说,就是由 ClassLoader 和它的子类来实现的。其实质是把类文件从硬盘读取到内存中。

java类的加载是动态的,它并不会一次性将全部的类都加载进去之后在运行,而是先将保证程序能运行的类加载到JVM中,其它的类是在需要用到的时候才进行加载的

类加载器的类型:

  • 启动类加载器(BootStrap ClassLoader)(c++编写,无法直接获取)
  • 扩展类加载器(Extension ClassLoader)
  • 应用程序加载器(Application ClassLoader)
  • 用户自定义类加载器(User ClassLoader)

类加载器可以通过Class对象来获取(getClassLoader)

package ttt;

public class Person {

    public static void main(String[] args) {

        Person p1 = new Person();
        Class<? extends Person> aClass1 = p1.getClass();
        
        ClassLoader classLoader = aClass1.getClassLoader();
        ClassLoader c1 = classLoader.getParent();
        ClassLoader c2 = classLoader.getParent().getParent();

        System.out.println(classLoader);
        System.out.println(c1);
        System.out.println(c2);

    }
}
//输出
// 应用程序加载器
jdk.internal.loader.ClassLoaders$AppClassLoader@3fec223d
//扩展类加载器
jdk.internal.loader.ClassLoaders$PlatformClassLoader@39ce698f
// 无法通过java程序获取启动类加载器,输出null
null

扩展:双亲委派机制

当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父加载器(一直向上委托,直到启动类加载器)。如果父加载器找不到指定类时,子类加载器才会尝试去加载

在这里插入图片描述
这样做的好处是为了防止代码植入。

假如我们自定义了一个java.lang.String类,但最终使用的一定是启动类加载器中的String类,而不是我们自己定义的,就避免了业务逻辑混乱的情况。

小结:

  • 了解JVM的体系结构
  • 了解类加载的过程
  • 了解类加载器及双亲委派机制的原理
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值