类加载器

1、ClassLoader类加载器

系统的环境变量CLASSPATH的主要作用是在JVM启动的时候进行类加载路径的定义。在JVM中可根据类加载器进行指定路径中类的加载,即找到类加载器就找到了类的来源。而类加载器通过ClassLoader类来获得,要想获得ClassLoader类对象则需使用Class类(反射的根源)来实现。方法:public ClassLoader getClassLoader​(),进一步可以获取其父类ClassLoader类对象:public final ClassLoader getParent​()

使用示例:

public class CDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = CDemo.class ;
        System.out.println(clazz.getClassLoader()) ; //获取当前类的加载器
        System.out.println(clazz.getClassLoader().getParent()) ;
        System.out.println(clazz.getClassLoader().getParent().getParent()) ;
    }
}

运行结果:

AppClassLoader应用程序加载器;

PlatformClassLoader平台类加载器(JDK1.8及以前为扩展类加载器ExtClassLoader,该类存在不安全问题,所以被废除不再使用);

还有一个无法看见的系统类加载器Bootstrap;

当获得类加载器后就可以利用类加载器来实现类的反射加载处理。

2、自定义ClassLoader处理类

类加载器的加载先后顺序:Bootstrap→PlatformClassLoader→AppClassLoader→自定义类加载器

系统类中的类加载器都是根据CLASSPATH路径进行类加载的,而自定义的类加载器,就可以由开发者任意指派类的加载位置。

示例:

D盘下程序文件:

package com.demo ;
public class CDemo {
    public void send() {
        System.out.println("一只瓶子a") ;
    }
}

自定义类加载器:

package com.demo1;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

public class TimerDemo {
    public static void main(String[] args) throws Exception {
        newClassLoader classLoader = new newClassLoader() ; //实例化自定义类加载器
        Class<?> cls = classLoader.loadData("com.demo.CDemo") ;
        Object obj = cls.getDeclaredConstructor().newInstance() ; //根据构造方法实例化类对象
        Method method = cls.getDeclaredMethod("send") ;
        method.invoke(obj) ;
    }
}
class newClassLoader extends ClassLoader {
    private static final String DEMO_CLASS_PATH = "D:" + File.separator + "CDemo.class" ;
    /**
     * 进行指定类的加载
     * @param className 类的完整名称“包.类”
     * @return 返回一个指定类的Class对象
     * @throws Exception 如果类文件不存在则无法加载
     */
    public Class<?> loadData(String className) throws Exception {
        byte [] data = this.loadClassData() ; //读取二进制文件
        if(data != null) {
            return super.defineClass(className, data, 0, data.length) ;
        }
        return null ;
    }
    public byte [] loadClassData() throws Exception { //通过文件进行类的加载
        InputStream input = null ;
        ByteArrayOutputStream bos = null ; //将数据加载到内存中
        byte data [] = null ;
        try {
            bos = new ByteArrayOutputStream() ; //实例化内存流
            input = new FileInputStream(new File(DEMO_CLASS_PATH)) ; //文件流加载
            input.transferTo(bos) ; //读取数据
            data = bos.toByteArray() ;
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            if(input != null) {
                input.close();
            }
            if(bos != null) {
                bos.close();
            }
        }
        return data ;
    }
}
结合日后的网络程序开发,就可以通过一个远程的服务器来确定类的功能。

如果要加载的程序类是由系统提供的类则会由系统类进行加载,如果开发者定义的类与系统类名称相同,那么为了保证系统的安全其不会被加载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值