Java reflection exploration-starting from class loading

Source: Internet
Author: User

Java reflection exploration-starting from class loading

 

I. class loading

JVM and Classes

When we call a Java command to run a Java program, this command will start a Java virtual machine process, no matter how complicated the Java program is, how many threads the program has started, they are all in the Java Virtual Machine Process. As described above, all threads and variables of the same JVM are in the same process, and they all use the memory zone of the JVM process. The JVM process is terminated in the following situations:

1. The program runs until it ends normally.
2. Run the program to end the program using the System. exit () or Runtime. getRuntime (). exit () code.
3. The program ends when an uncaptured exception or error occurs during execution.
3. The JVM process is forcibly terminated on the platform where the program is located.
From the above introduction, we can see that when the Java program is finished and the JVM process ends, the process will be lost in the memory.

Class Lifecycle

Class loading/class initialization

When a Program actively uses a class, if the class has not been loaded into the memory, the system will initialize the class by loading, connecting, and initializing. If there is no accident, the JVM completes these three steps consecutively, so these three steps are sometimes collectively referred to as class loading or class initialization.

Load: search for and load binary data of the class

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 java. lang. Class Object that represents the Class in the java heap and serve as the access entry to the data in the method area.

Note: Compile the compiled java class file (that is. class file. lang. class Object, used to encapsulate the data structure of the Class in the method area. That is, the Class object is finally obtained after loading, and it is worth noting that the Java. lang. A Class object is a single instance. No matter how many objects are created for this Class, its Class object is unique!
Connection:

1. Verification: ensure the correctness of the loaded class
2. Preparation: allocate memory for static variables of the class and initialize it as the default value.
3. parsing: converts a symbolic reference in a class into a direct reference.
Initialization: Assign the correct initial value to the static variables of the class.

Note: In the connection and initialization phase, static variables are assigned twice: the first is the default value of the static variable type, and the second is the value actually assigned to the static variable.

I drew a simple figure. The process is as follows:


Class loading refers to reading the class file of the class into the memory and creating a java. lang. class Object, that is, when any Class is used in the program, the system will create a java. lang. class Object. In fact, each Class is an abstract (or concept) of a group of objects with the same features, and all classes in the system are actually objects. They are all java. lang. Class instances.

Loading is completed by the class loader, which is usually provided by JVM. These class loaders are also the basis for all the previous programs to run, these class loaders provided by JVM are generally called system class loaders. In addition, developers can inherit the ClassLoader base class to create their own class loaders.


By using different class loaders, binary data of classes can be loaded from different sources. There are usually the following sources:

1. Load class files from the local file system, which is the class loading method of most sample programs.
2. It is also common to load class files from a JAR package. The database Driver class used in JDBC programming is stored in the JAR file, JVM can directly load the class file from the JAR file.
3. Load the class file through the network.
4. dynamically compile and load a Java source file.


The Class Loader generally does not need to wait until the class is used for the first time. the Java Virtual Machine specification allows the system to load certain classes in advance.

 

How Java programs use classes
Active use

1. Create a class instance
2. Static variables of a class or interface in the method, or assign values to the static variables
3. Call static methods of the class
4. Reflection (for example, Class. forName ("com. itzhai. Test "))
5. initialize a subclass of A Class
6. The Class (Main Class) marked as the startup Class of the Java Virtual Machine)

Passive Use
In addition to the above 6 methods, other usage of classes is passive and will not lead to class initialization. Class initialization is the first active use of classes by java programs,
All Java Virtual Machine implementations must be initialized only when each class or interface is "active for the first time" by the Java program.

 

Object initialization
When a class is loaded, connected, and initialized, this class can be used at any time. Object Instantiation and initialization are the activities of the initial stage of object life. Here we mainly discuss the characteristics of object initialization.
When compiling each class, the Java compiler generates at least one instance Initialization Method for the Class-that is () Method. This method corresponds to each constructor in the source code. If the class does not explicitly declare any constructor, the compiler generates a default non-argument constructor for the class, the default constructor only calls the parameter-free constructor of the parent class, and generates a constructor corresponding to the default constructor. () Method.
Generally, () The Code content included in the method is: call another () Method; initialize instance variables; and the code in the corresponding constructor.
If the constructor is explicitly starting from calling another constructor in the same class, it corresponds () The content in the method body is: () Method call; All bytecode in the application constructor.
If the constructor does not start by calling other constructor methods of its own class and the Object is not an Object () Includes: a pair of parent classes () Method call; the bytecode of the initialization method for instance variables; finally, the bytecode corresponding to the Construction of sub-methods.
If this class is an Object, its () The method does not include () Method call.

 

Ii. Differences between Class. forName, instance object. class (attribute), and instance object getClass ()

1. Similarities:
Through these methods, we get the Java. lang. Class Object (this is the final product of the Class mentioned above during loading)
For example:

 

Package com. lin;/*** function Overview: ** @ author linbingwen * @ since October 20, 2015 */public class people {/*** @ author linbingwen * @ since October 20, 2015 * @ param args */public static void main (String [] args) throws Exception {System. out. println (.............. load classes in different ways ...................); system. out. println (people. class); // pass the class. class obtains the Class Object people a = new people (); System. out. println (. getClass (); // use the Instance name. getClass () obtains the Class Object System. out. println (Class. forName (com. lin. people); // use Class. forName (full path) obtains the Class Object System. out. println (.............. create an object in different ways ...................); system. out. println (a); // create the object System in different ways. out. println (people. class. newInstance (); System. out. println (. getClass (). newInstance (); System. out. println (Class. forName (com. lin. people ). newInstance ());}}

 

Result:


You can see different loading methods from the above. In fact, this process only happens once!

2. Differences:

The following uses an instance to describe their differences

Create a class as follows

Package com. lin;/*** function Overview: ** @ author linbingwen * @ since October 20, 2015 */public class Cat {static {System. out. println (a cat is generated );}}

Then start using:

Package com. lin;/*** function Overview: ** @ author linbingwen * @ since October 20, 2015 */public class CatTest {/*** @ author linbingwen * @ since October 20, 2015 * @ param args */public static void main (String [] args) throws Exception {System. out. println (--------------- Cat. class starts ------------------); System. out. println (Cat. class); // pass the class. class obtains the Class Object System. out. println (--------------- Cat. class ended ------------------); System. out. println (--------------- Class. forName starts ----------------); System. out. println (Class. forName (com. lin. cat); // use Class. forName (full path) obtains the Class Object System. out. println (--------------- Class. forName ends ----------------); System. out. println (--------------- cat. getClass () starts ----------------); Cat cat = new Cat (); System. out. println (cat. getClass (); // use Class. forName (full path) obtains the Class Object System. out. println (--------------- cat. getClass () ends ------------------);}}
Output result:

If you remove Class. forName:

As follows:

 

Package com. lin;/*** function Overview: ** @ author linbingwen * @ since October 20, 2015 */public class CatTest {/*** @ author linbingwen * @ since October 20, 2015 * @ param args */public static void main (String [] args) throws Exception {System. out. println (--------------- Cat. class starts ------------------); System. out. println (Cat. class); // pass the class. class obtains the Class Object System. out. println (--------------- Cat. class ended ------------------); // System. out. println (--------------- Class. forName starts ----------------); // System. out. println (Class. forName (com. lin. cat); // use Class. forName (full path) obtains the Class Object // System. out. println (--------------- Class. forName ends ----------------); System. out. println (--------------- cat. getClass () starts ----------------); Cat cat = new Cat (); System. out. println (cat. getClass (); // use Class. forName (full path) obtains the Class Object System. out. println (--------------- cat. getClass () ends ------------------);}}

 

The result is changed:


Therefore, the following conclusions can be drawn:

1) Class cl = Cat. class;The JVM will use Cat-like class loaders to load Class A into the memory (provided that Class A has not been loaded into the memory) and will not initialize class.Returns the Class Object of Class.
2) Class cl = Object Reference o. getClass ();Returns the Class Object of the Class that references the object actually referred to during o Runtime (because the reference of the son object may be assigned to the reference variable of the parent object, if it has not been loaded, it will be loaded.
3) Class. forName (Class Name );Load Class A and initialize the class (premise: Class A has not loaded the memory)
 

3. new and newInstance ()

From the JVM perspective, when we use the keyword new to create a class, this class can not be loaded. However, when using the newInstance () method of the Class object, you must ensure that:

1. This class has been loaded;

2. This class has been connected. The above two steps are completed by the static Class method forName (). This static method calls the start Class loader, that is, the loader that loads the java API.

Now we can see that the newInstance () of the Class Object (this usage is similar to the factory mode in Java) is actually breaking down the new method into two steps, that is, first call the Class loading method to load a Class and then instantiate it. The benefits of this step-by-step operation are obvious. We can get better flexibility when calling the class Static Loading Method forName, and provide a means of downcoupling.

Class. forName (). newInstance () is different from getting an object through new.


1. Use newInstance to decouple data. The premise of using newInstance is that the class has been loaded and the class has been connected. This is exactly the work completed by the class static method forName. NewInstance breaks down the new method into two steps. That is, it first calls the class loading method to load a class and then instantiate it.

2. newInstance: weak type. Low efficiency. Only construction without parameters can be called. New: strong type. Relatively efficient. Can call any public constructor.

3. newInstance () is an inevitable choice for implementing IOC, reflection, interface programming, dependency inversion, and other technical methods. new can only implement instantiation of specific classes and is not suitable for interface programming.

4. newInstance () is generally used for dynamic loading classes.
 

5. Class. forName (""). newInstance () returns the object.

6. newInstance () is a method, while new is a keyword;

Note: Generally, class is used in the general framework. forName to load the class, and then call the method through reflection, such as in the Tomcat source code, this avoids the coupling of the new keyword, in addition, different class loaders can load different classes to improve the security and isolation between classes.


 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.