类加载
reference: https://docs.oracle.com/javase/tutorial/ext/basics/load.html
-
bootstrap classloader
:引导(也称为原始)类加载器,它负责加载 Java 的核心类。这个加载器是非常特殊的,它实际上不是java.lang.ClassLoader
的子类,而是由 JVM 自身实现的(底层是 C 代码)。因为 JVM 在启动的时候就自动加载它们, 所以不需要在系统属性 CLASSPATH 中指定这些类库 -
system classloader
:系统(也称为应用)类加载器,它负责在 JVM 被启动时,加载来自在命令java中的-classpath
或者java.class.path
系统属性或者 CLASSPATH 操作系统属性所指定的 JAR 类包和类路径。可以通过静态方法ClassLoader.getSystemClassLoader();
找到该类加载器。如果没有特别指定,则用户自定义的任何类加载器都将该类加载器作为它的父加载器 -
extension classloader
:扩展类加载器,它负责加载 JRE 的扩展目录(JAVA_HOME/jre/lib/ext
或由java.ext.dirs
系统属性指定的)中的 JAR 包。这为引入除 Java 核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个 JRE 中启动的 JVM 都是通用的,所以放入这个目录的 JAR 类包对所有的 JVM 和system classloader
都是可见的
classloader 加载类用的是 全盘负责委托机制
全盘负责
:即是当一个 classloader 加载一个 Class 的时候,这个 Class 所依赖的和引用的其它 Class通常
也由这个 classloader 负责载入委托机制
:先让 parent(父)类加载器 寻找,只有在 parent 找不到的时候才从自己的类路径中去寻找。- 类加载还采用了
cache机制
:如果 cache 中保存了这个 Class 就直接返回它,如果没有才从文件中读取和转换成 Class,并存入 cache,这就是为什么修改了 Class 但是必须重新启动 JVM 才能生效,并且类只加载一次的原因
Understanding Extension Class Loading
The extension framework makes use of the class-loading delegation mechanism. When the runtime environment needs to load a new class for an application, it looks for the class in the following locations, in order:
- Bootstrap classes: the runtime classes in
rt.jar
, internationalization classes ini18n.jar
, and others. - Installed extensions: classes in JAR files in the
lib/ext
directory of the JRE, and in the system-wide, platform-specific extension directory (such as/usr/jdk/packages/lib/ext
on the Solaris™ Operating System, but note that use of this directory applies only to Java™ 6 and later). - The class path: classes, including classes in JAR files, on paths specified by the system property
java.class.path
. If a JAR file on the class path has a manifest with theClass-Path
attribute, JAR files specified by theClass-Path
attribute will be searched also. By default, thejava.class.path
property’s value is.
, the current directory. You can change the value by using the-classpath
or-cp
command-line options, or setting theCLASSPATH
environment variable. The command-line options override the setting of theCLASSPATH
environment variable.
The precedence list tells you, for example, that the class path is searched only if a class to be loaded hasn’t been found among the classes in rt.jar
, i18n.jar
or the installed extensions.
Unless your software instantiates its own class loaders for special purposes, you don’t really need to know much more than to keep this precedence list in mind. In particular, you should be aware of any class name conflicts that might be present. For example, if you list a class on the class path, you’ll get unexpected results if the runtime environment instead loads another class of the same name that it found in an installed extension.
The Java Class Loading Mechanism
The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.
Here are some highlights of the class-loading API:
-
Constructors in
java.lang.ClassLoader
and its subclasses allow you to specify a parent when you instantiate a new class loader. If you don’t explicitly specify a parent, the virtual machine’s system class loader will be assigned as the default parent. -
The
loadClass
method inClassLoader
performs these tasks, in order, when called to load a class:- If a class has already been loaded, it returns it.
- Otherwise, it delegates the search for the new class to the parent class loader.
- If the parent class loader does not find the class,
loadClass
calls the methodfindClass
to find and load the class.
-
The
findClass
method ofClassLoader
searches for the class in the current class loader if the class wasn’t found by the parent class loader. You will probably want to override this method when you instantiate a class loader subclass in your application. -
The class
java.net.URLClassLoader
serves as the basic class loader for extensions and other JAR files, overriding thefindClass
method ofjava.lang.ClassLoader
to search one or more specified URLs for classes and resources.
To see a sample application that uses some of the API as it relates to JAR files, see the Using JAR-related APIs lesson in this tutorial.
Class Loading and the java
Command
The Java platform’s class-loading mechanism is reflected in the java
command.
- In the
java
tool, the-classpath
option is a shorthand way to set thejava.class.path
property. - The
-cp
and-classpath
options are equivalent. - The
-jar
option runs applications that are packaged in JAR files. For a description and examples of this option, see the Running JAR-Packaged Software lesson in this tutorial.
双亲委派 (父类委托)
reference: https://docs.oracle.com/cd/E19159-01/819-3672/gfqpi/index.html
防止内存中出现多份同样的字节码, 保护 Java 程序的正常运行 (系统自带的三个类加载器都加载特定目录下的类)
注意:
- 不能叫委托机制, 和 C++ 中的函数指针或 C# 中的引用类型不一样
The Class Loader Hierarchy
Class loaders in the Application Server runtime follow a delegation hierarchy
Delegation
Note that the class loader hierarchy is not a Java inheritance hierarchy, but a delegation hierarchy. In the delegation design, a class loader delegates classloading to its parent before attempting to load a class itself. A class loader parent can be either the System class loader or another custom class loader. If the parent class loader cannot load a class, the class loader attempts to load the class itself. In effect, a class loader is responsible for loading only the classes not available to the parent. Classes loaded by a class loader higher in the hierarchy cannot refer to classes available lower in the hierarchy.
The Java Servlet specification recommends that the Web class loader look in the local class loader before delegating to its parent. You can make the Web class loader follow the delegation inversion model in the Servlet specification by setting delegate=“false” in the class-loader element of the sun-web.xml file. It is safe to do this only for a web module that does not interact with any other modules. For details, see class-loader in Sun Java System Application Server 9.1 Application Deployment Guide.
The default value is delegate=“true”, which causes the Web class loader to delegate in the same manner as the other class loaders. You must use delegate=“true” for a web application that accesses EJB components or that acts as a web service client or endpoint. For details about sun-web.xml, see The sun-web.xml File in Sun Java System Application Server 9.1 Application Deployment Guide.