24-平台特定的启动类加载器深入分析与自定义系统类加载器详解

平台特定的启动类加载器深入分析与自定义系统类加载器详解

1.关于根类加载器和其他类加载:

​ 内建于JVM中启动类加载器会加载java.lang.ClassLoader以及其他的Java平台类;当JVM启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器;这块特殊的机器码叫做启动类加载器(Bootstrap)

​ 启动类加载器并不是Java类,而其他的加载器则都是Java类;启动类加载器是特定于平台的机器指令,它负责开启整个加载过程。

​ 所有类加载器(除了启动类加载器)都被实现为Java类。不过,总归要有一个组件来加载第一个Java类加载器,从而让整个加载过程能够顺利进行下去,加载第一个纯Java类加载器就是启动类加载器的职责。

​ 启动类加载器还会负责加载供JRE正常运行所需要的基本组件,这包括java.util与java.lang包中的类等等

所以:ClassLoader(系统类加载器)是由根类加载器所加载的!

 System.out.println(ClassLoader.class.getClassLoader());
 运行结果:
 	null

所以:扩展类加载器和系统类加载器也是由启动类加载器所加载的(AppClassLoader和ExtClassLoader的静态内部类都是这在Launcher中,所以加载Launcher的类加载器也是AppClassLoader、ExtClassLoader的类加载器)

 System.out.println(Launcher.class.getClassLoader());
 运行结果:
 	null
2.ClassLoader.getSystemClassLoader()源码解读:

​ Returns the system class loader for delegation. This is the default delegation parent for new ClassLoader instances, and is typically the class loader used to start the application.

​ 返回用于委派的系统类加载器。这是新类加载器实例的默认委托双亲,通常是用于启动应用程序的类加载器。

​ 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 Thread.

​ 此方法首先在运行时的启动序列的早期调用,此时它将创建系统类加载器并将其设置为调用线程的上下文类加载器。

​ The default system class loader is an implementation-dependent instance of [this class].

​ 默认的系统类加载器是该类的依赖于实现的实例。

​ If the system property “java.system.class.loader” 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 ClassLoader 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.

①如果在首次调用此方法时定义了系统属性“java.system.class.loader”,则该属性的值将被视为将作为系统类加载器返回的类的名称。**②这个类是使用默认的系统类加载器加载,并且必须定义一个公共构造函数,该构造函数接受一个用作委托父类的类加载器类型的参数。**然后使用此构造函数创建一个实例,并使用默认的系统类加载器作为参数。生成的类加载器被定义为系统类加载器【就是将自定义的类加载定义为系统类加载器】。【每一句都贼重要!!!】

​ If a security manager is present, and the invoker’s class loader is not null 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 checkPermission method with a RuntimePermission(“getClassLoader”) permission to verify access to the system class loader. If not, a SecurityException will be thrown.

​ 如果存在安全管理器,并且调用程序的类加载器不为空,并且调用程序的类加载器与系统类加载器不相同或不是系统类加载器的祖先,则此方法使用RuntimePermission(“getClassLoader”)权限调用安全管理器的checkPermission方法来验证对系统类加载器的访问。否则,将引发SecurityException。

Returns:
The system ClassLoader for delegation, or null if none

返回值: 用于委托的系统类加载器,或者为none时,返回空。

3.自定义系统类加载器:通过"java.system.class.loader"来设置
  • MyTest16为自定义类加载器,将其设置为系统类加载器,需要定义一个公共构造函数,该构造函数接受一个用作委托父类的类加载器类型的参数:(在MyTest16.java中添加这个构造方法)

    • public MyTest16(ClassLoader parent){
      	super(parent);
      }
      
    • 在没有添加构造函数之前:

      //将MyTest16作为系统类加载器去执行MyTest23
       public static void main(String[] args) {
          System.out.println(System.getProperty("java.system.class.loader"));
       }
      ...\out\production\IdeaProject>java -Djava.system.class.loader=Jvm.MyTest16 Jvm.MyTest23
      
      执行结果:
         Error occurred during initialization of VM
         java.lang.Error: java.lang.NoSuchMethodException: Jvm.MyTest16.<init>(java.lang.ClassLoader)
                 at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
                 at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)
         Caused by: java.lang.NoSuchMethodException: Jvm.MyTest16.<init>(java.lang.ClassLoader)
      
    • 添加构造函数之后:

      //将MyTest16作为系统类加载器去执行MyTest23
       public static void main(String[] args) {
          System.out.println(System.getProperty("java.system.class.loader"));
       }
      ...\out\production\IdeaProject>java -Djava.system.class.loader=Jvm.MyTest16 Jvm.MyTest23
      
      执行结果:
      		Jvm.MyTest16
      
  • 总结:可以知道通过java -Djava.system.class.loader=Jvm.MyTest16 ,将MyTest16显式的指定为系统类加载器

4.在控制台和终端执行下面的结果:
public class MyTest23 {
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.system.class.loader"));
        System.out.println(MyTest23.class.getClassLoader());
        System.out.println(MyTest16.class.getClassLoader());
        System.out.println(ClassLoader.getSystemClassLoader());//打印系统类加载器
    }
}
  • 在控制台执行结果::

    null
    sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$AppClassLoader@18b4aac2  // app
    
  • 在终端执行结果:

    Jvm.MyTest16
    sun.misc.Launcher$AppClassLoader@18b4aac2
    sun.misc.Launcher$AppClassLoader@18b4aac2
    [null]  //我这里不知道为什么是空,而老师讲的运行之后应该为:Jvm.MyTest16@....  //应该是MyTest16
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值