国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home Java JavaBase Detailed explanation of java class loader ClassLoader

Detailed explanation of java class loader ClassLoader

Nov 27, 2019 pm 03:35 PM
classloader class loader

Detailed explanation of java class loader ClassLoader

Ways to get ClassLoader

1. Get the ClassLoader of the current class

clazz.getClassLoader()

2. Get the ClassLoader of the current thread context

Thread.currentThread().getContextClassLoader();

3. Get the system’s ClassLoader

ClassLoader.getSystemClassLoader()

4. Get the caller’s ClassLoader

DriverManager.getCallerClassLoader

ClassLoader source code analysis

(Recommended learning: Java Video Tutorial)

Overview

The class loader is used to load classes Object, ClassLoader is an abstract class. If we are given the binary name of a class, the class loader should try to locate or generate the data that makes up the defining class. A typical strategy is to convert a given binary name into a file name, and then read the class file corresponding to this file name from the file system.

Each Class object will contain a reference to the ClassLoader that defines it.

The Class object of the array class is not created by the class loader, but is automatically created by the JVM as needed during the Java runtime. For the class loader of the array class, it is returned through Class.getClassLoader(), which is the same as the class loader of the element type in the array; if the element type in the array is a native type, The array class does not have a class loader [Code 1].

The application implements a subclass of ClassLoader to extend the way the JVM dynamically loads classes.

Class loaders are typically used by security managers to identify security domain issues.

The ClassLoader class uses a delegation model to find classes and resources. Each instance of ClassLoader will have a parent ClassLoader associated with it. When ClassLoader is asked to find a class or resource, the ClassLoader instance tries on its own Before searching for a class or resource, its parent class loader will be delegated to complete it. The built-in class loader of the virtual machine, called the startup class loader, does not have a parent loader, but it can be used as the parent class loader of a class loader [Parental delegation mechanism].

A class loader that supports concurrent class loading is called a parallel class loader. It is required to register itself through the ClassLoader.registerAsParallelCapable method during initialization. The ClassLoader class is registered as parallel by default, but if it If the subclasses are also loaded in parallel, you need to register the subclasses separately.

In an environment where the delegation model is not strictly hierarchical, the class loader needs to be parallel, otherwise class loading will cause deadlock, because the loader's lock is always held during the class loading process.

Normally, the Java virtual machine loads classes from the local file system in a platform-dependent manner. For example, in UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment.
However, some classes do not come from files; they are obtained from other sources, such as the network, or [dynamic proxies] are built by the application itself. The defineClass(defineClass) method will convert the byte array into an instance of Class. An instance of this newly defined class can be created by Class.newInstance.

The methods and constructors of objects created by a class loader may reference other classes. In order to determine the referenced class, the Java virtual machine calls the loadClass of the class loader that originally created the class. method.

Binary name: Any class name provided to CalssLoader in the form of a string parameter must be a binary name, including the following four situations

  • "java.lang. String" Normal class
  • "javax.swing.JSpinner$DefaultEditor" Internal class
  • "java.security.KeyStore\(Builder\)FileBuilder$1" Internal of KeyStore The inner class of class Builder The first anonymous inner class of FileBuilder
  • "java.net.URLClassLoader$3$1" The third anonymous inner class of URLClassLoader class The first anonymous inner class

Code 1:

public class Test12 {
    public static void main(String[] args) {
        String[] strings = new String[6];
        System.out.println(strings.getClass().getClassLoader());
        // 運(yùn)行結(jié)果:null

        Test12[] test12s = new Test12[1];
        System.out.println(test12s.getClass().getClassLoader());
        // 運(yùn)行結(jié)果:sun.misc.Launcher$AppClassLoader@18b4aac2

        int[] ints = new int[2];
        System.out.println(ints.getClass().getClassLoader());
        // 運(yùn)行結(jié)果:null
    }
}

loadClass method

The source code of loadClass is as follows. The loadClass method loads the Class with the specified binary name. By default, it is in the following order. Find a class:

a) Call findLoadedClass(String) to check whether this class is loaded

b) Call the loadClass method of the parent class loader. If the parent class loader is null, it will be called Start the class loader

c) Call the findClass(String) method to find

Use the above steps if the class is found and resolve is true, the resolveClass(Class) method will be called

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;
  }
}

findClass method

findClass的源碼如下,findClass尋找擁有指定二進(jìn)制名稱的類,JVM鼓勵(lì)我們重寫此方法,需要自定義加載器遵循雙親委托機(jī)制,該方法會(huì)在檢查完父類加載器之后被loadClass方法調(diào)用,默認(rèn)返回ClassNotFoundException異常。

protected Class<?> findClass(String name) throws ClassNotFoundException {
    throw new ClassNotFoundException(name);
}

defineClass方法

defineClass的源碼如下,defineClass方法將一個(gè)字節(jié)數(shù)組轉(zhuǎn)換為Class的實(shí)例。

protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                     ProtectionDomain protectionDomain)
    throws ClassFormatError
{
    protectionDomain = preDefineClass(name, protectionDomain);
    String source = defineClassSourceLocation(protectionDomain);
    Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
    postDefineClass(c, protectionDomain);
    return c;
}

自定義類加載器

/**
 * 繼承了ClassLoader,這是一個(gè)自定義的類加載器
 * @author 夜的那種黑丶
 */
public class ClassLoaderTest extends ClassLoader {
    public static void main(String[] args) throws Exception {
        ClassLoaderTest loader = new ClassLoaderTest("loader");
       Class<?> clazz = loader.loadClass("classloader.Test01");
        Object object = clazz.newInstance();
        System.out.println(object);
        System.out.println(object.getClass().getClassLoader());
    }
    //------------------------------以上為測(cè)試代碼---------------------------------

    /**
     * 類加載器名稱,標(biāo)識(shí)作用
     */
    private String classLoaderName;

    /**
     * 從磁盤讀物字節(jié)碼文件的擴(kuò)展名
     */
    private String fileExtension = ".class";

    /**
     * 創(chuàng)建一個(gè)類加載器對(duì)象,將系統(tǒng)類加載器當(dāng)做該類加載器的父加載器
     * @param classLoaderName 類加載器名稱
     */
    private ClassLoaderTest(String classLoaderName) {
        // 將系統(tǒng)類加載器當(dāng)做該類加載器的父加載器
        super();
        this.classLoaderName = classLoaderName;
    }

    /**
     * 創(chuàng)建一個(gè)類加載器對(duì)象,顯示指定該類加載器的父加載器
     * 前提是需要有一個(gè)類加載器作為父加載器
     * @param parent 父加載器
     * @param classLoaderName 類加載器名稱
     */
    private ClassLoaderTest(ClassLoader parent, String classLoaderName) {
        // 顯示指定該類加載器的父加載器
        super(parent);
        this.classLoaderName = classLoaderName;
    }

    /**
     * 尋找擁有指定二進(jìn)制名稱的類,重寫ClassLoader類的同名方法,需要自定義加載器遵循雙親委托機(jī)制
     * 該方法會(huì)在檢查完父類加載器之后被loadClass方法調(diào)用
     * 默認(rèn)返回ClassNotFoundException異常
     * @param className 類名
     * @return Class的實(shí)例
     * @throws ClassNotFoundException 如果類不能被找到,拋出此異常
     */
    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        byte[] data = this.loadClassData(className);
        /*
         * 通過defineClass方法將字節(jié)數(shù)組轉(zhuǎn)換為Class
         * defineClass:將一個(gè)字節(jié)數(shù)組轉(zhuǎn)換為Class的實(shí)例,在使用這個(gè)Class之前必須要被解析
         */
        return this.defineClass(className, data, 0 , data.length);
    }

    /**
     * io操作,根據(jù)類名找到對(duì)應(yīng)文件,返回class文件的二進(jìn)制信息
     * @param className 類名
     * @return class文件的二進(jìn)制信息
     * @throws ClassNotFoundException 如果類不能被找到,拋出此異常
     */
    private byte[] loadClassData(String className) throws ClassNotFoundException {
        InputStream inputStream = null;
        byte[] data;
        ByteArrayOutputStream byteArrayOutputStream = null;

        try {
            this.classLoaderName = this.classLoaderName.replace(".", "/");
            inputStream = new FileInputStream(new File(className + this.fileExtension));
            byteArrayOutputStream = new ByteArrayOutputStream();

            int ch;
            while (-1 != (ch = inputStream.read())) {
                byteArrayOutputStream.write(ch);
            }

            data = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            throw new ClassNotFoundException();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }
}

以上是一段自定義類加載器的代碼,我們執(zhí)行這段代碼

classloader.Test01@7f31245a
sun.misc.Launcher$AppClassLoader@18b4aac2

可以看見,這段代碼中進(jìn)行類加載的類加載器還是系統(tǒng)類加載器(AppClassLoader)。這是因?yàn)閖vm的雙親委托機(jī)制造成的,private ClassLoaderTest(String classLoaderName)將系統(tǒng)類加載器當(dāng)做我們自定義類加載器的父加載器,jvm的雙親委托機(jī)制使自定義類加載器委托系統(tǒng)類加載器完成加載。

改造以下代碼,添加一個(gè)path屬性用來指定類加載位置:

public class ClassLoaderTest extends ClassLoader {
    public static void main(String[] args) throws Exception {
        ClassLoaderTest loader = new ClassLoaderTest("loader");
        loader.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/");
        Class<?> clazz = loader.loadClass("classloader.Test01");
        System.out.println("class:" + clazz);

        Object object = clazz.newInstance();
        System.out.println(object);
        System.out.println(object.getClass().getClassLoader());
    }
    //------------------------------以上為測(cè)試代碼---------------------------------

    /**
     * 從指定路徑加載
     */
    private String path;

    ......
    
    /**
     * io操作,根據(jù)類名找到對(duì)應(yīng)文件,返回class文件的二進(jìn)制信息
     * @param className 類名
     * @return class文件的二進(jìn)制信息
     * @throws ClassNotFoundException 如果類不能被找到,拋出此異常
     */
    private byte[] loadClassData(String className) throws ClassNotFoundException {
        InputStream inputStream = null;
        byte[] data;
        ByteArrayOutputStream byteArrayOutputStream = null;

        className = className.replace(".", "/");

        try {
            this.classLoaderName = this.classLoaderName.replace(".", "/");
            inputStream = new FileInputStream(new File(this.path + className + this.fileExtension));
            byteArrayOutputStream = new ByteArrayOutputStream();

            int ch;
            while (-1 != (ch = inputStream.read())) {
                byteArrayOutputStream.write(ch);
            }

            data = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            throw new ClassNotFoundException();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

運(yùn)行一下

class:class classloader.Test01
classloader.Test01@7f31245a
sun.misc.Launcher$AppClassLoader@18b4aac2

修改一下測(cè)試代碼,并刪除工程下的Test01.class文件

public static void main(String[] args) throws Exception {
    ClassLoaderTest loader = new ClassLoaderTest("loader");
   loader.setPath("/home/fanxuan/桌面/");
    Class<?> clazz = loader.loadClass("classloader.Test01");
    System.out.println("class:" + clazz);

    Object object = clazz.newInstance();
    System.out.println(object);
    System.out.println(object.getClass().getClassLoader());
}

運(yùn)行一下

class:class classloader.Test01
classloader.Test01@135fbaa4
classloader.ClassLoaderTest@7f31245a

分析

改造后的兩塊代碼,第一塊代碼中加載類的是系統(tǒng)類加載器AppClassLoader,第二塊代碼中加載類的是自定義類加載器ClassLoaderTest。是因?yàn)镃lassLoaderTest會(huì)委托他的父加載器AppClassLoader加載class,第一塊代碼的path直接是工程下,AppClassLoader可以加載到,而第二塊代碼的path在桌面目錄下,所以AppClassLoader無法加載到,然后ClassLoaderTest自身嘗試加載并成功加載到。如果第二塊代碼工程目錄下的Test01.class文件沒有被刪除,那么依然是AppClassLoader加載。

再來測(cè)試一塊代碼

public static void main(String[] args) throws Exception {
    ClassLoaderTest loader = new ClassLoaderTest("loader");
    loader.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/");
    Class<?> clazz = loader.loadClass("classloader.Test01");
    System.out.println("class:" + clazz.hashCode());

    Object object = clazz.newInstance();
    System.out.println(object.getClass().getClassLoader());

    ClassLoaderTest loader2 = new ClassLoaderTest("loader");
    loader2.setPath("/home/fanxuan/Study/java/jvmStudy/out/production/jvmStudy/");
    Class<?> clazz2 = loader2.loadClass("classloader.Test01");
    System.out.println("class:" + clazz2.hashCode());

    Object object2 = clazz2.newInstance();
    System.out.println(object2.getClass().getClassLoader());
}

結(jié)果顯而易見,類由系統(tǒng)類加載器加載,并且clazz和clazz2是相同的。

class:2133927002
sun.misc.Launcher$AppClassLoader@18b4aac2
class:2133927002
sun.misc.Launcher$AppClassLoader@18b4aac2

再改造一下

public static void main(String[] args) throws Exception {
    ClassLoaderTest loader = new ClassLoaderTest("loader");
    loader.setPath("/home/fanxuan/桌面/");
    Class<?> clazz = loader.loadClass("classloader.Test01");
    System.out.println("class:" + clazz.hashCode());

    Object object = clazz.newInstance();
    System.out.println(object.getClass().getClassLoader());

    ClassLoaderTest loader2 = new ClassLoaderTest("loader2");
    loader2.setPath("/home/fanxuan/桌面/");
    Class<?> clazz2 = loader2.loadClass("classloader.Test01");
    System.out.println("class:" + clazz2.hashCode());

    Object object2 = clazz2.newInstance();
    System.out.println(object2.getClass().getClassLoader());
}

運(yùn)行結(jié)果

class:325040804
classloader.ClassLoaderTest@7f31245a
class:621009875
classloader.ClassLoaderTest@45ee12a7

ClassLoaderTest是顯而易見,但是clazz和clazz2是不同的,這是因?yàn)轭惣虞d器的命名空間的原因。

我們可以通過設(shè)置父類加載器來讓loader和loader2處于同一命名空間

public static void main(String[] args) throws Exception {
    ClassLoaderTest loader = new ClassLoaderTest("loader");
    loader.setPath("/home/fanxuan/桌面/");
    Class<?> clazz = loader.loadClass("classloader.Test01");
    System.out.println("class:" + clazz.hashCode());

    Object object = clazz.newInstance();
    System.out.println(object.getClass().getClassLoader());

    ClassLoaderTest loader2 = new ClassLoaderTest(loader, "loader2");
    loader2.setPath("/home/fanxuan/桌面/");
    Class<?> clazz2 = loader2.loadClass("classloader.Test01");
    System.out.println("class:" + clazz2.hashCode());

    Object object2 = clazz2.newInstance();
    System.out.println(object2.getClass().getClassLoader());
}

運(yùn)行結(jié)果

class:325040804
classloader.ClassLoaderTest@7f31245a
class:325040804
classloader.ClassLoaderTest@7f31245a

擴(kuò)展:命名空間

1. 每個(gè)類加載器都有自己的命名空間,命名空間由該加載器及所有的父加載器所加載的類組成

2. 在同一命名空間中,不會(huì)出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類

3. 在不同的命名空間中,有可能會(huì)出現(xiàn)類的完整名字(包括類的包名)相同的兩個(gè)類

php中文網(wǎng),大量的免費(fèi)Java入門教程,歡迎在線學(xué)習(xí)!??

The above is the detailed content of Detailed explanation of java class loader ClassLoader. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1502
276
How to solve class loader conflicts in Java development How to solve class loader conflicts in Java development Jun 29, 2023 am 08:32 AM

How to solve class loader conflicts in Java development Introduction: In Java development, class loader conflicts are a common problem. When different class loaders are used to load the same class or resource file, conflicts will occur, causing the program to fail to run properly. This article explains what a class loader conflict is and how to resolve it. 1. What is a class loader conflict? The class loading mechanism in Java adopts the parent delegation model. Each class loader has a parent class loader, and the final parent class loader is the startup class loader. when needed

Java Error: ClassLoader Error, How to Fix and Avoid Java Error: ClassLoader Error, How to Fix and Avoid Jun 25, 2023 am 09:02 AM

During development using Java, we often encounter ClassLoader errors, which are caused by the class loader not finding or loading the correct class. This kind of error will cause the program to fail to execute normally and bring inconvenience to development. Therefore, we need to understand the causes of ClassLoader errors and their solutions in order to better optimize our Java programs. 1. Causes of ClassLoader errors: Classes are loaded through ClassLoader in Java, ClassLoad

How SpringBoot encrypts and protects class files through custom classloader How SpringBoot encrypts and protects class files through custom classloader May 11, 2023 pm 09:07 PM

Background Recently, key business codes have been encrypted for the company framework to prevent the engineering code from being easily restored through decompilation tools such as jd-gui. The configuration and use of the related obfuscation scheme are relatively complex and there are many problems for the springboot project, so the class files are encrypted and then passed The custom classloder is decrypted and loaded. This solution is not absolutely safe. It only increases the difficulty of decompilation. It prevents gentlemen but not villains. The overall encryption protection flow chart is shown in the figure below. Maven plug-in encryption uses custom maven plug-in to compile. The class file specified is encrypted, and the encrypted class file is copied to the specified path. Here, it is saved to resource/corecla.

How to use the ClassLoader function for class loading in Java How to use the ClassLoader function for class loading in Java Jun 26, 2023 pm 04:16 PM

The principles and methods of class loading using the ClassLoader function in Java have always been one of the focuses of Java developers. The ClassLoader function is part of the Java class library. Its main function is to load Java class files into the Java Virtual Machine (JVM) so that the program can run normally. The ClassLoader function is the core of Java class loading. In the Java runtime environment, it is responsible for finding and loading the bytecode of Java classes, so understand and master it.

Detailed explanation of PHP auto-loading knowledge points: Unlock a powerful tool to improve your skill threshold Detailed explanation of PHP auto-loading knowledge points: Unlock a powerful tool to improve your skill threshold Feb 19, 2024 pm 03:15 PM

Overview of PHP automatic loading PHP automatic loading means that when using a class, PHP will automatically load the definition file of the class. This is usually achieved through a class loader. A class loader is a program responsible for loading class definition files. It can be built-in or customized. Class loader types There are two types of class loaders built into PHP: Zend class loader: This is PHP's default class loader, which loads class definition files located in PHP's built-in libraries. PSR-4 class loader: PSR-4 is an autoloading standard that defines a set of rules for loading class definition files. The PSR-4 class loader loads class definition files according to the PSR-4 standard. Additionally, class loaders can be customized. Custom class loaders can be customized according to their own

The role of class loader in Java virtual machine The role of class loader in Java virtual machine Apr 13, 2024 pm 02:51 PM

The role of the class loader: Loading: Read class files from the specified source. Verification: Confirm that the class file conforms to the specification. Preparation: allocate memory and initialize static variables. Parse: Parse symbol references. Initialization: Call methods, execute static initialization blocks, and allocate class objects.

The Art of PHP Autoloading: Exploring Loading Techniques The Art of PHP Autoloading: Exploring Loading Techniques Mar 02, 2024 pm 09:19 PM

Autoloading is a technique that automatically loads PHP classes without the need to manually include each file. It simplifies application development and maintenance, improving performance and maintainability. This article will explore the commonly used automatic loading technology in PHP. SPLAutoloaderSPL (Standard PHP Library) contains a built-in autoloading mechanism called the spl_autoload_reGISter() function. This function allows you to register a loader function that will be called when an attempt is made to load a class that does not exist. The following example demonstrates how to use SPLAutoloader: spl_autoload_register(function($class){

How to use the ClassLoader function for dynamic class loading in Java How to use the ClassLoader function for dynamic class loading in Java Jun 26, 2023 pm 02:10 PM

The ClassLoader function in Java can dynamically load classes at runtime, which is very useful in applications that require flexible deployment and modification of code. Through the function of ClassLoader, the plug-in mechanism can be implemented to improve the scalability and flexibility of the system. This article will introduce how to use the ClassLoader function for dynamic class loading. 1. The role of ClassLoader When starting the Java Virtual Machine (JVM), three ClassLoaders will be created:

See all articles