双亲委派及自定义类加载器

本文详细介绍了Java类从编译到执行的过程,包括ClassLoader的工作原理,类的装载、链接(校验、准备、解析)和初始化阶段。讨论了不同类型的ClassLoader,如BootStrapClassLoader、ExtClassLoader和AppClassLoader,以及自定义ClassLoader的实现。此外,还阐述了类加载的双亲委派机制,并通过示例展示了如何使用自定义类加载器加载类。
摘要由CSDN通过智能技术生成

绪论

谈谈类从编译到执行的过程

  • 编译器将Robot.java源文件编译为Robot.class字节码文件
  • ClassLoader将字节码转换为JVM中的Class对象
  • JVM利用Class对象实例化Robot对象

谈谈CLassLoader:

  • ClassLoader再java中有着非常重要的作用,它主要工作在Class的装载阶段,其主要作用是从系统外部获得Class二进制数据流。他是java的核心组件,所有的Class都是由ClassLoader进行记载的,ClassLoader负责通过将Class文件里的二进制数据流装进系统,然后交给java虚拟机进行链接、初始化等操作。

Classloader的种类有哪些

  • BootStrapClassLoader:C++编写,加载核心库java.*
  • ExtClassLoader:java编写,加载扩展库javax.*
  • AppClassLoader:java编写,加载程序所在目录中的类
  • 自定义ClassLoader:Java编写,定制化加载

类的装载过程

  • 加载 -> 通过ClassLoader加载class文件字节码,生成class对象
  • 链接 ->
    1、校验:检查加载的class的正确性和安全性
    2、准备:为类变量分配存储空间并设置类变量初始值
    3、解析:JVM将常量池内的符号引用转换为直接引用(可选)
  • 初始化 -> 执行类变量赋值和静态代码块
    1、使用new字节码指令创建类的实例,或者使用getstatic、putstatic读取或者设置一个静态字段的值(放入常量池中的常量除外),或者调用一个静态方法的时候,对应类必须进行过初始化。
    2、通过反射进行调用的时候,如果类没有进行过初始化,则要首先进行初始化。
    3、当初始化一个类的时候,如果发现父类没有进行过初始化,则首先触发父类初始化。对于静态字段,自由直接定义这个字段的类才会被初始化,因此,通过其子类引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
    4、当虚拟机启动时,用户需要指定一个主类,(包含main方法的类)虚拟机会首先初始化这个类。

loadClass 和 forName的区别

  • Class.forName得到的class是已经初始化完成的
  • Classloader.loadClass得到的class是还没有链接的

双亲委派机制图示

在这里插入图片描述

自定义类加载器

新建需要被加载的类ByteCodeSimple.java,放在桌面并通过javac编译为.class文件

public class ByteCodeSimple {
	
	static {
		System.out.println("new instance start");
	}
	
	public static int add(int a, int b) {
		int c = 0;
		c = a + b;
		return c;
	}
	
}

自定义类加载器实现 CustomClassLoader.java

package com.***.demo.test;

import java.io.*;

public class CustomClassLoader extends ClassLoader {

    private String path;
    private String classLoaderName;

    public CustomClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] b = loadClassData(path + name + ".class");
        return defineClass(name, b, 0, b.length);
    }

    private byte[] loadClassData(String name) {
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
                out.write(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
}

测试类

package com.***.demo.test;

public class CustomClassLoaderTest {

    public static void main(String[] args) throws Exception {
        String path = "C:\\Users\\Desktop\\";
        String className = "ByteCodeSimple";
        CustomClassLoader myClassLoad = new CustomClassLoader(path, "自定义类加载器");
        Class<?> c = myClassLoad.loadClass(className);
        c.newInstance();
    }

}

测试结果

new instance start

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值