javadoc的解释:

ClassLoader的每一个实例都会有一个与之关联的父ClassLoader,当被要求去寻找一个类或者资源的时候,ClassLoader的实例就会对于类或者是资源的寻找委托给他的父ClassLoader(在他自己尝试找这个类或者资源之前),并层层向上委托。

虚拟机内建的ClassLoader即Bootstrap根类加载器,他本身是没有双亲的,但是他可以作为一个类加载器的双亲。

支持并发加载类的类加载器,被称为 parallel capable class loaders ,被要求在类的初始化期间调用ClassLoader.registerAsParallelCapable()将自身注册为parallelcapableclassloader。 ClassLoader默认是并发类加载器,但他的子类如果是并发的,还依然需要注册。

当境委派模型并不是严格的层次委派模型时,要求类加载器必须是支持并行的类加载器,否则类加载就会导致死锁。因为加载器的锁(loader lock我也不知道咋翻译)在类的加载过程中一直不会释放。

一般来说jvm虚拟机加载类来源于本地文件系统(与操作系统跟平台相关),但也可能来源于其他资源,比如网络,或者运行时的动态生成。

在这种情况下,加载类的方法会把一个字节数组(调用 loadClassData() 返回byte[] ,通过defineClass(byte[])转为一个Class)转换为一个class对象,通过Class.newInstance 来创建对应对象。

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

}
}

由类加载器创建的对象,其方法或者构造器可能引用了其他未加载的类,为了确定这些引用是什么(注意这些引用对应的类还未被装入,需要确定这些引用是什么) jvm虚拟机会调用加载这个类的class的classloader 来加载这些引用(再次跳入第一步 开始递归)

1.获取ClassLoader

 public class MyTest06 {

     public static void main(String[] args) {
String str = new String("212");
C c = new C();
System.out.println(str.getClass().getClassLoader());
System.out.println(c.getClass().getClassLoader());
} }
class C{ }//out: null
sun.misc.Launcher$AppClassLoader@2a139a55

第二个返回值说明自定义类C是由AppClassLoader 系统类加载器加载

第一个返回值说明String由Bootstrap根加载器加载

/** 如下是源码中对 getClassLoader() 方法的说明
* Returns the class loader for the class. Some implementations may use
* null to represent the bootstrap class loader. This method will return
* null in such implementations if this class was loaded by the bootstrap
* class loader.
* 如果类由bootstrap class loader加载 这个方法会返回null在一些jvm实现中
*
* <p> If a security manager is present, and the caller's class loader is
* not null and the caller's class loader is not the same as or an ancestor of
* the class loader for the class whose class loader is requested, then
* this method calls the security manager's {@code checkPermission}
* method with a {@code RuntimePermission("getClassLoader")}
* permission to ensure it's ok to access the class loader for the class.
*
* <p>If this object
* represents a primitive type or void, null is returned.
*
* @return the class loader that loaded the class or interface
* represented by this object.
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method denies
* access to the class loader for the class.
* @see java.lang.ClassLoader
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/

2.ClassLoader.loadClass()方法与Class.forName()方法

class CL{
static {
System.out.println("class cl");
}
}
public class MyTest07 { public static void main(String[] args) throws Exception {
ClassLoader clazzloader = ClassLoader.getSystemClassLoader();
Class<?> clazz = clazzloader.loadClass("jvm.CL");
System.out.println("==================================");
System.out.println(clazz);
System.out.println("==================================");
Class<?> clazz2 = Class.forName("jvm.CL");
System.out.println("==================================");
System.out.println(clazz2);
} }//out:
==================================
class jvm.CL
==================================
class cl
==================================
class jvm.CL

loadclass 只加载对应类,forName 会一并将类初始化

不过调用 clazz.newInstance()会初始化该类:

public class MyTest07 {

	public static void main(String[] args) throws Exception {
ClassLoader clazzloader = ClassLoader.getSystemClassLoader();
Class<?> clazz = clazzloader.loadClass("jvm.CL");
System.out.println("==================================");
System.out.println(clazz);
System.out.println("==================================");
clazz.newInstance();
System.out.println("==================================");
Class<?> clazz2 = Class.forName("jvm.CL");
System.out.println("==================================");
System.out.println(clazz2);
} }out:
==================================
class jvm.CL
==================================
class cl
==================================
==================================
class jvm.CL

  

3.HotSpot实现中用null代替根加载器Bootstrap

public class MyTest08 {

	public static void main(String[] args) {
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);
while(classloader!=null) {
classloader= classloader.getParent();
System.out.println(classloader);
}
} }//out:
sun.misc.Launcher$AppClassLoader@2a139a55
sun.misc.Launcher$ExtClassLoader@7852e922
null

4.数组的classloader,数组是JVM在运行时动态生成的类型,没有类加载器,如果调用getClassLoader会返回对应元素的类加载器。

public class MyTest09 {

	public static void main(String[] args) {
String[] strs = new String[2];
System.out.println(strs.getClass().getClassLoader()); System.out.println("============================"); MyTest09[] ms = new MyTest09[2];
System.out.println(ms.getClass().getClassLoader()); System.out.println("============================"); int[] ints = new int[2];
System.out.println(ints.getClass().getClassLoader());
} }//out:
null
============================
sun.misc.Launcher$AppClassLoader@2a139a55
============================
null

其中String类型的类加载器是Bootstrap 在HotSpot实现中被表现为null

源生类型则没有类加载器。

5.类加载器一般都会伴随一个安全管理器,来确保类加载过程中是安全的

JVM(三、双亲委派机制)的更多相关文章

  1. jvm双亲委派机制详解

    双亲委派机制 ​ 记录一下JVM的双亲委派机制学习记录. 类加载器种类 ​ 当我们运行某一个java类的main方法时,首先需要由java虚拟机的类加载器将我们要执行的main方法所在的class文件 ...

  2. 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

    一.概述   定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的 ...

  3. JVM加载类的过程,双亲委派机制中的方法

    JVM加载类的过程: 1)JVM中类的整个生命周期: 加载=>验证=>准备=>解析=>初始化=>使用=>卸载  1.1.加载 类的加载阶段,主要是获取定义此类的二进 ...

  4. 说一说JVM双亲委派机制与Tomcat

    双亲委派模型与JVM 类加载 讲个故事: 以前,爱捣鼓的小明突然灵机一动,写出了下面的代码 package java.lang; public class String { //...复制真正Stri ...

  5. [转帖]说一说JVM双亲委派机制与Tomcat

    说一说JVM双亲委派机制与Tomcat https://www.cnblogs.com/dengchengchao/p/11844022.html 讲个故事: 以前,爱捣鼓的小明突然灵机一动,写出了下 ...

  6. JVM类加载与双亲委派机制被打破

    前言 前文已经讲了虚拟机将java文件编译成class文件后的格式:JVM虚拟机Class类文件研究分析 java文件经过编译,形成class文件,那么虚拟机如何将这些Class文件读取到内存中呢? ...

  7. 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)

    一.JVM内存结构 ▷ 谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期.数据共享:是否GC.是否OOM 答:jvm 内存结构包括程序计数器.虚拟机栈.本地方法栈.堆.方法区:它是字节码运行时 ...

  8. JVM学习六:JVM之类加载器之双亲委派机制

    前面我们知道类加载有系统自带的3种加载器,也有自定义的加载器,那么这些加载器之间的关系是什么,已经在加载类的时候,谁去加载呢?这节,我们将进行讲解. 一.双亲委派机制 JVM的ClassLoader采 ...

  9. JVM之类加载器、加载过程及双亲委派机制

    JVM 的生命周期 虚拟机的启动 Java 虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实 ...

  10. 深入探究JVM之类加载与双亲委派机制

    @ 目录 前言 类的生命周期 加载 验证 准备 解析 初始化 案例一 案例二 案例三 案例四 类加载器 类加载器和双亲委派模型 破坏双亲委派模型 第一次 SPI Tomcat OSGI 总结 前言 前 ...

随机推荐

  1. wso2 使用配置

    1.下载wso2 https://docs.wso2.com 2.配置 https://172.10.0.59:9443/publisher https://172.10.0.59:9443/carb ...

  2. Keep、小红书、美图…独角兽App能拿到新一轮救命钱吗?

    大多数人热爱手机,不是因为时尚的外观或者结实的零部件,而是因琳琅满目的App赋予其太多的功能.智能手机最先是清理掉人类的零碎时间,现如今又开始肢解我们大块的时间,或者说,智能手机本身就是生活.在如此背 ...

  3. Java基本语法--控制台输入(Scanner类)

    通过Scanner类获取用户输入时,控制台会一直等待用户的输入,可以输入不同类型的值.本篇博客主要讲解从控制台输入值,即Scanner类的使用方法. Api文档中关于Scanner类的构造方法 键盘输 ...

  4. linux分区命令parted的用法

    parted的适用场景 创建操作大于2T的分区 一般情况下,我们都是选择使用fdisk工具来进行分区,但是目前在实际生产环境中使用的磁盘空间越来越大,呈TiB级别增长:而常用的fdisk这个工具对分区 ...

  5. jQuery图片剪裁插件Cropper.js的使用

    插件下载地址及文档说明 1.引入必要的js和css核心文件 <link rel="stylesheet" href="../css/cropper.css" ...

  6. react中用swiper实现大图功能

    1.引入Swiper(用的是4.5.0版本)      import Swiper from 'swiper';      //引入样式,还可以加上自己的样式      import '../../s ...

  7. 虚拟机win7 安装过程中遇到虚拟工具安装失败

    如果遇见这样的问题 倘若你用的是这样的镜像:cn_windows_7_enterprise_x64_dvd_x15-70741.iso 换镜像源.换镜像源.换镜像源! 换成带sp1的iso镜像:cn_ ...

  8. Centos7部署jenkins

    1.       下载rpm包: a)         下载地址:https://pkg.jenkins.io/redhat-stable/ b)         点选一个下载即可,例如点选:“jen ...

  9. python3练习100题——018

    原题链接:http://www.runoob.com/python/python-exercise-example18.html 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个 ...

  10. goto语句的本质

    除非跳出多个循环嵌套和远程注入技术,否则尽量少用goto goto会降低程序的可读性,让代码难以调试 利用递归也可以实现循环结构和do while类似 #define _CRT_SECURE_NO_W ...