1. 任何Class对象,都会包含一个定义该类的ClassLoader对象
2. 数组类(一个数组,元素是类)不由类加载器创建,是运行时由java虚拟机根据需要创建。如果使用该数组对象调用getClassLoader对象,则返回的类加载器的类型和他元素调用getClassLoader()方法,返回的是一样的。
String[] str = new String[2]; //在rt.jar下,所以是根类加载器加载
System.out.println(str.getClass().getClassLoader());
System.out.println("-------------------");
MyTest[] tests = new MyTest[4];
System.out.println(tests.getClass().getClassLoader());
注意下面这种:
int[] ints = new int[2];
System.out.println(ints.getClass().getClassLoader());
这里返回null并不是表示他也有根类加载器加载,而是因为,原始类型的数组类没有类加载器。
3. 自定义类加载器,就是对原生ClassLoader的一种扩展。ClassLoader是一个抽象类,所以我们自己定义累加器只需要继承ClassLoader类,然后加入特定需求就好。
4. 类加载器使用双亲委托去找需要的类或者资源。
5. 支持并行加载类的类加载器,叫并发类加载器。在初始化类的时候该类加载器通过ClassLoader.registerAsParallelCapable注册。
6. 在委托模型不是特别清晰的情况下,区别于jvm已有的委托模型,那么加载的时候,需要做并行操作,否则类加载的时候会出现死锁的情况。 (这条没遇见过,理解有点困难)
7. 本地系统的jvm类加载,通过我们配置的classpath去找到并加载资源,这样来看,spring配置文件中,配置classpath去加载文件或者资源也是这种思想。windows上就和我们配置jdk的系统变量一个意思。
8.还有一些类资源并不是以文件的形式存在于我们的电脑上,比如通过网络加载(比如Maven),还有一些通过程序运行过程中动态的生成(比如动态代理)。这种情况下defineClass方法将这些动态的字节数组(动态获取的这些资源以字节数组的形式表现,在还没有被转化前)转化为一个类实例,使用Class.newInstance。
9.
看视频上面给了一个例子,网络类加载器,他需要继承ClassLoader类,并且必须要有findClass方法和loadClassData方法,这两个方法在ClassLoader中也有。findClass负责将loadClassData方法在网络上下载并返回的字节码数组,转化为对应的类实例(这一步由defineClass完成 )