análisis casos mecanismo de delegación de cargador de clases profundidad 17- padre

Padres casos mecanismo de la clase delegación loader análisis en profundidad

java.lang.ClassLoader
protected Class<?> loadClass(String name , 
                          boolean resolve) 
throws ClassNotFoundException

Cargas de la clase con el nombre especificado binaria. La implementación predeterminada de este método busca clases en el siguiente orden:

① Invoke findLoadedClass (String) para comprobar si la clase ya se ha cargado.
② invocar el método loadClass en el cargador de clases padre. Si el padre es nulo el cargador de clases incorporada a la máquina virtual se utiliza, en su lugar.
③ invocar el método FindClass (String) para encontrar la clase.

Usando el nombre del binario de la carga de la clase especificada. La implementación por defecto de este método para la búsqueda de clases en el siguiente orden:

① llamar findLoadedClass cheque (String) si se carga la clase.

② llamar al método loadClass en el cargador de clases padre. Si el padre está vacía, a continuación, utilizar la incorporada en el cargador de clases de máquina virtual.

③ llamar al método FindClass (String) para encontrar la clase.

Si se encontró la clase mediante los pasos anteriores, y la bandera determinación es cierto, este método a continuación invoca el método resolveClass (Clase) en la clase de objeto resultante.

Si los pasos anteriores para encontrar la clase, y la bandera determinación es cierto, este método se llama el método de generación objeto de clase resolveClass (Clase).

Se anima subclases de ClassLoader para anular FindClass (String), en lugar de este método.
A menos que se reemplaza, este método sincroniza en el resultado del método getClassLoadingLock durante todo el proceso de carga de clases.

Subclase animó reescritura cargador FindClass (Cadena), en lugar de este método.

A menos reescrito, si no todo el proceso de carga de clases, este método resultará método de sincronización getClassLoadingLock.

Parámetros:
Nombre - El nombre del archivo binario de la clase
resolución - Si esto es cierto entonces resolver las clases
Devuelve:
la clase de objeto resultante
Lanza:
ClassNotFoundException - Si no se pudo encontrar la clase

Ofrecer Fuente:

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
  • El artículo 15 de la clase personalizada cargador de seguir analizando:
    • En (1), (2), (3) se añadieron a declaraciones de impresión, con el tiempo encontrado (1), (2) no está ejecutando, solamente (3) se ejecuta. Debido MyTest16 loader1 = new MyTest16 ( "loader1 ");, es un parámetro de constructor, de modo que 'el cargador de clases sistema como cargador de cargador de clases padre' , al mismo tiempo, y el cargador de clases del sistema puede cargar MyTest16, por lo , la copia impresa de la declaración final es: el cargador de clases del sistema, en lugar de la clase loader nuestra costumbre.
    • La razón, de acuerdo con el mecanismo de delegación de la clase padre cargador, MyTest16 ( "loader1") loader1 ciertamente no es el primero en probar este cargador de clases a la carga, pero confiado a sus intentos padre a la carga, y el padre loader1 es el "sistema de cargador de clases ".
    • Si un cargador de clases se carga correctamente clases de prueba, entonces el cargador de clases se denomina cargador de clases definido , todos vuelven Clase aplicarse con éxito en el cargador de clase de objeto (incluyendo el cargador de clases personalizado) son llamados a la clase inicial cargador . [Cargador de clases define aquí es: el cargador de clases del sistema, el cargador de clases es inicialmente: la carga cargador de clases del sistema y de encargo clase (loader1)]
/**
 * 自定义类加载器
 */
public class MyTest16 extends ClassLoader{
    private String classLoaderName;       //标示性的属性,类加载器的名字
    private final String fileExtension = ".class";  //每一次中磁盘上读取的文件的扩展名
    public MyTest16(String classLoaderName){
        super();   //将系统类加载器当做该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }
    // 该方法的前提是已经有了parent这样一个加载器
    public MyTest16(ClassLoader parent, String classLoaderName){
        super(parent);   //显示执行该类加载器的父加载器(parent)
        this.classLoaderName = classLoaderName;
    }
    @Override
    public String toString() {
        return "[" + this.classLoaderName + "]";
    }

    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        System.out.println("findClass invoked:"+className);             //(1)
        System.out.println("class loader name:"+this.classLoaderName);	//(2)
       
        byte[] data = this.loadClassData(className);
        return this.defineClass(className,data,0,data.length); //最终返回一个字节class对象
    }

    /*
    	通过类的名字(className),把对应的文件的名字找到,并以输入输出流的形式最后返回一个字节数组,这个
    	字节数组就是从class文件中读取的二进制信息。
    */
    private byte[] loadClassData(String className){
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;
        try {
            this.classLoaderName = this.classLoaderName.replace(".","/");
            is = new FileInputStream(new File(className + this.fileExtension));
            int ch;
            while (-1 != (ch=is.read())){
                baos.write(ch);
            }
            data = baos.toByteArray();
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try {
                baos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return data;
    }

    public static void test(ClassLoader classLoader) throws Exception {
        //1.下面这个调用的loadClass方法,其实调用的还是ClassLoader类中的方法,
        //2.loadClass方法回去调用我们上面所重写的 findClass方法,根据二进制名字寻找
        //class对象(这里是MyTest10类)。 【这也是自定义类最关键的一环,重写findClass方法】
        Class<?> clazz = classLoader.loadClass("Jvm.MyTest10");
        Object object = clazz.newInstance();
        System.out.println(object);
        System.out.println(object.getClass().getClassLoader());  //(3)
    }

    public static void main(String[] args) throws Exception {
        MyTest16 loader1 = new MyTest16("loader1");
        test(loader1);
    }

}
运行结果:
      MyTest10 static block
      Jvm.MyTest10@6d6f6e28
      sun.misc.Launcher$AppClassLoader@18b4aac2

1. El uso de un cargador de clase personalizada para cargar los archivos de clase:

  • archivos de clase primera MyTest10, crear una carpeta en el escritorio carpeta Jvm poner dentro, y luego eliminar el archivo MyTest10.class generado por el compilador. Cuando se ejecuta el programa, cargador loader1 (cargador de medida) los padres encargó por primera vez (el cargador de clases del sistema) para cargar el cargador de clases del sistema para obtener los archivos de clases correspondientes a encontrar directorios de ruta de clases, sin embargo, porque se elimina el archivo de clase, tan cargado sin éxito, a continuación, hasta los padres a encontrar el cargador de clases raíz, carga o sin éxito, a continuación, volver a cargador de clases loader1 para cargar los MyTest10.class loader1
  • ★★ ★★ Si el compilador genera el archivo MyTest10.class no se elimina , a continuación, por el cargador de clases de sistema para cargar el archivo de clase, [razón: hay padres mecanismo de confianza, cargador de clases loader1 llamará al sistema de cargador de clases padre para tratar de carga ruta de clase carpeta de archivo de clase, esta vez debido a la presencia del archivo de clase en la ruta de clase, por lo que se debe cargar. Y, para no cargar archivos de clase en el escritorio]
/**
 * 自定义类加载器
 */
public class MyTest16 extends ClassLoader{
    private String classLoaderName;
    private String path;
    private final String fileExtension = ".class";
    public MyTest16(String classLoaderName){
        super();   //将系统类加载器当做该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }
    public MyTest16(ClassLoader parent, String classLoaderName){
        super(parent);   //显示执行该类加载器的父加载器(parent)
        this.classLoaderName = classLoaderName;
    }
    public void setPath(String path) {
        this.path = path;
    }

    @Override
    public String toString() {
        return "[" + this.classLoaderName + "]";
    }

    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        System.out.println("findClass invoked:"+className);
        System.out.println("class loader name:"+this.classLoaderName);

        byte[] data = this.loadClassData(className);
        return this.defineClass(className,data,0,data.length); //最终返回一个class对象
    }

    private byte[] loadClassData(String className){
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        className = className.replace(".","\\");
        try {
            is = new FileInputStream(new File(this.path + className + this.fileExtension));
            baos = new ByteArrayOutputStream();
            int ch;
            while (-1 != (ch = is.read())){
                baos.write(ch);
            }
            data = baos.toByteArray();
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try {
                is.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }
    public static void main(String[] args) throws Exception {
        MyTest16 loader1 = new MyTest16("loader1");
        loader1.setPath("C:\\Users\\admin\\Desktop\\");
		  //这里是将MyTest10的class文件,在桌面创建一个文件夹Jvm放里面,去加载桌面文件夹下的class文件
        Class<?> clazz = loader1.loadClass("Jvm.MyTest10");
        System.out.println("class:"+clazz.hashCode());
        Object object = clazz.newInstance();
        System.out.println(object);
    }
}
运行结果:
      findClass invoked:Jvm.MyTest10 <--- 说明调用了自定义的类加载器loader1去加载MyTest10.class
      class loader name:loader1		 <---
      class:1173230247
      MyTest10 static block
      Jvm.MyTest10@330bedb4
  • Ejemplo 2:

    • Premisa: existe el archivo MyTest10.class ruta de clase, trabajar a partir de los resultados finales, crea dos cargadores de clases, después de que el cargador de primera clase se ha cargado MyTest.class, cuando una segunda carga es la misma clase (MyTest. clase), cuando no se carga debido a que el código fuente debe ser juzgado, si la clase ya está cargado, a continuación, devuelve directamente al objeto. Por lo tanto, el código hash correspondiente () devuelve el mismo, y MyTest10 bloque estático se ejecuta sólo una vez.

    • Sin embargo, si MyTest10.class ruta de clase del archivo se elimina, los resultados de operación, como se muestra a continuación, pero sigue siendo la clase MyTest10 se carga una vez, [ una clase sólo se carga una vez definido y no se ha roto , porque se puede ver la clase MyTest10 MyTest10 bloque de bloque estático estático de código se ejecuta sólo una vez, para ser cargado una sola vez descrita MyTest10], puede verse que, la salida de clase código hash () es diferente aquí implica espacio de nombres problema.

      • Espacio de nombres:

        • Cada cargador de clases tiene su propio espacio de nombres, el espacio de nombres por el cargador de clases y de todas las clases del cargador de clases padre cargado .
        • En el mismo espacio de nombres, las dos clases [nombre completo de la clase (incluyendo el paquete de) la misma no se produce].
        • En un espacio de nombres diferente, [que puede ser un nombre de clase completo (incluyendo el paquete de) los mismos] dos clases.
      findClass invoked:Jvm.MyTest10
      class loader name:loader1
      class:1173230247
      MyTest10 static block   //第一加载,并初始化,静态代码块被执行力。
      Jvm.MyTest10@330bedb4
      
      findClass invoked:Jvm.MyTest10
      class loader name:loader2
      class:2125039532
      Jvm.MyTest10@12a3a380
      
//这里只写了主函数
public static void main(String[] args) throws Exception {
      MyTest16 loader1 = new MyTest16("loader1");
      loader1.setPath("C:\\Users\\admin\\Desktop\\");

      Class<?> clazz = loader1.loadClass("Jvm.MyTest10");
      System.out.println("class:"+clazz.hashCode());
      Object object = clazz.newInstance();
      System.out.println(object);

      System.out.println();

      MyTest16 loader2 = new MyTest16("loader2");
      loader1.setPath("C:\\Users\\admin\\Desktop\\");

      Class<?> clazz1 = loader2.loadClass("Jvm.MyTest10");
      System.out.println("class:"+clazz1.hashCode());
      Object object1 = clazz.newInstance();
      System.out.println(object1);
}
运行结果:
   class:1836019240            <--
   MyTest10 static block		 <--	
   Jvm.MyTest10@135fbaa4

   class:1836019240				 <--
   Jvm.MyTest10@45ee12a7
Publicado 25 artículos originales · ganado elogios 0 · Vistas 1456

Supongo que te gusta

Origin blog.csdn.net/qq_40574305/article/details/104784864
Recomendado
Clasificación