Class loader tree structure, parent delegate (proxy) mechanism 03, Custom class loader (file, network, encryption) 04, Thread context class loader 05, server class loading principle

Class loaders

The class file bytecode content is loaded into memory, and the static data is converted into runtime data structures in the method area. A java.lang. class object representing this class is generated in the heap as an access point to the method area class data.

Class caching The standard Java SE Class loader can find classes on demand, but once a Class is loaded into the Class loader, it remains loaded (cached) for a while, although the JVM garbage collector can reclaim these Class objects.

2. Class loader hierarchy (tree structure)

Bootstarap class loader (C) – it is used to load Java core libraries (JAVA_HOME/jre/lib/rt.jar or sun.boot.class.path), is implemented in native code, Does not inherit from java.lang.classLoader. – Loads extension classes and application class loaders and specifies their parent class loaders.

Extensions Class Loader (Java) – Used to load Java extension libraries (JAVA_HOME/jre/ext/*.jar, or the contents of the java.ext.dirs directory). The implementation of the Java Virtual machine provides an extension library directory in which the class loader finds and loads Java classes. – Implemented by sun.misc.Launcher$ExtClassLoader

Application Class Loader (Java) – it loads the classes of Java applications according to the classpath (java.class.path) By the sun. The misc. The Launcher $AppClassLoader implementation

Custom classloaders (written in Java) – Developers can implement their own classloaders by inheriting methods from the java.lang.ClassLoader class to meet special needs

Java.class.ClassLoader class java.classloader The basic responsibility of the java.lang. ClassLoader Class is to find or generate the bytecode corresponding to a specified Class name, and then define a Java Class from this bytecode, which is an instance of the java.lang.Class Class. – In addition, ClassLoader is responsible for loading Java application resources, such as image files and configuration files.

Related method -getparent () returns the parent class loader of the class loader -loadClass (String name) loads the class named name, The result is an instance of the java.lang.Class Class – findClass(String name) The result is an instance of the java.lang.Class Class – findLoadedClass(String name) DefineClass (String name, byte[] b,int off,int Len) converts the contents of byte array B into a Java Class, The result returned is an instance of the java.lang.Class Class, which is declared final. – resolveClass(Class

package com.lyy.test; public class Demo2 { public static void main(String[] args) { System.out.println(ClassLoader.getSystemClassLoader()); System.out.println(ClassLoader.getSystemClassLoader().getParent()); System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent()); //JAVA_HOME/jre/lib/rt.jar System.out.println(System.getProperty("java.class.path")); System.out.println("====================================="); String a = "gaogao"; System.out.println(a.getClass().getClassLoader()); System.out.println(a); }}Copy the code

Class loader of the proxy pattern  proxy mode – to other loader to load the specified class  parents trust mechanism – that is a particular class loader in received the request to load the class, first will load the task entrusted to the parent class loader, a back, know the highest granddad, if the parent class loader can complete class loading, Returns successfully; Only if the parent class loader is unable to complete the load task, do the load itself. – The parent delegate mechanism is designed to keep the Java core libraries type safe. This mechanism ensures that no user can define the java.lang.Object class himself. Class loaders, in addition to user-loaded classes, are also the most basic barrier to security. Co-parent delegation acts as a proxy mode — not all classloaders adopt co-parent delegation. – The Tomcat server class loader also uses proxy mode, except that it first tries to load a class, and then proxies it to the parent class loader if it can’t find it, which is the reverse order of normal class loaders.

The process of customizing a class loader – first check whether the type of the request has been loaded into the namespace by the class loader, and return it if it has; – If the parent Class loader can delegate the Class loading request, the Class instance loaded by the parent Class loader is returned. — Call findClass (…) of this classloader Method, the view retrieves the corresponding bytecode and, if it does, calls defineClass(…) Import type to method area; If the bytecode cannot be obtained or other reasons fail, an exception loadClass(…) is returned. LoadClass (…). Abort the loading process by reversing the exception. — Note that the JVM does not consider the same class loaded by two classloaders

package com.lyy.temp; public class HelloWrold { public static void main(String[] args) { System.out.println("aaa"); }}Copy the code
package com.lyy.test; /** * public class Demo3 {public static void main(String[] args) throws ClassNotFoundException { FileSystemClassLoader load = new FileSystemClassLoader("E:/VIP"); FileSystemClassLoader load2 = new FileSystemClassLoader("E:/VIP"); Class<? > c = load.loadClass("com.lyy.temp.HelloWrold"); Class<? > c2 = load.loadClass("com.lyy.temp.HelloWrold"); Class<? > c3 = load2.loadClass("com.lyy.temp.HelloWrold"); Class<? > c4 = load2.loadClass("java.lang.String"); Class<? > c5 = load2.loadClass("com.lyy.test.Demo1"); System.out.println(c.hashCode()); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashcode ())); System.out.println(c3.getClassLoader()); // Custom class loader system.out.println (c4.getClassloader ()); // Bootstrap classloader system.out.println (c5.getClassloader ()); // System default class loader}}Copy the code

File class loader

package com.lyy.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; Public class FileSystemClassLoader extends ClassLoader{// com.lyy.test.user --> d:/myjava/com/lyy/test/User.class private String rootDir; public FileSystemClassLoader(String rootDir){ this.rootDir=rootDir; } @Override protected Class<? > findClass(String name) throws ClassNotFoundException { Class<? > c = findLoadedClass(name); // If the class has been loaded, return the already loaded class, otherwise load a new class if(null! = c){ return c; }else{ ClassLoader parent = this.getParent(); c = parent.loadClass(name); // Delegate to the parent class load if(null! = c){ return c; }else{ byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); }else{ c = defineClass(name, classData,0, classData.length); } } } return c; } private byte[] getClassData(String name) { //com.lyy.test.User d:/myjava/com/lyy/test/User.class String path = rootDir+"/"+name.replace('.', '/')+"class"; //IOUtils, which can be used to convert data in a stream to bytes InputStream is = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { is = new FileInputStream(path); byte[] buffer = new byte[1024]; int temp = 0; while((temp=is.read(buffer)) ! = -1){ baos.write(buffer,0,temp); } return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { if(is ! = null){ is.close(); } if(baos ! = null){ baos.close(); } } catch (IOException e) { e.printStackTrace(); }}}}Copy the code

Network class loader

package com.lyy.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; /** * public NetClassLoader extends ClassLoader{//com.lyy.test.User --> www.baidu.com private String rootUrl; public NetClassLoader(String rootUrl){ this.rootUrl=rootUrl; } @Override protected Class<? > findClass(String name) throws ClassNotFoundException { Class<? > c = findLoadedClass(name); // If the class has been loaded, return the already loaded class, otherwise load a new class if(null! = c){ return c; }else{ ClassLoader parent = this.getParent(); c = parent.loadClass(name); // Delegate to the parent class load if(null! = c){ return c; }else{ byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); }else{ c = defineClass(name, classData,0, classData.length); } } } return c; } private byte[] getClassData(String name) { //com.lyy.test.User d:/myjava/com/lyy/test/User.class String path = rootUrl+"/"+name.replace('.', '/')+"class"; //IOUtils, which can be used to convert data in a stream to bytes InputStream is = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { URL url = new URL(path); is = url.openStream(); byte[] buffer = new byte[1024]; int temp = 0; while((temp=is.read(buffer)) ! = -1){ baos.write(buffer,0,temp); } return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { if(is ! = null){ is.close(); } if(baos ! = null){ baos.close(); } } catch (IOException e) { e.printStackTrace(); }}}}Copy the code

Encryption and decryption loader (reverse operation, DES symmetric encryption and decryption)

package com.lyy.test; * @author 01 ** / public class Demo4 {public static void main(String[] args) throws Exception { // int a = 3; //0000011 // System.out.println(Integer.toBinaryString(a^0xff)); ClasformatError // FileSystemClassLoader load = new FileSystemClassLoader("E:/VIP/temp"); // Class<? > c = load.loadClass("HelloWrold"); // System.out.println(c); DecrptClassLoader loader = new DecrptClassLoader("E:/VIP/temp"); Class<? > c = loader.loadClass("com.lyy.temp.HelloWrold"); System.out.println(c); }}Copy the code
package com.lyy.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; Public class FileSystemClassLoader extends ClassLoader{// com.lyy.test.user --> d:/myjava/com/lyy/test/User.class private String rootDir; public FileSystemClassLoader(String rootDir){ this.rootDir=rootDir; } @Override protected Class<? > findClass(String name) throws ClassNotFoundException { Class<? > c = findLoadedClass(name); // If the class has been loaded, return the already loaded class, otherwise load a new class if(null! = c){ return c; }else{ ClassLoader parent = this.getParent(); c = parent.loadClass(name); // Delegate to the parent class load if(null! = c){ return c; }else{ byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); }else{ c = defineClass(name, classData,0, classData.length); } } } return c; } private byte[] getClassData(String name) { //com.lyy.test.User d:/myjava/com/lyy/test/User.class String path = rootDir+"/"+name.replace('.', '/')+"class"; //IOUtils, which can be used to convert data in a stream to bytes InputStream is = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { is = new FileInputStream(path); byte[] buffer = new byte[1024]; int temp = 0; while((temp=is.read(buffer)) ! = -1){ baos.write(buffer,0,temp); } return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { if(is ! = null){ is.close(); } if(baos ! = null){ baos.close(); } } catch (IOException e) { e.printStackTrace(); }}}}Copy the code
package com.lyy.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** * public class extends ClassLoader extends ClassLoader{// com.lyy.test.user --> d:/myjava/com/lyy/test/User.class private String rootDir; public DecrptClassLoader(String rootDir){ this.rootDir=rootDir; } @Override protected Class<? > findClass(String name) throws ClassNotFoundException { Class<? > c = findLoadedClass(name); // If the class has been loaded, return the already loaded class, otherwise load a new class if(null! = c){ return c; }else{ ClassLoader parent = this.getParent(); c = parent.loadClass(name); // Delegate to the parent class load if(null! = c){ return c; }else{ byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); }else{ c = defineClass(name, classData,0, classData.length); } } } return c; } private byte[] getClassData(String name) { //com.lyy.test.User d:/myjava/com/lyy/test/User.class String path = rootDir+"/"+name.replace('.', '/')+"class"; //IOUtils, which can be used to convert data in a stream to bytes InputStream is = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { is = new FileInputStream(path); int temp = -1; while((temp=is.read()) ! = -1){ baos.write(temp^0xff); } return baos.tobytearray (); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { if(is ! = null){ is.close(); } if(baos ! = null){ baos.close(); } } catch (IOException e) { e.printStackTrace(); }}}}Copy the code

In general, it is guaranteed that all other classes associated with the same class are loaded by the class loader of the current class. For example, if the Class itself is found in Ext, then some of the new classes in it will have to be found in Ext (not a lower level), so some of the app can find, but not find. Mysql/SQL Server JDBC API is loaded by Boot or Ext, but Service Prover is loaded by Ext or App, so it may not be able to find driver. In the Java world, this problem is encountered in virtually anything that is classified as apI-SPI (Service Provide Interface, vendor specific). Common SPIs are JDBC, JCE, JNXP, and JBI.

package com.lyy.test; Public class Demo5 {public static void main(String[] args) throws Exception {public static void main(String[] args) throws Exception { ClassLoader loader = Demo5.class.getClassLoader(); System.out.println(loader); ClassLoader laoder2 = Thread.currentThread().getContextClassLoader(); System.out.println(laoder2); Thread.currentThread().setContextClassLoader(new FileSystemClassLoader("E:/VIP/")); System.out.println(Thread.currentThread().getContextClassLoader()); Class<Demo1> c = (Class<Demo1>)Thread.currentThread().getContextClassLoader().loadClass("com.lyy.test.Demo1"); System.out.println(c); System.out.println(c.getClassLoader()); }}Copy the code

Class loading mechanism of TOMCAT server