Fully parse Java class loaders and fully parse java Loads
In-depth understanding and exploration of Java class loading mechanism ----1. java. lang. ClassLoader class Introduction
Java. lang. the basic function of the ClassLoader class is to find or generate the corresponding byte code based on the name of a specified class, and then define a Java class from these byte code, that is, java. lang. an instance of the Class.
ClassLoader provides a series of methods, such:
2. Tree hierarchy of the Class Loader in JVM
The class loaders in Java can be roughly divided into two types: one is provided by the system, and the other is compiled by Java application developers.
Bootstrap class loader ):
It is used to load the Java core library (jre/lib/rt. jar). It is implemented using native C ++ code and does not inherit from java. lang. ClassLoader.
Load the extension class and application class loaders and specify their parent class loaders, which cannot be obtained in java.
Extensions class loader ):
It is used to load Java extension libraries (jre/ext/*. jar ). The Java virtual machine provides an extension library directory. This class loader searches for and loads Java classes in this directory.
Application class loader ):
It loads the Java class according to the CLASSPATH of the Java application. Generally, Java application classes are loaded by them. You can obtain it through ClassLoader. getSystemClassLoader.
Custom class loader ):
In addition to the class loaders provided by the system, developers can inherit the java. lang. ClassLoader class to implement their own class loaders to meet some special requirements.
The following test code proves this level:
public class testClassLoader { @Test public void test(){ //application class loader System.out.println(ClassLoader.getSystemClassLoader()); //extensions class loader System.out.println(ClassLoader.getSystemClassLoader().getParent()); //bootstrap class loader System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent()); }}
Output:
We can see that the ClassLoader class is loaded by AppClassLoader. His father is ExtClassLoader, and his father cannot obtain ExtClassLoader because it is implemented in C ++.
3. Parental Appointment Mechanism
When receiving a request for loading a class, a specific class loader first delegates the loading task to the parent class loader.Delegate a load task to an upstream NodeUntil the parent class loader, if the parent class loader can complete the class loading task, it will return success. If not, it will pass down the delegate task and its subclass loader will load it.
Advantages of the parent-child delegation mechanism:
Ensure the security of the java core library (for example, if you write a java. lang. String class, the native String class cannot be loaded because of the parent-child delegation mechanism)
Proxy Mode
In contrast to the parent-child delegation mechanism, the proxy mode tries to load the data first. If the data cannot be loaded, it is passed up. Tomcat is the proxy mode.
4. Custom Class Loader
public class MyClassLoader extends ClassLoader{ private String rootPath; public MyClassLoader(String rootPath){ this.rootPath = rootPath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { //check if the class have been loaded Class<?> c = findLoadedClass(name); if(c!=null){ return c; } //load the class byte[] classData = getClassData(name); if(classData==null){ throw new ClassNotFoundException(); } else{ c = defineClass(name,classData, 0, classData.length); return c; } } private byte[] getClassData(String className){ String path = rootPath+"/"+className.replace('.', '/')+".class"; InputStream is = null; ByteArrayOutputStream bos = null; try { is = new FileInputStream(path); bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int temp = 0; while((temp = is.read(buffer))!=-1){ bos.write(buffer,0,temp); } return bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); }finally{ try { is.close(); bos.close(); } catch (Exception e) { e.printStackTrace(); } } return null; } }
Test the custom class loader.
Create a test class HelloWorld
package testOthers;public class HelloWorld {}
Create a testOthers folder in the root directory of drive D, compile HelloWorld. java, and put the obtained class file under the testOthers folder.
Use the following code for testing:
public class testMyClassLoader { @Test public void test() throws Exception{ MyClassLoader loader = new MyClassLoader("D:"); Class<?> c = loader.loadClass("testOthers.HelloWorld"); System.out.println(c.getClassLoader()); }}
Output:
The HelloWorld class is loaded by MyClassLoader, our custom class loader.
5. Detailed description of the class loading process
JVM divides the class loading process into three steps: Load, Link, and initialization)
1) load:
Searches for and loads binary data of the class;
2) link:
Verification: ensure that the loaded class information complies with JVM specifications and there are no security issues.
Preparation: allocate memory for static variables of the class and initialize it as the default value.
Resolution: converts a symbolic reference in the constant pool of a VM to a direct reference.
3) initialization:
Assign the correct initial value to the static variables of the class.
Ps: in Java, the virtual Opportunity maintains a constant pool for each loaded class. [different from the String constant pool, this constant pool is only an ordered set of the Class Name (such as the class name and method name) and symbol reference. The String constant pool is shared by the entire JVM.] These symbols (such as a in int a = 5;) are symbolic references, the parsing process is to convert it to the relative address pointing to the object address in the heap.
Class initialization steps:
1) if this class has not been loaded and linked, load and link it first.
2) If this class has a direct parent class and the class has not been initialized (Note: In a class loader, the class can only be initialized once ), initialize the direct parent class (not applicable to interfaces)
3) if the class contains blocks with static identifiers, execute these initialization statements in sequence.