类加载器的方法_JS加载器

类加载器的方法_JS加载器packagecom.tech.load.def;/***@authorlw*@since2021/12/3*/publicclassUserImpl{static{System.out.println(“UserImplinit…”);}}packagecom.tech.load.def;/***@authorlw*@since2021/12/3*/publicclassDe..

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

package com.tech.load.def;

/**
 * @author lw
 * @since 2021/12/3
 */
public class UserImpl {
    static {
        System.out.println("UserImpl init ...");
    }
}

 

package com.tech.load.def;

/**
 * @author lw
 * @since 2021/12/3
 */
public class DefLoader {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //上下文类加载器,默认使用的是 应用程序类加载器
//        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//        Class<?> c1 = contextClassLoader.loadClass("com.tech.load.def.UserImpl");
//        c1.newInstance(); //classloader.loadClass 不会触发初始化,当创建对象时执行初始化,执行静态程序块内容 输出 "UserImpl init ..."
//        ClassLoader contextClassLoader1 = Thread.currentThread().getContextClassLoader();
//        Class<?> c2 = contextClassLoader1.loadClass("com.tech.load.def.UserImpl");
//        c2.newInstance(); //使用相同的类加载器 加载相同的类名 则加载的是同一个类,c1 c2是同一个类,由于已经初始化过 创建对象不再初始化 不再打印  "UserImpl init ..."
//        System.out.println(contextClassLoader==contextClassLoader1); //true 获取的上下文类加载器是同一个类加载器 
//        System.out.println(c1==c2); // true 同一个类加载器器,加载同名的类,第一次加载时加载的类会缓存到类加载器的缓存,再次加载直接在缓存读取,两次加载的是同一个类
        
        //直接获取类的类加载器 应用程序类加载器
        ClassLoader classLoader = UserImpl.class.getClassLoader();
        ClassLoader classLoader1 = UserImpl.class.getClassLoader();
        System.out.println(classLoader==classLoader1); //true 获取的是同一个应用程序类加载器
       
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        System.out.println(classLoader==contextClassLoader); //true 线程上下文类加载器默认采用的也是应用程序类加载器 与通过类型对象getClassLoader获取方式相同

        Class<?> c1 = Class.forName("com.tech.load.def.UserImpl"); //会触发类的初始化
        ClassLoader classLoader2 = c1.getClassLoader();
        System.out.println(classLoader==classLoader2); //true 获取的是同一个应用程序类加载器
        

    }
}

在应用程序中,默认我们获取上下文类加载器、类型对象getClassLoader都是采用的同一个应用程序类加载器,类在第一次被加载后会缓存到类加载器的缓存中,由于是同一个类加载器此时同名的类不能被多次加载,且应用程序类加载器只能加载classpath下的类。

如果我们想加载自定义路径下的类,需要用到自定义类加载器,可以去指定路径下加载类,且通过创建多个类加载器对象,加载的同名类相互隔离,也就是说同名类可以被多个自定义类加载器对象加载。

编写自定义类加载器:

  1.  继承ClassLoader;
  2. 重写findClass方法在指定路径下进行类的加载,得到字节数组,然后使用defineClass根据字节数组生成字节码文件 也就是class文件;

编写一个测试类Goods放在D盘下,javac得到class文件


/**
 * @author lw
 * @since 2021/12/3
 */
public class Goods {
    static {
        System.out.println("Goods init ...");
    }
}
javac Goods.java
package com.tech.load.def;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * 自定义类加载器 加载类
 * @author lw
 * @since 2021/12/3
 */
public class DefLoad7 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader classLoader1 = new MyClassLoader();
        Class<?> c1 = classLoader1.loadClass("Goods");
        Class<?> c2 = classLoader1.loadClass("Goods");
        System.out.println(c1==c2);//true 使用同一个类加载器加载同名类两次,实际只加载了一次,第二次是在类加载器的缓存加载的 结果两次加载的是同一个
        c1.newInstance(); //会初始化
        c2.newInstance(); //不会初始化 
        
        MyClassLoader classLoader2 = new MyClassLoader();
        Class<?> c3 = classLoader2.loadClass("Goods");
        System.out.println(c1==c3); //false 使用不同的类加载器对同一个类进行加载,会得到不同的类型对象
        c3.newInstance(); //会初始化
    }
}

//自定义类加载器 加载D盘下的类
class MyClassLoader extends ClassLoader{
    
    //去指定的路径下加载类
    //name是类名称
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String path="D:\\"+name+".class";
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //将指定路径下的文件 拷贝到输出流
            Files.copy(Paths.get(path),os);
            byte[] bytes = os.toByteArray();
            //调用父类的方法 根据字节数组生成字节码文件 也就是class文件
            //bytes -> *.class

            return defineClass(name,bytes,0,bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ClassNotFoundException("类文件未找到",e);
        }
    }
}

类加载器的方法_JS加载器

使用自定义加载器,创建多个类加载器对象去加载同一个类,会得到多个类型对象。 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196882.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • golang 进制转换_java string转integer

    golang 进制转换_java string转integer1-Youmaywriteyourconversionfunction(Fastest):funcString(nint32)string{buf:=[11]byte{}pos:=len(buf)i:=int64(n)signed:=i<0ifsigned{i=-i}for{pos–buf[pos],i=’0’+byt

    2022年9月2日
  • pycharm添加不了解释器_pycharm解释器为空

    pycharm添加不了解释器_pycharm解释器为空直接去项目文件下.idea/workspace.xml修改源文件即可。

    2022年8月29日
  • padStart()与padEnd()「建议收藏」

    padStart()与padEnd()「建议收藏」padStart()padStart()方法用另一个字符串填充当前字符串(如果需要的话,会重复多次),以便产生的字符串达到给定的长度。从当前字符串的左侧开始填充。语法str.padStart(targetLength[,padString])参数:targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。padString:可选填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截

    2022年9月4日
  • 以太坊(ETH)挖矿最新教程_以太坊个人挖矿

    以太坊(ETH)挖矿最新教程_以太坊个人挖矿以太坊(ETH)挖矿最新教程目前网上的大多数以太坊挖矿教程是很早整理编写的,基本都已过时不适用了。但挖矿是一个技术持续升级更新的过程,因此根据最新实战情况编写了本文,并争取在以后抽时间持续保持跟进更新。一.基本要求ETH 挖矿主要是使用显卡来挖矿。因此你需要一台拥有以下设备的PC(矿机):显卡、主板、电源、CPU、内存(推荐4G)、硬盘(推荐60G的SSD)、PCI-E转接线

    2022年10月15日
  • 微信支付-支付结果通知接收「建议收藏」

    微信支付-支付结果通知接收「建议收藏」微信支付-支付结果通知接收最近在做微信支付功能在微信成功后,微信通过异步方式返回支付结果是遇到了问题:参数接收不到。后来通过查阅资料才将问题解决,现在将解决方法分享一下。官方文档解释如上图所示:通过微信支付时要先在微信支付系统生成预付订单,然后才能在前台发起支付请求。生成预付订单时会向微信支付系统传递一个参数:notify_url。下面是该参数的解释:微信对这个回调路径没有特殊要求,不需要授权目录下

    2022年5月29日
  • hive数据类型转换cast_c语言数据类型的转换

    hive数据类型转换cast_c语言数据类型的转换在《Hive内置数据类型》文章中,我们提到了Hive内置数据类型由基本数据类型和复杂数据类型组成。今天的话题是Hive数据类型之间的转换。同Java语言一样,Hive也包括隐式转换(implicitconversions)和显式转换(explicitlyconversions)。  Hive在需要的时候将会对numeric类型的数据进行隐式转换。比如我们对两个不同数据类型的数字进行比较

    2022年9月21日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号