美文网首页
二十一、Class.forName vs ClassLoader

二十一、Class.forName vs ClassLoader

作者: 此间有道 | 来源:发表于2020-08-12 21:53 被阅读0次
    零、关键方法
    1. Class.forName(String className, boolean initialize, ClassLoader loader)
      1)initialize:是否执行类初始化操作,即是否执行<cinit>方法。
    2. Class.forName(String className)
      1)等价于:Class.forName(String className, true, currentLoader)
      2)currentLoader为真正加载当前类的classLoader(最后被委托的类加载器,执行defineClass方法的类加载器实例),非线程上下文的ClassLoader;
    3. ClassLoader.load(String className, boolean resolve)
      1)resolve:是否解析类,即是否解析符号为直接地址;
    4. ClassLoader.load(String className)
      1)等价:ClassLoader.load(String className, false)
    一、 关联点

    Class.forName最终也是调用ClassLoader去加载类的。

    二、区别

    1. 是否执行类初始化操作

    1)Class.forName可以控制是否执行类初始化操作;
    2)ClassLoader不会触发类初始化操作;

    案例:数据库驱动需要使用Class.forName来触发静态库注册驱动;

    2. 是否会解析数组类型

    1)Class.forName会解析数组类型,如[Ljava.lang.String;
    2)ClassLoader不会解析数组类型,加载时会抛出ClassNotFoundException;

    3. 是否有缓存

    1)类是缓存真正加载类的ClassLoader里的,此时需要避免委托给应用类加载器,而使用自定义类加载器去加载类
    考虑打破双亲委派或指定AppClassLoader不可见路径;
    2)只要指定每次加载类的ClassLoader即可实现热加载;

    public class HotLoadClassTest {
        private final File path = new File("/Users/kivi/Documents");
    
        @Test
        public void testClassForName() throws Throwable {
            Class aClass = Class.forName("MyString", true, new MyClassLoader(new URL[]{path.toURL()}));
            aClass.getDeclaredMethod("echo").invoke(null);
    
            /** 替换MyString实现,可加载最近类 **/
            aClass = Class.forName("MyString", true, new MyClassLoader(new URL[]{path.toURL()}));
            aClass.getDeclaredMethod("echo").invoke(null);
        }
    
        @Test
        public void testClassLoader() throws Throwable {
            Class<?> aClass = new MyClassLoader(new URL[]{path.toURL()}).loadClass("MyString");
            aClass.getDeclaredMethod("echo").invoke(null);
    
            /** 替换MyString实现,可加载最近类 **/
            aClass = new MyClassLoader(new URL[]{path.toURL()}).loadClass("MyString");
            aClass.getDeclaredMethod("echo").invoke(null);
        }
    
        public static class MyClassLoader extends URLClassLoader {
            public MyClassLoader(URL[] urls) {
                super(urls);
            }
    }
    
    public class MyString {
        private static int invokeTime = 0;
    
        static {
            System.out.println("here is MyString static block");
        }
    
        public static void echo() {
            System.out.println("第" + (invokeTime++) + "次被调用");
        }
    }
    
    

    相关文章

      网友评论

          本文标题:二十一、Class.forName vs ClassLoader

          本文链接:https://www.haomeiwen.com/subject/asomdktx.html