bilibili-深入理解JVM 虚拟机 学习笔记
P11 _类加载器双亲委托机制详解(11)
- 根类加载器
- 加载
$JAVA_HOME/jre/lib/rt.jar
-Xbootclasspath
用于更改引导类路径- 是最高层的加载器,没有父加载器
- JVM实现的一部分,由 C++ 实现;不是 ClassLoader 的子类
- 更多信息
- 加载
- 拓展类加载器
- 加载
$JAVA_HOME/jre/lib/ext/*.jar
- 加载
-Djava.ext.dirs
指定目录下的 jar 包特别提醒
:设置时别忘了加上系统默认的目录,-Djava.ext.dirs=./xxx:$JAVA_HOME/jre/lib/ext
- 父加载器为 根类加载器
- 加载
- 系统类加载器
- 加载 classpath 中指定的 jar 包及目录中的 class
- 加载
-Djava.class.path
指定的目录下 jar 包
- 用户自定义加载器
- 用户指定目录
package new_package.jvm.p11;
import jdk.internal.dynalink.ChainedCallSite;
import sun.misc.Launcher;
public class ClassLoaderTest {
public static void main(String[] args) {
/**
* Returns the class loader for the class. Some implementations may use
* null to represent the bootstrap class loader. This method will return
* null in such implementations if this class was loaded by the bootstrap
* class loader.
*/
ClassLoader classLoader = String.class.getClassLoader();
System.out.println(classLoader);
// null
ClassLoader classLoader2 = ChainedCallSite.class.getClassLoader();
System.out.println(classLoader2.getClass().getName());
// sun.misc.Launcher$ExtClassLoader
System.out.println(classLoader2.getParent());
// null
ClassLoader classLoader3 = Launcher.getLauncher().getClassLoader();
System.out.println(classLoader3.getClass().getName());
// sun.misc.Launcher$AppClassLoader
ClassLoader classLoader4 = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader4.getClass().getName());
// sun.misc.Launcher$AppClassLoader
}
}
P12 _类加载器与类初始化深度剖析(12)
-XX:+TraceClassLoading 加载类列表
package new_package.jvm.p12;
public class MyTest {
public static void main(String[] args) {
System.out.println(Chird.a);
Chird.dosomething();
}
}
class Parent {
static int a = 3;
static {
System.out.println("Parent static block");
}
static void dosomething(){
System.out.println("Parent dosomething");
}
}
class Chird extends Parent {
static {
System.out.println("Chird static block");
}
}
// Parent static block
// 3
// Parent dosomething
// 没有对 Chird 类主动使用
package new_package.jvm.p12;
public class MyTest2 {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class clazz = classLoader.loadClass("new_package.jvm.p12.Parent2");
System.out.println(clazz);
System.out.println("---");
Class clazz2 = Class.forName("new_package.jvm.p12.Parent2");
System.out.println(clazz2);
}
}
class Parent2 {
static {
System.out.println("Parent2 block");
}
}
// class new_package.jvm.p12.Parent2
// ---
// Parent2 block
// class new_package.jvm.p12.Parent2
loadClass() 不是对类的主动使用,不会导致类的初始化;
P13_不同的类加载器作用与加载动作分析(13)
多看看 java.lang.ClassLoader 的 javadoc 文档
/**
* Returns the system class loader for delegation. This is the default
* delegation parent for new <tt>ClassLoader</tt> instances, and is
* typically the class loader used to start the application.
*
* <p> This method is first invoked early in the runtime's startup
* sequence, at which point it creates the system class loader and sets it
* as the context class loader of the invoking <tt>Thread</tt>.
*
* <p> The default system class loader is an implementation-dependent
* instance of this class.
*
* <p> If the system property "<tt>java.system.class.loader</tt>" is defined
* when this method is first invoked then the value of that property is
* taken to be the name of a class that will be returned as the system
* class loader. The class is loaded using the default system class loader
* and must define a public constructor that takes a single parameter of
* type <tt>ClassLoader</tt> which is used as the delegation parent. An
* instance is then created using this constructor with the default system
* class loader as the parameter. The resulting class loader is defined
* to be the system class loader.
*
* <p> If a security manager is present, and the invoker's class loader is
* not <tt>null</tt> and the invoker's class loader is not the same as or
* an ancestor of the system class loader, then this method invokes the
* security manager's {@link
* SecurityManager#checkPermission(java.security.Permission)
* <tt>checkPermission</tt>} method with a {@link
* RuntimePermission#RuntimePermission(String)
* <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
* access to the system class loader. If not, a
* <tt>SecurityException</tt> will be thrown. </p>
*
* @return The system <tt>ClassLoader</tt> for delegation, or
* <tt>null</tt> if none
*
* @throws SecurityException
* If a security manager exists and its <tt>checkPermission</tt>
* method doesn't allow access to the system class loader.
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
* loader specified by the "<tt>java.system.class.loader</tt>"
* property.
*
* @throws Error
* If the system property "<tt>java.system.class.loader</tt>"
* is defined but the named class could not be loaded, the
* provider class does not define the required constructor, or an
* exception is thrown by that constructor when it is invoked. The
* underlying cause of the error can be retrieved via the
* {@link Throwable#getCause()} method.
*
* @revised 1.4
*/
public static ClassLoader getSystemClassLoader() {
// ...
}
package new_package.jvm.p13;
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
while (classLoader != null) {
classLoader = classLoader.getParent();
System.out.println(classLoader);
}
/**
* Returns the context ClassLoader for this Thread. The context
* ClassLoader is provided by the creator of the thread for use
* by code running in this thread when loading classes and resources.
* If not {@linkplain #setContextClassLoader set}, the default is the
* ClassLoader context of the parent Thread. The context ClassLoader of the
* primordial thread is typically set to the class loader used to load the
* application.
*
* <p>If a security manager is present, and the invoker's class loader is not
* {@code null} and is not the same as or an ancestor of the context class
* loader, then this method invokes the security manager's {@link
* SecurityManager#checkPermission(java.security.Permission) checkPermission}
* method with a {@link RuntimePermission RuntimePermission}{@code
* ("getClassLoader")} permission to verify that retrieval of the context
* class loader is permitted.
*
* @return the context ClassLoader for this Thread, or {@code null}
* indicating the system class loader (or, failing that, the
* bootstrap class loader)
*
* @throws SecurityException
* if the current thread cannot get the context ClassLoader
*
* @since 1.2
*/
ClassLoader classLoader2 = Thread.currentThread().getContextClassLoader();
System.out.println(classLoader2);
}
}
// sun.misc.Launcher$AppClassLoader@18b4aac2
// sun.misc.Launcher$ExtClassLoader@2b193f2d
// snull
// sun.misc.Launcher$AppClassLoader@18b4aac2s
package new_package.jvm.p13;
import java.sql.DriverManager;
public class ClassLoaderTest2 {
public static void main(String[] args) {
// 获取当前类的 ClassLoader
ClassLoader classLoader = ClassLoaderTest2.class.getClassLoader();
System.out.println(classLoader);
// 获取当前线程上下文的 ClassLoader
ClassLoader classLoader2 = Thread.currentThread().getContextClassLoader();
System.out.println(classLoader2);
// 获取系统的 ClassLoader
ClassLoader classLoader3 = ClassLoader.getSystemClassLoader();
System.out.println(classLoader3);
// ClassLoader classLoader4 = DriverManager.getCallerClassLoader();
}
}
// sun.misc.Launcher$AppClassLoader@18b4aac2
// sun.misc.Launcher$AppClassLoader@18b4aac2
// sun.misc.Launcher$AppClassLoader@18b4aac2