[Conocimiento profundo de JVM]: ClassLoader (ClassLoader) y modelo de delegación principal

Este artículo involucra

Carga de clases

Cada archivo de clase de extensión ".java" escrito almacena la lógica del programa que debe ejecutarse, y el compilador de Java compila estos archivos ".java" en un archivo con el nombre de extensión ".class".

jvmEl inicio se realiza mediante la creación de una clase inicial mediante el cargador de clases de arranque, que se jvmespecifica mediante la implementación específica. [De las especificaciones oficiales]

El archivo ".class" guarda las instrucciones de la máquina virtual convertida del código Java. Cuando se necesita usar una clase, la máquina virtual cargará su archivo ".class", creará el objeto de clase correspondiente y cargará el archivo de clase en el memoria de la máquina virtual , este proceso se denomina carga de clases.

Mecanismo de delegación de padres de mecanismo de carga de clases

Jvm usa un método de carga bajo demanda para archivos de clase. Cuando la clase necesita ser utilizada, jvm cargará su archivo de clase en la memoria para generar objetos de clase.

Al cargar la clase, se utiliza 双亲委派机制, es decir, un modo de delegación de tareas que entrega la solicitud a la clase padre para su procesamiento.

Proceso de implementación:

Carga de clases durante el tiempo de ejecución de Java

Conozca los métodos más importantes de la clase ClassLoader, que se utilizarán para escribir el eco en el exploit.

loadClass (String)

Este método carga el tipo binario con el nombre especificado (incluido el nombre del paquete). Ya no se recomienda que los usuarios lo reescriban después de JDK1.2, pero los usuarios pueden llamar directamente a este método. El método loadClass () es implementado por la clase ClassLoader La lógica es la realización del modelo de delegación principal . El código fuente es el siguiente. loadClass (String name, boolean resolve) es un método sobrecargado, y el parámetro resolve representa si se debe generar un objeto de clase y realizar operaciones relacionadas con la resolución en al mismo tiempo.

protected Class<?> loadClass(String name, boolean resolve)
      throws ClassNotFoundException
  {
      synchronized (getClassLoadingLock(name)) {
          // 先从缓存查找该class对象,找到就不用重新加载
          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
                  // 如果都没有找到,则通过自定义实现的findClass去查找并加载
                  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;
      }
  }

 

Acerca de la diferencia loadClass (), findClass (), defineClass ()

 

Cómo implementar un ClassLoader

Primero herede la clase ClassLoader y luego anule el método findClass (String name) para completar un cargador de clases con un modelo de delegación principal.

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 查看是否已经加载过该类,加载过的类会有缓存,是使用native方法实现的
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    //父类不为空则先让父类加载
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                    //父类是null就是BootstrapClassLoader,使用启动类类加载器加载
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // 父类类加载器不能加载该类
                }

                //如果父类未加载该类
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    //让当前类加载器加载
                    c = findClass(name);
                }
            }
            return c;
        }
    }

En el modo de método de plantilla clásico, las subclases solo necesitan implementar findClass y preocuparse por dónde se cargan.

Un punto más, el padre debe configurarse por sí mismo, lo que se puede hacer en el constructor

Link de referencia:

Cargador de clases Jvm, una explicación detallada del mecanismo de carga de clases, solo lea este

Comprensión profunda del cargador de clases de Java (ClassLoader)

Conozca las preguntas de la entrevista del cargador casi de clase

Supongo que te gusta

Origin blog.csdn.net/Candyys/article/details/107025266
Recomendado
Clasificación