Java类加载机制:从字节码到对象的奇妙之旅

目录
什么是类加载机制?
类加载顺序
类加载顺序图
双亲委派模型
双亲委派模型示意图
如何打破双亲委派模型?
要想学好java,首先得知道它是什么,怎么运行的,怎么加载的,运行的是个什么东西,今天我写篇文章说一下,表演开始喽
Java是一门面向对象的编程语言,它的特点之一就是可以跨平台运行 。为什么可以跨平台,因为Java程序不是直接编译成机器码,而是编译成一种中间格式的字节码(),然后由Java虚拟机(JVM)在不同的平台上解释执行 。
那Java虚拟机是如何加载和执行字节码的?这就涉及到了Java类加载机制
什么是类加载机制?
类加载机制是Java虚拟机将字节码转换成可运行的类的过程 。这个过程包括三个主要步骤:加载、链接和初始化?编辑
初始化:就是执行类中的静态初始化器和静态初始化程序,执行静态初始化程序,把静态变量初始化成指定的值;()方法由编译器自动产生,收集类中{}代码块中类变量赋值语句和类中静态成员变量的赋值语句 。此时将会执行静态代码块和静态方法 。
初始化过程的注意点
下面的实例解释下,b可以赋值,c不可以,提示,因为c在代码块下面,也就是之后
类加载顺序
一般来说,类加载顺序遵循以下原则:
主动引用:当一个类被主动引用时,该类才会被加载 。主动引用包括下面几种情况:
创建类的实例,如new A() 。调用类的静态方法,如A.() 。访问类或接口的静态变量,或者对该静态变量赋值,如A.field或A.field = value 。反射调用类的方法或构造器,如Class.("A")或A.class.("") 。初始化一个类的子类,如new B(),其中B是A的子类,这时候会先加载A 。虚拟机启动时被标明为启动类的类,如java。
被动引用:当一个类被被动引用时,该类不会被加载 。被动引用包括下面几种情况:
访问或设置一个数组类型的静态变量,如A[] arr或A[]. 。引用一个常量字段,如A.,其中是用final修饰的静态变量,并且在编译期已经确定了值 。引用一个接口中定义的常量字段,如I.,其中是用final修饰的变量,并且在编译期已经确定了值 。引用一个父类中定义的静态字段,如B.field,其中field是在A中定义的静态变量,而B是A的子类 。类加载顺序图
大家可以验证下,可能需要的示例太多这里先不举例了
双亲委派模型
双亲委派模型是Java类加载机制的一个重要特征,它决定了一个类由哪个类加载器()来加载 。类加载器是Java虚拟机的一个组件,它负责根据不同的策略来加载类 。Java虚拟机提供了三种内置的类加载器:
除了这三种内置的类加载器外,还可以自定义类加载器,只要继承java.lang.抽象类,并重写其中的方法即可 。自定义的类加载器通常会作为应用类加载器的子类加载器 。
双亲委派模型的工作原理是:当一个类需要被加载时,首先会委托给其父类加载器去尝试加载,如果父类加载器无法加载,则再由自己去尝试加载 。这样就形成了一个从下到上的委托链,最终由启动类加载器作为最后的尝试者 。这样做的好处是可以避免重复或冲突的类被加载,保证了Java程序的安全性和稳定性 。
双亲委派模型示意图
双亲委派模型的代码在java.lang.类中的函数中实现,其逻辑如下:
如何打破双亲委派模型?
举个栗子
public class MyClassLoader extends ClassLoader {@Overrideprotected Class findClass(String name) throws ClassNotFoundException {// 这里可以自定义类的加载方式,例如从文件系统加载类文件等return super.findClass(name);}}