精华内容
下载资源
问答
  • 启动类加载器 用 Bootstrap 类加载器加载类: public class F { static { System.out.println("bootstrap F init"); } } 执行 public class Load5_1 { public static void main(String[] args) throws ...

    启动类加载器

    用 Bootstrap 类加载器加载类:

    public class F {
    	static {
    		System.out.println("bootstrap F init");
    	}
    }

    执行

    public class Load5_1 {
    	public static void main(String[] args) throws ClassNotFoundException {
    		Class<?> aClass = Class.forName("cn.leon.jvm.t3.load.F");
    		System.out.println(aClass.getClassLoader());
    	}
    }	

    输出 

    E:\git\jvm\out\production\jvm>java -Xbootclasspath/a:.
    cn.itcast.jvm.t3.load.Load5
    bootstrap F init
    null

    -Xbootclasspath 表示设置 bootclasspath
    其中 /a:. 表示将当前目录追加至 bootclasspath 之后
    可以用这个办法替换核心类
        java -Xbootclasspath:<new bootclasspath>
        java -Xbootclasspath/a:<追加路径>
        java -Xbootclasspath/p:<追加路径>

    展开全文
  • Java中的类和类加载器一起 唯一确定类在jvm中的一致性。 BootStrapClassLoader <- ExtClassLoader <- AppClassLoader <- 自定义类加载器 ...启动类加载器:主要负责加载 java.home 下的 lib 目录下的...

    Java中的类和类加载器一起 唯一确定类在jvm中的一致性。

    • BootStrapClassLoader <- ExtClassLoader <- AppClassLoader <- 自定义类加载器

    • 启动类加载器:主要负责加载 java.home 下的 lib 目录下的类库或者被 -Xbootclasspath 参数指定的路径中的类库。应用程序不能直接使用该加载器。
    • 扩展类加载器:负责加载 java.home 下的 lib/ext 下的类或者系统变量 java.ext.dirs 指定路径下的类库。开发者可以使用该加载器。
    • 引用程序类加载器:负责加载用户指定的路径 即 classPath 下的类库。如果程序员没有自定义类加载器,默认调用该加载器。

    • 双亲委派模型要求,除了顶层的启动类加载器以外,其他的类加载器都要有自己的父类加载器,使用组合关系复用父类加载器。
    • 过程:当用户需要加载器时,首先不会自己去加载这个类,而是将请求委托给父类加载器,每一层都是如此,因此最终都会到达顶层的类加载器。只有当父类加载器反馈不能加载,才会将加载的任务给子类加载器。
    • 好处:让Java类同其类加载器一起具备了一种带优先级。比如我们要加载java.lang.Object类,无论我们用哪个类加载器去加载Object类,这个加载请求最终都会委托给Bootstrap ClassLoader,这样就保证了所有加载器加载的Object类都是同一个类。这样保证了Java程序运行的稳定性。

    转载于:https://my.oschina.net/u/4141148/blog/3068731

    展开全文
  • 平台特定的启动类加载器深入分析与自定义系统类加载器详解 1.关于根类加载器和其他类加载: ​ 内建于JVM中启动类加载器会加载java.lang.ClassLoader以及其他的Java平台类;当JVM启动时,一块特殊的机器码会运行,...

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

    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
      
    展开全文
  • 什么是启动类加载器 就是SpringBoot启动后,要立马执行的程序,这时候就需要启动类加载器完整这个要求。 启动类加载器实践 1、创建第一个启动类加载器(方式1) 1)、创建启动类加载器,实现CommandLineRunner...

    目录

     

    什么是启动类加载器

    启动类加载器实践

    1、创建第一个启动类加载器(方式1)

    2、多个类加载器,如何控制调用顺序

    启动类加载器原理


    什么是启动类加载器

    就是SpringBoot启动后,要立马执行的程序,这时候就需要启动类加载器完整这个要求。

     

    启动类加载器实践

    1、创建第一个启动类加载器(方式1)

    1)、创建启动类加载器,实现CommandLineRunner接口

    @Component
    
    public class FirstCommandlineRunner  implements CommandLineRunner{
    
        @Override
    
        public void run(String... args) throws Exception {
    
            System.out.println("\u001B[32m >>> startup fist runner<<<");
    
        }
    
    }

      

    2)、启动项目,输出如下

     

    2、多个类加载器,如何控制调用顺序

    只需要增加Order注解即可

    第一个启动类加载器

    @Component
    
    @Order(1)
    
    public class FirstCommandlineRunner  implements CommandLineRunner{
    
        @Override
    
        public void run(String... args) throws Exception {
    
            System.out.println("\u001B[32m >>> startup fist runner<<<");
    
        }
    
    }

     

    第二个启动类加载器

    @Component
    
    @Order(2)
    
    public class SecondCommandlineRunner implements CommandLineRunner{
    
        @Override
    
        public void run(String... args) throws Exception {
    
            System.out.println("\u001B[32m >>> startup second runner<<<");
    
        }
    
    }

    然后启动项目,输出如下

     

    2、创建类加载器,方式二

    1)、创建FirstApplicationRunner 类,实现 ApplicationRunner接口,然后设置Order为1

    @Component
    
    @Order(1)
    
    public class FirstApplicationRunner  implements ApplicationRunner{
    
        @Override
    
        public void run(ApplicationArguments args) throws Exception {
    
            System.out.println("\u001B[32m >>> startup first application runner<<<");
    
    
        }
    
    }

      

    2) 同理,创建SecondApplicationRunner 类,实现 ApplicationRunner接口,然后设置Order为2

    @Component
    
    @Order(2)
    
    public class SecondApplicationRunner implements ApplicationRunner{
    
        @Override
    
        public void run(ApplicationArguments args) throws Exception {
    
            System.out.println("\u001B[32m >>> startup second application runner<<<");
    
    
        }
    
    }

      

    3)启动项目,查看输出结果如下

     

    启动类加载器原理

    进入run方法,启动类加载器的入口是callRunners方法

     

    进入callRunners方法

    private void callRunners(ApplicationContext context, ApplicationArguments args) {
    
        List<Object> runners = new ArrayList<>();
    
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    
        AnnotationAwareOrderComparator.sort(runners);
    
        for (Object runner : new LinkedHashSet<>(runners)) {
    
            if (runner instanceof ApplicationRunner) {
    
                callRunner((ApplicationRunner) runner, args);
    
            }
    
            if (runner instanceof CommandLineRunner) {
    
                callRunner((CommandLineRunner) runner, args);
    
            }
    
        }
    
    }

    将实现ApplicationRunner接口的类实例增加到runners列表中

    将实现CommandLineRunner接口的类实例增加到runners列表中。

    然后进行排序AnnotationAwareOrderComparator.sort(runners);

    排序完毕后依次调用callRunner方法

     

    callRunner方法实现如下。里面调用各自的run方法

    private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
        try {
            (runner).run(args);
    
        }catch (Exception ex) {
            throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
        }
    
    }
    
    
    private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
        try {
            (runner).run(args.getSourceArgs());
        }catch (Exception ex) {
            throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
        }
    
    }

     

    展开全文
  • 平台特定的启动类加载器深入分析: 这里以上一次【https://www.cnblogs.com/webor2006/p/9157626.html】的这个程序作为学习的开端,如下: 运行结果: /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/...
  • 通过上截图,可以看出,应用类加载器的加载目录为.也就是当前目录 下图就是.(点)目录 总结: 若是将 根加载器加载目录修改下 改成当前目录 虚拟机初始化的时候出错,先加载Object类 找不到object类,虚拟机...
  • 在运行期,一个Java类是由该类的完全限定名(binary name,二进制名)和用于加载该类的定义类加载器(defining loader)所共同决定的。如果同样名字(即相同的完全限定名)的类是由两个不同的加载器所加载,那么这些...
  • 启动加载器是如何实现的? 答:流程图 3. 启动加载器实现有什么异同点? 相同:实现方法名一致,都是run。调用点一样都是callRunner方法。 不同:执行顺序优先级不一样,run方法传入参数不一样。 4. 启动加载器的...
  • 那么我们怎么证明扩展类加载器和应用类加载器也是由启动类加载器加载呢,由于扩展类加载器和应用类加载器都是在Launcher这个类里边,并且不是public的,那么我们就无法在MyTest23里边直接引用他们,但是之前我们提到...
  • Bootstrap里加载的是/LIB 里的类库 如下 [img]http://dl.iteye.com/upload/attachment/415860/287207b3-1d0b-324d-8861-ba587cd38c99.png[/img] 大概的看下 几个类库 rt.jar JAVA基础库 charset.jar java...
  • 最近使用唯品会的vjtools的BeanMapper进行对象的深度克隆转换DTO/VO这种操作,SpringBoot的dev-tools热启动,需要把vjtools和dozer包都放到spring-devtools.properties的incloud里面,否则会出现强转失败的问题,...
  • 内建于JVM中的启动类加载器会加载java.lang.ClassLoader以及其他java平台类, 当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器, 这块特殊的机器码叫做启动类加载器(Bootstarp)。 启动类...
  • 启动类加载器(引导类加载器,Bootstrap ClassLoader)2.扩展类加载器(Extension ClassLoader)3.应用程序类加载器(系统类加载器,AppclassLoader)4.自定义类加载器ClassLoader 类加载器系统 类加载器子系统负责...
  • 1.启动类加载器(Bootstrap ClassLoader):负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类。 2.扩展类加载器(Extension ClassLoader):...
  • 请问,若自定义一个类加载器启动时加载类走的是自定义类加载器还是AppClass Loader?
  • 在java中默认有三个加载器启动类加载器,扩展类加载器,应用类加载器启动类加载器是用来加载 Java 的核心类,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是...
  • 内建于jvm中的启动类加载器会加载java.lang.classloader以及其他的java类平台, 当jvm启动时,一块特殊的机器码会运行,它会加载扩展类加载器与系统类加载器, 这块特使的机器码叫作启动类加载器(Bootstrap)。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,019
精华内容 2,007
关键字:

启动类加载器