JVM学习(9)研究JVM底层ClassLoader源码分析与案列

研究JVM底层ClassLoader源码分析与案列

首先由外而内

  • ClassLoader是有JDK1.0版本就已经出现了
  • ClassLoader是一个抽象类继承Object

接下来我们来看看ClassLoader的Documentation

java.lang public abstract class ClassLoader(java.lang包里面公共抽象ClassLoader 类
extends Object(继承父类是Object
A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a “class file” of that name from a file system.(类加载器是负责加载类的对象。ClassLoader是一个抽象类。给定一个类的二进制名称,类加载器应该尝试定位或生成构成该类定义的数据。典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。
Every Class object contains a reference to the ClassLoader that defined it.(每个类对象都包含对定义它的类加载器的引用。
Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime. The class loader for an array class, as returned by Class.getClassLoader() is the same as the class loader for its element type; if the element type is a primitive type, then the array class has no class loader.(数组类的类对象不是由类加载器创建的,而是根据Java运行时的要求自动创建的。由Class.getClassLoader()返回的数组类的类加载器与其元素类型的类加载器相同;如果元素类型是基元类型,那么数组类没有类加载器。
Applications implement subclasses of ClassLoader in order to extend the manner in which the Java virtual machine dynamically loads classes.(应用程序实现类加载器的子类,以便扩展Java虚拟机动态加载类的方式。
Class loaders may typically be used by security managers to indicate security domains.(安全管理器通常会使用类加载器来指示安全域。
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine’s built-in class loader, called the “bootstrap class loader”, does not itself have a parent but may serve as the parent of a ClassLoader instance.(ClassLoader类使用委托模型来搜索类和资源。类加载器的每个实例都有一个关联的父类加载器。当请求查找类或资源时,类加载器实例将在试图查找类或资源本身之前,将对类或资源的搜索委托给其父类加载器。虚拟机的内置类加载器称为“引导类加载器”,它本身没有父类,但可以作为类加载器实例的父类。
Class loaders that support concurrent loading of classes are known as parallel capable class loaders and are required to register themselves at their class initialization time by invoking the ClassLoader.registerAsParallelCapable method. Note that the ClassLoader class is registered as parallel capable by default. However, its subclasses still need to register themselves if they are parallel capable. In environments in which the delegation model is not strictly hierarchical, class loaders need to be parallel capable, otherwise class loading can lead to deadlocks because the loader lock is held for the duration of the class loading process (see loadClass methods).(支持类的并发加载的类加载器被称为支持并行的类加载器,并且需要在类初始化时通过调用ClassLoader . RegisterAsParallelEnable方法来注册自己。请注意,默认情况下,ClassLoader类注册为支持并行。然而,它的子类仍然需要注册它们自己,如果它们能够并行的话。在委托模型没有严格分层的环境中,类装入器需要具有并行能力,否则类装入会导致死锁,因为装入器锁在类装入过程中一直保持着(参见loadClass方法)。
Normally, the Java virtual machine loads classes from the local file system in a platform-dependent manner. For example, on UNIX systems, the virtual machine loads classes from the directory defined by the CLASSPATH environment variable.(通常,Java虚拟机以平台相关的方式从本地文件系统加载类。例如,在UNIX系统上,虚拟机从类路径环境变量定义的目录中加载类。
However, some classes may not originate from a file; they may originate from other sources, such as the network, or they could be constructed by an application. The method defineClass converts an array of bytes into an instance of class Class. Instances of this newly defined class can be created using Class.newInstance.(但是,有些类可能不是来自文件;它们可能来自其他来源,如网络,也可能由应用程序构建。方法defineClass将字节数组转换为类类的实例。这个新定义的类的实例可以使用
The methods and constructors of objects created by a class loader may reference other classes. To determine the class(es) referred to, the Java virtual machine invokes the loadClass method of the class loader that originally created the class.(类加载器创建的对象的方法和构造函数可以引用其他类。为了确定所引用的类,Java虚拟机调用最初创建该类的类加载器的loadClass方法。
For example, an application could create a network class loader to download class files from a server.(例如,应用程序可以创建一个网络类加载器来从服务器下载类文件。

Sample code might look like:(示例代码可能如下所示
ClassLoader loader = new NetworkClassLoader(host, port);(host主机名,port端口号
Object main = loader.loadClass(“Main”, true).newInstance();(原始的class,因为指定了包名+类名
. . .

The network class loader subclass must define the methods findClass and loadClassData to load a class from the network. Once it has downloaded the bytes that make up the class, it should use the method defineClass to create a class instance. A sample implementation is:(网络类加载器子类必须定义从网络中加载类的方法findClass和loadClassData。一旦它下载了组成类的字节,它应该使用方法defineClass创建一个类实例。一个示例实现是:

       class NetworkClassLoader extends ClassLoader {
           String host;
           int port;
           public Class findClass(String name) {	//根据类的名字找到这个类
               byte[] b = loadClassData(name);
               return defineClass(name, b, 0, b.length);
           }

           private byte[] loadClassData(String name) {	//将真正类的数据以byte[]字节数组返回
               // load the class data from the connection
                . . .
           }
   }

Binary names(二进制名称:这里对应的是第一段的(The class ClassLoader is an abstract class. Given the binary name of a class)如果看的是JavaDocumentation文档有相关的链接可以从第一段跳转至这里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vhCUBvsT-1581842930279)(E:\Typora\图片\2020-02-16.01.png)]

Any class name provided as a String parameter to methods in ClassLoader must be a binary name as defined by The Java™ Language Specification.(作为字符串参数提供给类加载器中方法的任何类名必须是由Java语言规范定义的二进制名称。
Examples of valid class names include:(有效类名的示例包括:
“java.lang.String”(普通的二进制名字
"javax.swing.JSpinner D e f a u l t E d i t o r " ( ∗ ∗ DefaultEditor"(** DefaultEditor"表示的是DefaultEditor是JSpinner的内部类**)
“java.security.KeyStore B u i l d e r Builder BuilderFileBuilder$1”(Builder是KeyStore的内部类FileBuilder是Builder的内部类1是FileBuilder的第一个匿名内部类
“java.net.URLClassLoader$3$1”(URLClassLoader的第三个匿名类中的第一个匿名内部类

Since:
1.0
See Also:
resolveClass(Class)

案列1

Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime. The class loader for an array class, as returned by Class.getClassLoader() is the same as the class loader for its element type; if the element type is a primitive type, then the array class has no class loader.(数组类的类对象不是由类加载器创建的,而是根据Java运行时的要求自动创建的。由Class.getClassLoader()返回的数组类的类加载器与其元素类型的类加载器相同;如果元素类型是基元类型,那么数组类没有类加载器。

public class Array1 {
    public static void main(String[] args) {
        String[] strings=new String[5];
        System.err.println(strings.getClass());
        System.err.println(strings.getClass().getClassLoader());

    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R3Kk82yS-1581842930280)(E:\Typora\图片\2020-02-16.02.png)]

这里的String字符串输出为null所以String[]输出肯定也为null,是有Bootstrap ClassLoader(根类加载器)$JAVA_HOME中jre/lib/rt.jar里所有的class因为String是rt.jar里面的class文件,大家可以看看这句翻译(null in such implementations if this class was loaded by the bootstrap 如果此类是由引导程序加载的,则在此类实现中为空)这句话是getClassLoader()里面Doc文档说明的。

更改代码

public class Array1 {
    public static void main(String[] args) {
       /* String[] strings=new String[5];
        System.err.println(strings.getClass());
        System.err.println(strings.getClass().getClassLoader());*/
        System.err.println("-------------------");
        Array1[] array1s=new Array1[5];
        System.err.println(array1s.getClass());
        System.err.println(array1s.getClass().getClassLoader());
    }
} 	

运行结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HPkVp66M-1581842930280)(E:\Typora\图片\2020-02-16.03.png)]

Array1对应的是AppClassLoader类加载器所以Array1[]对应的也是AppClassLoader类加载器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值