preface

  • As mentioned earlier, a class is only loaded once.
  • However, this is in the case of class loaders in the same namespace, where a class is only loaded once.

The namespace

  • Each classloader has its own namespace, which consists of the loader that loaded the class and all the classes loaded by its parent loader.
  • There can be no two classes in the same namespace whose full name (including the package name of the class) is the same.
  • In different namespaces, it is possible to have two classes whose full name (including the package name of the class) is the same.

The sample

The example follows the last blog post

  • This is where the second constructor for the custom classloader comes in handy,
    public UserClassLoader(ClassLoader parent, String classLoaderName) {
     super(parent);// Explicitly define the parent of the class loader
     this.classLoaderName = classLoaderName;
    }
    Copy the code
  • Again, delete the.class file from the default path, and use custom class load to load the class from the specified path.
    public static void main(String[] args) throws Exception {
      UserClassLoader userClassLoader = new UserClassLoader("userClassLoader");
      userClassLoader.setPath("C:/Users/25852/Desktop/"); Class<? > clazz = userClassLoader.loadClass("com.jvmstudy.classloading.ClassLoaderTest");// Cannot be the current class
      Object object = clazz.newInstance();
      System.out.println("class HashCode: "+clazz.hashCode());
      System.out.println(object.getClass().getClassLoader());
      System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
      
      // Use userClassLoader as the parent
      UserClassLoader userClassLoader1 = new UserClassLoader(userClassLoader,"userClassLoader1");
      userClassLoader1.setPath("C:/Users/25852/Desktop/"); Class<? > clazz1 = userClassLoader1.loadClass("com.jvmstudy.classloading.ClassLoaderTest");// Cannot be the current class
      Object object1 = clazz1.newInstance();
      System.out.println("class HashCode: "+clazz1.hashCode());
      System.out.println(object1.getClass().getClassLoader());
      System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
      
      UserClassLoader userClassLoader2 = new UserClassLoader("userClassLoader2");
      userClassLoader2.setPath("C:/Users/25852/Desktop/"); Class<? > clazz2 = userClassLoader2.loadClass("com.jvmstudy.classloading.ClassLoaderTest");// Cannot be the current class
      Object object2 = clazz2.newInstance();
      System.out.println("class HashCode: "+clazz2.hashCode());
      System.out.println(object2.getClass().getClassLoader());
    }
    Copy the code
  • The results of
  • instructions
    • First, the parent of a custom class load must have an AppClassLoader, although the constructor can specify a parent. For example, the parent of the custom classloader would be the AppClassLoader.
    • Because the default path class is loaded by the AppClassLoader, because the corresponding class file has been deleted, obviously it cannot be loaded, according to the parent delegate mechanism, delegate down, can not load, by the custom class loader itself.
    • In the above code, the parent class of userClassLoader1 is loaded by userClassLoader. According to the parent delegation mechanism, the class is loaded by userClassLoader. Look at the namespace definition. UserClassLoader is used, so the same class is only loaded once.
    • If userClassLoader2 fails to load the AppClassLoader, userClassLoader2 will load the AppClassLoader itself. In this case, userClassLoader2 shall prevail. So it loads a different class than the first two, which means the same class is reloaded once.

Class of unloading

define

  • The life cycle of a class begins when it is loaded, connected, and initialized.
  • When the Class object representing a Class is no longer referenced, that is, untouchable (no reference to it), the life cycle of the Class object will end, and the data of a Class in the method area will be unloaded, thus ending the life cycle of the MySample Class.
  • When a Class ends its life cycle depends on when the Class object representing it ends its life cycle.
  • Classes loaded by the class loader of the Java VIRTUAL Machine are not unloaded during the life cycle of the VM. As mentioned earlier, the class loaders that come with the Java Virtual Machine include root class loaders, extension class loaders, and system class loaders. The Java virtual Machine itself will always refer to these Class loaders, and these Class loaders will always refer to the Class objects of the classes they load, so these Class objects will always be accessible.
  • Classes loaded by user-defined class loaders can be unloaded.
  • When the program is run, a class is loaded by the Loader. In the internal implementation of the class loader, a Java collection is used to hold references to the loaded classes. On the other hand, a Class object always references its classloader, which is obtained by calling the Class object’s getClassLoader() method. In this way, the Class instance representing a Class is bidirectional associated with the Loader.
  • An instance of a Class always refers to a Class object that represents that Class. The getClass() method is defined in the Object Class. This method returns a reference to the Class Object that represents the Class to which the Object belongs. In addition, all Java classes have a static property, class, that references the class object that represents that class.

Use code to demonstrate class unloading

  • Use JVM parameters-XX:+TraceClassUnloadingTo print the unload message for the class

  • If the.class file to be loaded is deleted from the default path, the code is as follows

    public static void main(String[] args) throws Exception {
         UserClassLoader userClassLoader = new UserClassLoader("userClassLoader");
         userClassLoader.setPath("C:/Users/25852/Desktop/"); Class<? > clazz = userClassLoader.loadClass("com.jvmstudy.classloading.ClassLoaderTest");// Cannot be the current class
         Object object = clazz.newInstance();
         System.out.println("class HashCode: "+clazz.hashCode());
         System.out.println(object.getClass().getClassLoader());
         System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
         // Let classes and custom class loaders no longer reference each other
         userClassLoader = null;
         clazz = null;
         object = null;
         System.gc();// The actual scenario does not use this
    
         userClassLoader = new UserClassLoader("userClassLoader");
         userClassLoader.setPath("C:/Users/25852/Desktop/");
         clazz = userClassLoader.loadClass("com.jvmstudy.classloading.ClassLoaderTest");// Cannot be the current class
         object = clazz.newInstance();
         System.out.println("class HashCode: "+clazz.hashCode());
         System.out.println(object.getClass().getClassLoader());
     }
    Copy the code
  • The results of