Article directory
1. The life cycle of a class
The complete lifecycle of a class in memory: 加载-->使用-->卸载
. The loading process is divided into 装载、链接、初始化
three stages.
2. Class loading process
When a program actively uses a certain class, if the class has not been loaded into memory, the system will initialize the class through three steps of loading, linking, and initialization. If there is no accident, the JVM will complete these three steps continuously, so these three steps are sometimes collectively referred to as class loading.
Class loading is divided into three stages:
(1) load ( Loading
)
Read the class file of the class into memory and create an java.lang.Class
object for it. This process is done by the class loader
(2) link ( Linking
)
①Verify Verify : Ensure that the loaded class information complies with the JVM specification, for example: starting with cafebabe
, there is no security issue.
② Prepare Prepare : The stage of formally allocating memory for class variables (static) 设置类变量默认初始值
, and these memory will be allocated in the method area.
③Resolve : The process of replacing symbolic references ( constant names) in the virtual machine constant pool with direct references (addresses).
(3) Initialize ( Initialization
)
-
The process of execution
类构造器<clinit>()方法
.类构造器<clinit>()方法
It is generated by combining the assignment actions of all class variables in the class automatically collected at compile time and the statements in the static code block. (The class constructor is for constructing class information, not for constructing objects of that class). -
When initializing a class, if you find that its parent class has not been initialized, you need to trigger the initialization of its parent class first.
-
The virtual machine ensures that a thread
类的<clinit>()方法
is properly locked and synchronized in a multi-threaded environment.
3. Class loader (classloader)
3.1 The role of the class loader
Load class
the file bytecode content into the memory, and convert these static data into the runtime data structure of the method area, and then generate an object representing this class in the heap java.lang.Class
as the access entry of the class data in the method area.
Class caching: Standard JavaSE
class loaders can look up classes on demand, but once a class is loaded into the class loader, it will remain loaded (cached) for a period of time. However, the JVM garbage collection mechanism can reclaim these Class
objects.
3.2 Classification of class loaders (JDK8)
The JVM supports two types of class loaders, namely 引导类加载器(Bootstrap ClassLoader)
and 自定义类加载器(User-Defined ClassLoader)
.
Conceptually speaking, a custom class loader generally refers to a type of class loader that is customized by the developer in the program, but the Java Virtual Machine Specification does not define it in this way, but all class loaders derived from abstract ClassLoader
classes Both are divided into custom class loaders. No matter how the type of class loader is divided, our most common class loader structure in the program is mainly as follows:
(1) Startup class loader (bootstrap class loader, Bootstrap ClassLoader)
- This class loading is
C/C++语言
implemented using, nested inside the JVM. Often returns null when getting its object - It is used to load Java's core library (
JAVA_HOME
/jre
/lib
/rt.jar
orsun.boot.class.path
the contents of the path). Used to provide classes needed by the JVM itself. - Does not inherit from
java.lang.ClassLoader
, has no parent loader. - For security reasons, the Bootstrap startup class loader only loads classes whose package name starts with
java
,javax
, etc.sun
- Load extension classes and application class loaders, and specify them as their parent class loaders.
(2) Extension ClassLoader (Extension ClassLoader)
- Written in the Java language and
sun.misc.Launcher$ExtClassLoader
implemented by . - Inherited from the ClassLoader class
- The parent class loader is the startup class loader
- Load the class library from
java.ext.dirs
the directory specified by the system property, or load the class library from thejre
/lib
/ subdirectory of the JDK installation directory.ext
If user-created JARs are placed in this directory, they will also be automatically loaded by the extension class loader.
(3) Application class loader (system class loader, AppClassLoader)
- Written in java language,
sun.misc.Launcher$AppClassLoader
implemented by - inherits from
ClassLoader
class - The parent class loader is the extension class loader
- It is responsible for loading the class library under the path specified by
classpath
the environment variable or system propertyjava.class.path
- The class loader in the application defaults to the system class loader.
- It is the default parent loader for user-defined class loaders
- The class loader can be obtained by the
ClassLoader
methodgetSystemClassLoader()
(4) User-defined class loader (understand)
- In the daily application development of Java, the loading of classes is almost performed by the cooperation of the above three types of loaders. When necessary, we can also customize the class loader to customize the way classes are loaded.
- One of the key factors reflecting the powerful vitality and great charm of the Java language is that Java developers can customize the class loader to realize the dynamic loading of the class library. The loading source can be a local JAR package or a remote resource on the network. .
- At the same time, custom loaders can be implemented
应用隔离
. For example, middleware and component frameworks such as Tomcat and Spring implement custom loaders internally, and isolate different component modules through custom loaders. This mechanism is much better than the C/C++ program. It is almost impossible to add new functions to the C/C++ program without modifying it. Only one compatibility can block all good ideas. - Custom class loaders usually need to inherit from ClassLoader.
3.3 Parental delegation mechanism
The process of class loading in java adopts the parent delegation mechanism. Loading a class is first entrusted by the application class loader to the extension class loader, and then entrusted by the extension class loader to the startup class loader. If the startup class loader finds that it cannot load If not, it will be loaded by the extension class loader. If the extension class loader cannot be loaded, it will be loaded by the application class loader. If the application class loader cannot be found, an exception will be reported ClassNotFound
.
understand:
- If a class loader receives a class loading request, it will not try to load the class by itself first, but will delegate the request to the parent class loader to complete.
- This is true for every level of classloader. Therefore, all loading requests should eventually be delivered to the top-level startup class loader.
- Only when the parent loader reports that it cannot complete the loading request (the required class is not found in the search scope), the child loader will try to load it by itself.
In the same way (why from bottom to top, and then from top to bottom) : After a class receives a class loading request, if the class is not loaded, the current class loader will not load the class itself , but put this The class loading request is delegated to its parent class to complete, and the parent class continues to delegate to its parent class loader after receiving the request, and so on, until all requests are delegated to the startup class loader . If this class is not loaded by the startup class loader, the subclass loader will be delegated down to load this class until the request is successfully loaded, but until the custom loader is not found, the JVM will throw an ClassNotFund
exception.
The picture is taken from the Internet.
3.3.1 Advantages of Parental Delegation Mechanism
- Avoid duplicate loading of classes
- When a class with the same name as the package is defined in your own program
Java.lang
, at this time, because the parental delegation mechanism is used, the class in progress will be loaded by the startup class loaderJAVA_HOME/lib
instead of the user-defined class. At this point, the program can be compiled normally, but the class defined by itself cannot be loaded and run. - Protect the security of the program and prevent the core API from being tampered with at will. Through delegation, the core will not be tampered with
.class
, even if it is tampered with, it will not be loaded, and even if it is loaded, it will not be the same.class
object. Different loaders load the same.class
or not the sameClass
object. This ensuresClass
execution security.- For example , if you define a
java.lang.String
class yourself, it will first be loaded by the application class loader. The application class loader recognizes that this class does not belong to me, because it is a class at the JVM system level. At this time, the application loader will not load it. Delegate upward until the class loader is started, and the class loader recognizes that this class belongs to me to load, and it will go down andJAVA_HOME
load the class with the same package nameString
. After the loading is complete, even if there is another class with the same package name and class name, itString
will not be loaded, because the class with the same package name has already been loaded, which will cause even if the developer defines a class with the same package as the JVM level. To load self-defined classes ensures system-level class loading security and prevents core APIs from being tampered with at will.
- For example , if you define a
3.4 View the class loader object of a class
(1) Get the default system class loader
ClassLoader classloader = ClassLoader.getSystemClassLoader();
(2) Check which class loader loaded a certain class
ClassLoader classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
//如果是根加载器加载的类,则会得到null
ClassLoader classloader1 = Class.forName("java.lang.Object").getClassLoader();
(3) Get the parent loader of a class loader
ClassLoader parentClassloader = classloader.getParent();
Sample code:
import org.junit.Test;
public class TestClassLoader {
@Test
public void test01(){
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("systemClassLoader = " + systemClassLoader);
}
@Test
public void test02()throws Exception{
ClassLoader c1 = String.class.getClassLoader();
System.out.println("加载String类的类加载器:" + c1);
ClassLoader c2 = Class.forName("sun.util.resources.cldr.zh.TimeZoneNames_zh").getClassLoader();
System.out.println("加载sun.util.resources.cldr.zh.TimeZoneNames_zh类的类加载器:" + c2);
ClassLoader c3 = TestClassLoader.class.getClassLoader();
System.out.println("加载当前类的类加载器:" + c3);
}
@Test
public void test03(){
ClassLoader c1 = TestClassLoader.class.getClassLoader();
System.out.println("加载当前类的类加载器c1=" + c1);
ClassLoader c2 = c1.getParent();
System.out.println("c1.parent = " + c2);
ClassLoader c3 = c2.getParent();
System.out.println("c2.parent = " + c3);
}
}
3.5 Use ClassLoader to get the stream
One of the main methods about the class loader: getResourceAsStream(String str): Get the input stream of the specified file under the class path
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("exer2\\test.properties");
System.out.println(in);
Example:
//需要掌握如下的代码
@Test
public void test5() throws IOException {
Properties pros = new Properties();
//方式1:此时默认的相对路径是当前的module
// FileInputStream is = new FileInputStream("info.properties");
// FileInputStream is = new FileInputStream("src//info1.properties");
//方式2:使用类的加载器
//此时默认的相对路径是当前module的src目录
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info1.properties");
pros.load(is);
//获取配置文件中的信息
String name = pros.getProperty("name");
String password = pros.getProperty("password");
System.out.println("name = " + name + ", password = " + password);
}