前言
学习JVM类加载器,ClassLoader这个类加载器的核心类是必须要重视的。
Notes:下方蓝色文字是自己的翻译(如果有问题请指正)。黑色文字是源文档。红色文字是自己的备注。
ClassLoader类源码文档
public abstract class ClassLoader extends Object
类加载器是一个负责加载类的对象。
A class loader is an object that is responsible for loading classes.
类"ClassLoader"是一个抽象类。
The class ClassLoader is an abstract class.
给定一个类的“binary name”(下方有binary name的解释),类加载器应该尝试定位或生成一些构成类定义的数据。(这里生成是因为可以动态生成类的定义。)
Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class.
一种典型的策略是将这个给定的二进制名字转换成一个文件系统的名字,然后去读取这个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.
每一个Class对象都包含一个加载它的ClassLoader的引用。(如String.class.getClassLoader()
)
Every Class object contains a reference to the ClassLoader that defined it.
数组类的Class对象不是被class loader创建的,而是被Java运行时环境自动创建的。
Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime.
对于数组类型的class loader对象是和数组内部的element类型的class loader是同一个。(比如说String[]的类加载器就等于String的类加载器,同为根类加载器。)
The class loader for an array class, as returned by Class.getClassLoader() is the same as the class loader for its element type;
如果数组中的元素是一个原始类型,那么这个数组是没有class loader的。
if the element type is a primitive type, then the array class has no class loader.
客户应用可以实现ClassLoader类来扩展一种JVM动态加载类的方式。(这句话就是自定义加载器的作用,你自己写类加载器就是用来动态加载类的)
Applications implement subclasses of ClassLoader in order to extend the manner in which the Java virtual machine dynamically loads classes.
类加载器一般会被security managers所使用,用来标识一些安全域范围。
Class loaders may typically be used by security managers to indicate security domains.
ClassLoader类使用了一种委托模型来寻找类和资源。
The ClassLoader class uses a delegation model to search for classes and resources.
ClassLoader类的每一个实例都会有一个与之关联的parent class loader
Each instance of ClassLoader has an associated parent class loader.
当我们向一个class loader发起请求查找一个class或者资源的时候,在这个ClassLoader查找之前,它会先将这个查找请求委托给它的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.
虚拟机内嵌的类加载器,我们称为"bootstrap class loader",它没有parent class loader,但是它可以作为其他类加载器的双亲。
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.
支持并行的类加载器称为"parallel capable class loaders",它被要求在它自己初始化期间,它需要通过调用ClassLoader.registerAsParallelCapable()方法来把自己注册成并行类加载器。
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.
ClassLoader类默认被注册成为一个"parallel capable class loaders"
Note that the ClassLoader class is registered as parallel capable by default.
但是,它的子类依然需要自己注册成"parallel capable class loaders"
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).
通常情况下,JVM是以一种平台无关的从本地文件系统加载类。例如,在UNIX系统中,虚拟机从CLASSPATH环境变量中加载类。
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.
然后,有些类并不是来自于文件系统,而是来自于其他地方,如网络或者其二进制码是由应用自己生成的。
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.
在这种情况下,"defineClass"会将字节数组转换为一个Class类的实例。这个新定义的类的实例是可以由Class.newInstance来创建的。
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.
由类加载创建的对象的方法和构造器可能会引用其他类。
The methods and constructors of objects created by a class loader may reference other classes.
为了确认“被引用的类”(假设为A类)都是什么类,虚拟机会调用创建这个类的class loader的loadClass方法,来加载这个类。
To determine the class(es) referred to, the Java virtual machine invokes the loadClass method of the class loader that originally created the class.
上面2句比较难以理解,举个例子,一个MySample类的构造器和一个MyCat类的构造器方法中,本没有关系,new MySample()中会new MyCat(),此时就是MySample引用了MyCat类。
所以这里“被引用的类”就是MyCat,MySample会先被加载,然后加载MyCat的时候,JVM会使用MySample的类加载器来加载MyCat。
例如,一个应用可以创建一个网络类加载器来从远程服务器下载字节码文件。
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);
Object main = loader.loadClass("Main", true).newInstance();
...
network class loader必须要定义findClass和loadClassData方法来从网络上加载类。
The network class loader subclass must define the methods findClass and loadClassData to load a class from the network.
一旦下载字节码文件完成,需要调用defineClass来创建一个Class类实例。
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:
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) {
// load the class data from the connection
. . .
}
}
Binary names
对ClassLoader类中的方法参数来说,如果这个参数是代表class名字,那么这个名字必须是一个binary name(二进制名字)。这个二进制名字是被JLS定义的。
Any class name provided as a String parameter to methods in ClassLoader must be a binary name as defined by The Java™ Language Specification.
如下:binary name(二进制名字)类名需要给全路径,中间用点号分割,如果有内部类使用"$"分割,如果有匿名内部类,按顺序使用"$ + 数字"代表
Examples of valid class names include:
"java.lang.String"
"javax.swing.JSpinner$DefaultEditor"
"java.security.KeyStore$Builder$FileBuilder$1"
"java.net.URLClassLoader$3$1"
ClassLoader方法源码文档
getSystemClassLoader()
返回一个用于委托的系统类加载器。它是新的ClassLoader实例的默认的委托双亲,它通常是用来启动应用的类加载器。
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.
getSystemClassLoader()这个方法最早在JVM运行时的启动阶段中被第一次调用,在此调用时,它会创建系统类加载器并且会将它设置为调用这个方法的当前线程的上下文类加载器。
这也是为什么:Thread.currentThread().getContextClassLoader()用来获取当前线程上下文的ClassLoader,一般为系统类加载器。
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.
当这个方法第一次被调用的时候,如果系统属性“java.system.class.loader”被定义了,那么这个属性的值就会被作为系统类加载器的名字了。
“java.system.class.loader”这个被设置的值肯定是一个类的二进制名。我称它为“被设置的系统类加载器类”。
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.
“被设置的系统类加载器类”是被默认系统类加载器加载的,这个“被设置的系统类加载器类”必须定义一个public的接受一个ClassLoader参数的构造器,这个参数的值会被作为委托双亲。
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.
接下来一个实例会被默认的系统类加载器调用刚才那个构造器创建。得到的class loader就会被定义为系统类加载器。
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"修改系统类加载器。这是虚拟机提供给我们的一个功能。
系统属性"java.system.class.loader"默认是null,没有定义。
如果存在安全管理器,并且调用方的类加载器不为null,并且调用方的类加载器与系统类加载器不同或没有双亲的关系,则此方法使用RuntimePermission(“getClassLoader”)权限调用安全管理器的checkPermission方法,以验证对系统类加载器的访问。否则,将抛出SecurityException。
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.
返回值:双亲委托的系统类加载器,或者是null。
Returns:
The system ClassLoader for delegation, or null if none