欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

Class.forName()方法实际上 CAD加密 也是调用的CLassLoader来实现的

点击: 次  来源:宝鼎软件 时间:2018-08-04

原文出处: 纪莫

媒介

最近在口试进程中有被问到,在Java反射中Class.forName()加载类和利用ClassLoader加载类的区别。其时没有想出来厥后本身研究了一下就写下来记录一下。

表明

在java中Class.forName()和ClassLoader都可以对类举办加载。ClassLoader就是遵循双亲委派模子最终挪用启动类加载器的类加载器,实现的成果是“通过一个类的全限命名来获取描写此类的二进制字节约”,获取到二进制流后放到JVM中。Class.forName()要领实际上也是挪用的CLassLoader来实现的。

Class.forName(String className);这个要领的源码是

@CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

最后挪用的要领是forName0这个要领,在这个forName0要领中的第二个参数被默认配置为了true,这个参数代表是否对加载的类举办初始化,昆山软件开发,配置为true时会类举办初始化,代表会执行类中的静态代码块,以及对静态变量的赋值等操纵。

也可以挪用Class.forName(String name, boolean initialize,ClassLoader loader)要领来手动选择在加载类的时候是否要对类举办初始化。Class.forName(String name, boolean initialize,ClassLoader loader)的源码如下:

/* @param name       fully qualified name of the desired class
     * @param initialize if {@code true} the class will be initialized.
     *                   See Section 12.4 of <em>The Java Language Specification</em>.
     * @param loader     class loader from which the class must be loaded
     * @return           class object representing the desired class
     *
     * @exception LinkageError if the linkage fails
     * @exception ExceptionInInitializerError if the initialization provoked
     *            by this method fails
     * @exception ClassNotFoundException if the class cannot be located by
     *            the specified class loader
     *
     * @see       java.lang.Class#forName(String)
     * @see       java.lang.ClassLoader
     * @since     1.2
     */
    @CallerSensitive
    public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // Reflective call to get caller class is only needed if a security manager
            // is present.  Avoid the overhead of making this call otherwise.
            caller = Reflection.getCallerClass();
            if (sun.misc.VM.isSystemDomainLoader(loader)) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);
                if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }
        return forName0(name, initialize, loader, caller);
    }

源码中的注释只摘取了一部门,个中对参数initialize的描写是:if {@code true} the class will be initialized.意思就是说:假如参数为true,则加载的类将会被初始化。

举例

下面照旧举例来说明功效吧:

一个含有静态代码块、静态变量、赋值给静态变量的静态要领的类

public class ClassForName {

    //静态代码块
    static {
        System.out.println("执行了静态代码块");
    }
    //静态变量
    private static String staticFiled = staticMethod();

    //赋值静态变量的静态要领
    public static String staticMethod(){
        System.out.println("执行了静态要领");
        return "给静态字段赋值了";
    }
}

测试要领:

public class MyTest {
    @Test
    public void test44(){

        try {
            Class.forName("com.test.mytest.ClassForName");
            System.out.println("#########支解符(上面是Class.forName的加载进程,下面是ClassLoader的加载进程)##########");
            ClassLoader.getSystemClassLoader().loadClass("com.test.mytest.ClassForName");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}

运行功效:

执行了静态代码块
执行了静态要领
#########支解符(上面是Class.forName的加载进程,下面是ClassLoader的加载进程)##########

按照运行功效得出Class.forName加载类是将类进了初始化,昆山软件公司,而ClassLoader的loadClass并没有对类举办初始化,只是把类加载到了虚拟机中。

应用场景

在我们熟悉的Spring框架中的IOC的实现就是利用的ClassLoader。