Java object-oriented -- class loaders and reflection, java object-oriented -- Loading
The relationship between jvm and class in the Class Loader
When you call a java command to run a java program, a java virtual machine process is started. All threads and variables of the same jvm are in the same process, and the memory zone of the jvm process is used.
JvmProcess Termination:
1. The program runs until it ends normally.
2. System. exit () or Runtime. getRuntime. exit () is encountered ().
3. encountered an uncaptured exception or error
4. The JVM process is forcibly terminated on the platform where the program is located.
When the jvm process is terminated, all data in the jvm memory will be lost.
Class Loading
When a Program actively uses a class, if the class has not been loaded into the memory, the system will load the class.Class LoadingIt refers to reading the class file of the Class into the memory and creating an instance of java. lang. class for it. In java, everything is an object, and classes are also java. lang. Class objects.
Class loading involves three steps: Loading, connection, and initialization. The loading stage must complete the following steps:
1) Get the binary byte stream that defines this class using the full qualified name of a class.
2) convert the static storage structure represented by this byte stream into the runtime data structure of the method area.
3) generate a Class object that represents this Class in the java heap as the entry to access the data in the method area.
Class LoadingIs completed by the class loader, which is generally provided by the JVM. By using different class loaders, you can load binary data of classes from the following sources:
1. Load the class file from the local file system
2. Load the class file directly from the jar package
3. Load class files through the network
4. dynamically compile and load a java source file
Class connection
Merges binary data of the class into the JRE (java Runtime Environment ).
1. Verify: Check whether the loaded class has a correct internal structure and is consistent with other classes.
2. Preparation: allocates memory for the static attributes of the class and sets the default initial values.
3. Resolution: Replace the symbolic reference in the binary data of the class with a direct reference.
Class initialization
Initialize static attributes of a class. You can specify the initial value when declaring the static attribute and the initial value through the static initialization block. JVM will execute these statements in sequence in the program.
Class initialization time
The Java virtual machine specification does not have a mandatory constraint on when to start the class loading process. The specific implementation of the virtual machine is free of control. However, for class initialization, the virtual machine specification strictly specifies several situations, class initialization must be triggered before initialization.
1. When creating a class instance: Create an instance through the new operator, reflection, or deserialization
2. Use static methods of Classes
3. Static variables of the lifecycle class (except static variables modified by final), OR values for static attributes
4. Create a java. lang. Class Object of a Class or interface through reflection, such as Class. forName ("Hello "). Note that the ClassLoader. loadClass (name, false) method does not link the class, but only loads the class, so Initialization is not performed. However, the Class is forcibly initialized only when the forName () Static Method of the Class is used.
5. When initializing a subclass, all its parent classes will be initialized.
6. The main class of the main () method is initialized first.
For static properties of the final type, if the attribute value can be determined during compilation (converted to A. class file), this attribute can be considered as the compile-time volume. During compilation, replace it with a specific value. Therefore, even using this static property will not lead to class initialization, which is equivalent to using a constant !!
The above is called "Active reference" for a class ". In addition, class initialization is not triggered, which is called "passive reference", for example, in the following situations:
1. The subclass accesses the static variables of the parent class. The subclass may not be initialized and the parent class will be initialized.
2. The class is referenced through array definition, and class initialization is not triggered.
3. constants of the definition class. constants are stored in the constant pool of the call class during the compilation phase. In essence, they are not directly referenced to classes that define constants. Therefore, initialization of classes that define constants is not triggered.
class SuperClass {
static {
System.out.println ("superclass init");
}
public static int value = 111;
}
class SubClass extends SuperClass {
static {
System.out.println ("subclass init");
}
}
public class Test {
public static void main (String [] args) {
System.out.println (SubClass.value); // Passive reference, the subclass will not be initialized
SubClass [] scArr = new SubClass [5]; // Passive reference, no output
}
}
Class Loader
Each class loader (except the root class loader) is java. lang. classLoader instance, responsible. the class file is loaded into the memory and the corresponding java is generated for it. lang. class Object.
The same. class will not be loaded twice by the same class loader. How can I determine whether it is the same class:
In java, a class is identified by its fully qualified class name-package name + class name; In jvm, A class uses its fully qualified class name + its class loader ID --- package name + class name + Class Loader name
Loader hierarchy:
At JVM startup, an initial class loader hierarchy consisting of three class loaders is formed:
1. Bootstrap ClassLoader root class loader (Bootstrap Class Loader) to load the java core class (limited loading path: jdk1.8 _ 02/jre/lib/rt. jar ). It is not a subclass of java. lang. ClassLoader, but implemented by JVM itself. For the sake of security and functional integrity, the virtual machine does not load any jar that exists in the path of the startup Class Loader. Only the classes that come with JDK are loaded, therefore, developers should not store custom classes in this directory.
2. extension ClassLoader Extension class loader to load the JAR class package in the JRE Extension directory (limited loading path: % JAVA_HOME %/jre/lib/ext/or java. ext. directory specified by the dirs system attribute)
3. system ClassLoader System class loader, loading java. class. path System attribute or the jar package and class path specified by the CLASSPATH environment variable, you can use the static ClassLoader method ClassLoader. getSystemClassLoader () gets the system class loader. If not specified, the user-defined class loader uses the class loader as its parent loader. You can also use the getClassLoader () method of the Class instance to load the current Class.
4. Custom Class Loader
The class loader in the JVM system can only load the. class file in the corresponding path while the program is running, and cannot change the search path. If you want to load classes from other paths at runtime, you need to write a custom class loader.
Basic Program loading process
1. according to <JAVA_HOME>/jre/lib/i386/jvm. cfg decides whether to run JVM in client or server mode, and then load <JAVA_HOME>/jre/bin/client | server/jvm. dll to start JVM;
2. The Bootstrap ClassLoader will be loaded when the JVM is started (start the class loader and write it in C/C ++, which is part of the JVM itself );
3. Load Java core APIs through Bootstrap ClassLoader, including the sun. misc. Launcher class (ExtClassLoader and AppClassLoader are its internal classes );
4. sun. misc. during initialization, the Launcher class will create an instance of its own. During the creation process, an ExtClassLoader instance will be created (specifying that the parent class loader is null) an AppClassLoader instance (specifying the parent class loader as an ExtClassLoader instance), and setting the AppClassLoader instance as the main thread's ThreadContextClassLoader (thread context class loader ).
5. The AppClassLoader instance starts to load the classes required in the classpath path.
Class Loading Mechanism
1. Full responsibility: All classes dependent on and referenced by a class are loaded by the same loader unless another loader is displayed.
2. Parent-parent delegation: When a Class Loader receives a class loading request, it first delegates the request to the parent class loader and recursion to Bootstrap ClassLoader. Then, the loader tries to search for and load classes based on the request. If the class cannot be loaded, it will feed back information to the subclass loader (throwing ClassNotFoundException), and The subclass loader will load the class by itself.
The parent-child relationship between classes during the loading period is not the parent-child relationship in class inheritance, but is a combination to implement the Parent-Child delegation model.
The root class loader is implemented by c ++. It is not implemented by java and does not inherit ClassLoader. Therefore, the returned value of the extension class loader calling parent () is null. However, the extension class loader can still be delegated to the root class loader.
The reason for using the parent-class delegation mode: the class added by the parent-Class Loader does not prevent the quilt class from being reloaded, because the class is identified by the fully qualified name + Class Loader name in JVM. In addition, it can avoid loading malicious classes with the same name as sun's core APIs.
public Class <?> loadClass (String name) throws ClassNotFoundException {
return loadClass (name, false);
}
// In the ClassLoader, only the definition of findClass () is provided. The specific implementation needs to be provided by the subclass.
protected Class <?> findClass (String name) throws ClassNotFoundException {
throw new ClassNotFoundException (name);
}
protected synchronized Class <?> loadClass (String name, boolean resolve) throws ClassNotFoundException {
// First determine whether the class has been loaded, and if it is already loaded, return the instance directly
Class c = findLoadedClass (name);
if (c == null) {
// If not loaded, delegate to the parent class loader
try {
if (parent! = null) {
// If there is a parent class loader, delegate to the parent class loader to load
c = parent.loadClass (name, false);
} else {
// If there is no parent class loader, it is currently an extension class loader
// will call the native method that starts the class loader
c = findBootstrapClassOrNull (name);
}
} catch (ClassNotFoundException e) {
// If all parent class loaders cannot be loaded, only the load method of the current class loader is called
c = findClass (name);
}
}
if (resolve) {
resolveClass (c);
}
return c;
}
3. cache mechanism: ensure that all loaded classes are cached. When a program needs a Class, it first searches for the Class object from the cache area. If no Class is available, the Class is loaded.
Custom Class Loader
Except the root loader in JVM, all class loaders are instances of the ClassLoader subclass. developers can customize class loaders by extending the ClassLoader and rewriting the methods included in the ClassLoader.
As shown in the source code above, the loadClass () method is mainly implemented by the parent-parent delegate model. At last, the findClass () method is called to load classes. Therefore, the custom Class Loader overwrites findClass () specifically, it is convenient to write loadClass () to avoid overwriting the parent class delegate and buffer mechanisms of the default class loader.
Core methods of the ClassLoader class:
You can use the custom class loader to implement the following functions:
The digital signature is automatically verified before the code is executed;
Decrypts the code based on the password provided by the user, so that the Code obfuscators can be implemented to avoid decompilation of class files;
Dynamically load classes as needed;
Load other data to the application in the form of bytecode as needed;
URLClassLoader class
Java provides an implementation class URLClassLoader for ClassLoader, which is also the parent class of the system class loader and extended Class Loader. It can obtain binary files from the local file system and remote hosts to load classes.
Two constructors of URLClassLoader
URLClassLoader (URL [] urls): use the default parent class loader to create a ClassLoader object, which will be queried and loaded from the series path specified by urls.
URLClassLoader (URL [] urls, ClassLoader parent): create with the specified parent class loader...
Once the URLClassLoader object is obtained, you can call the loadClass () method of the class loader to load the specified class.
Loading images, videos, text, and other non-class resources
In addition to loading classes, ClassLoader can also be used to load images, videos, and other non-class resources. It also uses the parent-parent delegate model to pass requests for loading resources to the top-layer Bootstrap ClassLoader, search for resources in the corresponding directory. If the resource fails, it is returned and searched layer by layer.
Related instance methods:
URL getResource (String name): The resource name is'/'.URLObject enumeration.
InputStream getResourceAsStream (String name): returns the input stream for reading the specified resource.
Enumeration <URL> getResources (String name)
Dynamic Loading Method
1. Use the existing Class Loader
// will perform class initialization
Class.forName (String name);
Class.forName (String name, true, this.getClass (). GetClassLoader ());
// do not perform class initialization
Class.forName (String name, false, this.getClass (). GetClassLoader ());
this.getClass (). loadClass (String name);
// Loaded by the system class loader, no initialization is performed
ClassLoader.getSystemClassLoader (). LoadClass (String name);
// Loaded by the thread context class loader, no initialization is performed
Thread.currentThread (). GetContextClassLoader (). LoadClass (String name);
2. Use URLClassLoader
URL[] baseUrls = {new URL("file:/d:/test/demo.jar")};
URLClassLoader loader = new URLClassLoader(baseUrls);
Class clazz = loader.loadClass("com.demo.Hello");
Hello hello=(Hello)class.newInstance();
3. inherit the ClassLoader's custom Class Loader
public class MyClassLoader extends ClassLoader {
public Class<?> findClass(String name) throws ClassNotFoundException {
String classNameWithPackage = name;
Class<?> clazz = null;
try {
name = name.replace(".", "/");
name += ".class";
URL url = MyClassLoader.class.getClassLoader().getResource(name);
System.err.println(">>:" + url.getPath());
File file = new File(url.getPath());
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[fis.available()];
int len = fis.read(b);
fis.close();
System.err.println(len);
clazz = defineClass(classNameWithPackage, b, 0, len);
} catch (Exception e) {
e.printStackTrace();
}
return clazz;
}
}
Reflection
The program receives an external input object during runtime. during compilation, it cannot predict which classes the object and class may belong to. However, the program needs to call the method of the object runtime type, in this case, reflection can be used to discover the details of the object and Class Based on the Runtime information (RTTI: Runtime type information.
Get Class Object
. After the class file is loaded by the Class loader, a metadata object describing the class structure will be generated in JVM. lang. class Object can access the structure information of this Class in JVM.
In java, everything is an object. Classes are the abstraction of objects, but classes are also objects. java. lang. Class is the abstraction of classes.
The following three methods are usually used to obtain Class objects in a Java program:
(1) Use the static Class method Class. forName (String className) of the Class. The value of the String parameter is the fully qualified Class name of a Class.
(2) Call the class attribute of a Class to obtain the class object corresponding to the Class. For example, Person. class will return the Class object corresponding to the Person class.
(3) Call the getClass () method of an Object, which is defined in the java. lang. Object Class.
Obtain information from Class
The Class provides a large number of instance methods to obtain the detailed information of the Class corresponding to the Class Object:
ObtainClassConstructor contained in the class corresponding to the object:(The constructor of the parent class will not be returned)
Constructor <T> getConstructor (class <?>... ParameterTypes): returns the public constructor specified by the corresponding class.
Constuctor <?> [] GetConnstuctor (): returns allPublicConstructor
Constructor <T> getDeclaredConstructor (class <?>... ParameterTypes): returns the constructor specified by the corresponding class, regardless of the access permission of the constructor.
Constuctor <?> [] GetDeclaredConstructor (): returns the class definedAllConstructor, which is independent of the constructor's access permission.
ObtainClassMethods contained in the class corresponding to the object:
Method getMethod (String name, class <?>... ParameterTypes): returns the public method specified by the corresponding class.
Method [] getMethods (): returns all public methods of the corresponding class, including inherited methods.
Method getDeclaredMethod (String name, class <?>... ParameterTypes): returns the specified method of the corresponding class, regardless of the access permission of the method.
Method [] getDeclaredMethods (): returns all methods defined by the corresponding class, regardless of the access permission of the Method.
AccessClassTheFiled:
Filed getFiled (String name): returns the public Filed specified by the corresponding class.
Filed [] getFiled (): returns all public Filed of the corresponding class.
Filed getDeclaredFiled (String name): The Filed specified by the corresponding class is returned, which is irrelevant to the Filed access permission.
Filed [] getDeclaredFiled (): returns all fileds of the corresponding class, regardless of the Filed access permission.
The Class also provides other APIs to view the comments, internal classes, parent classes, Implemented interfaces, and other details of the Class.
The difference between getMethod () and getDeclaredMethod () in the preceding method: the former returns the public method and contains the public method inherited from the parent class. The latter only returns all methods defined by the corresponding class.
In the getMethod () method, you need to input multiple types as Class <?> Is a type parameter similar to String. class or Interger. class. Because there is a method overload in java, different methods must be distinguished based on the parameter list.
public class ClassTest {
private ClassTest () {
}
public ClassTest (String name) {
System.out.println ("Executes a constructor with parameters");
}
private void info1 () {
System.out.println ("private method");
}
public void info () {
System.out.println ("execute the info method without parameters");
}
public void info (String str) {
System.out.println ("Execute the info method with parameters" + ", its str parameter value:" + str);
}
public static void main (String [] args) throws Exception {
Class clazz = Class.forName ("demo3.ClassTest");
// Get all constructors of the class corresponding to this Class object
Constructor [] ctors = clazz.getDeclaredConstructors ();
System.out.println ("All constructors of ClassTest are as follows:");
for (Constructor c: ctors) {
System.out.println (c);
}
// Get all public constructors of the class corresponding to this Class object
Constructor [] publicCtors = clazz.getConstructors ();
System.out.println ("All public constructors of ClassTest are as follows:");
for (Constructor c: publicCtors) {
System.out.println (c);
}
// Get all public methods defined by the class corresponding to the Class object
Method [] mtds = clazz.getMethods ();
System.out.println ("All methods defined by ClassTest are as follows:");
for (Method md: mtds) {
System.out.println (md);
}
// Get the specified method of the class corresponding to the Class object
System.out.println ("The info () method with a string parameter in ClassTest is:" + clazz.getMethod ("info", String.class));
// Access the external class of this class via getDeclaringClass ()
System.out.println ("The package for ClassTest is:" + clazz.getPackage ());
System.out.println ("The parent class of ClassTest is:" + clazz.getSuperclass ());
}
}