前言

学习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

【Java虚拟机7】ClassLoader源码文档翻译的更多相关文章

  1. 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

    目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...

  2. JVM 类加载器ClassLoader源码学习笔记

    类加载 在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 类型可以是Class,Interface, 枚举等. Java虚拟机与程序的生命周期 在如下几种情况下,Java虚拟机 ...

  3. JAVA上百实例源码以及开源项目

    简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级.中级.高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情.执着,对IT的憧憬. ...

  4. JAVA上百实例源码网站

    JAVA源码包1JAVA源码包2JAVA源码包3JAVA源码包4 JAVA开源包1 JAVA开源包2 JAVA开源包3 JAVA开源包4 JAVA开源包5 JAVA开源包6 JAVA开源包7 JAVA ...

  5. Java集合---Array类源码解析

    Java集合---Array类源码解析              ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...

  6. Java IO 之 OutputStream源码

    Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆         瓣:BYSocket FaceBook:BYSocket Twitter   ...

  7. java线程池ThreadPoolExector源码分析

    java线程池ThreadPoolExector源码分析 今天研究了下ThreadPoolExector源码,大致上总结了以下几点跟大家分享下: 一.ThreadPoolExector几个主要变量 先 ...

  8. 《java.util.concurrent 包源码阅读》 结束语

    <java.util.concurrent 包源码阅读>系列文章已经全部写完了.开始的几篇文章是根据自己的读书笔记整理出来的(当时只阅读了部分的源代码),后面的大部分都是一边读源代码,一边 ...

  9. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...

随机推荐

  1. MySQL主主互备不同步的解决方法

    MySQL主主互备不同步 首先在服务器上执行show slave satus;可以看到很多同步的参数: Master_Log_File: SLAVE中的I/O线程当前正在读取的主服务器二进制日志文件的 ...

  2. ELK+kafka+filebeat搭建生产ELFK集群

    文章原文 ELK 架构介绍 集群服务版本 服务 版本 java 1.8.0_221 elasticsearch 7.10.1 filebeat 7.10.1 kibana 7.10.1 logstas ...

  3. java 线程基础篇,看这一篇就够了。

    前言: Java三大基础框架:集合,线程,io基本是开发必用,面试必问的核心内容,今天我们讲讲线程. 想要把线程理解透彻,这需要具备很多方面的知识和经验,本篇主要是关于线程基础包括线程状态和常用方法. ...

  4. MySQL——备份与恢复

    MySQL数据库备份和恢复 --备份类型: 1.热备份(只有InnoDB支持)(不影响业务,最好的方式) 2.冷备份( 阻止用户访问) 3.温备份 --备份方式: 1.逻辑备份(文本表示:SQL语句) ...

  5. Sentry Web 性能监控 - Metrics

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  6. throw关键字

    1.基础用法 2.方法中加合法校验,告知方法的调用者 数组越界判断 3.一切皆为对象,创建的是运行期对象,则可以不处理(throws/try catch),直接交给JVM处理(打印并终止程序) 4.O ...

  7. C# Collection

    数组与集合不同的适用范围: 数组:数组最适用于创建和使用固定数量的强类型化对象. 集合:集合提供更灵活的方式来使用对象组. 与数组不同,你使用的对象组随着应用程序更改的需要动态地放大和缩小. 对于某些 ...

  8. 【C++基础教程】第五课

    上次的作业答案,非常简单. 第一题: 我们需要知道,字符(char类型)在计算机中存储的时候,是把这个字符对应的代码(专业术语叫做编码)进行存储.例如,换行符'\n'的代码就是10,'0'对应的代码就 ...

  9. OpenGL渲染管道,Shader,VAO&VBO&EBO

    OpenGL渲染管线 (也就是)OpenGL渲染一帧图形的流程 以下列举最简单的,渲染一个三角形的流程,你可以将它视为 精简版OpenGL渲染管线 更复杂的流程也仅仅就是:在此基础上的各个流程中 添加 ...

  10. 使用ImageMagick操作gif图

    上篇文章我们已经学习了 GraphicsMagick 中的许多函数,也说过 GraphicsMagick 是 ImageMagick 的一个分支,所以他们很多的函数都是一样的使用方式和效果,相似的内容 ...