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. C++——流类库与输入/输出

    I/O流的概念 当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象,流是一种抽象,它负责在数据的生产者和数据的消费者之间建立连接,并管理数据的流动.程序建立一个流对象 ...

  2. C++——动态内存分配1

    9.动态内存分配  new 类型名T(初值列表) 其功能是在程序执行期间申请用于存放T类型对象的内存空间,并依初值列表赋以初值,结果值:成功则T类型的指针,指向新分配的内存:失败则为0(null).若 ...

  3. Virtual DOM(八)

    Virtual DOM 这个概念相信大部分人都不会陌生,它产生的前提是浏览器中的 DOM 是很“昂贵"的,为了更直观的感受,我们可以简单的把一个简单的 div 元素的属性都打印出来,如图所示 ...

  4. 0120 springboot集成Mybatis和代码生成器

    在日常开发中,数据持久技术使用的架子使用频率最高的有3个,即spring-jdbc , spring-jpa, spring-mybatis.详情可以看我之前的一篇文章spring操作数据库的3个架子 ...

  5. 解决安装完Anaconda后右键没有powershell、、、

    法一: win+R 打开资源管理 输入powershell.exe 法二: 额,,按住 shift 再右键...嘿嘿嘿

  6. P3391 【模板】文艺平衡树

    模板题 link Splay 区间翻转,存个代码 旋转时,要注意goal是引用 , 并记得修改 , 有标记的一定记得标记下放 , 还有清空 #include<iostream> #incl ...

  7. 白面系列 nginx

    Nginx == engine x. nginx就是一个服务器.主要提供web服务.负载均衡(反向代理).web缓存等服务. nginx ≈ apache,但nginx是轻量级的高性能高并发的服务器. ...

  8. MAC MAMP集成环境安装 PHP 扩展

    MAC MAMP集成环境安装 PHP扩展 开发环境中,对于需要维护很多 WEB 站点,以及可能会使用到很多不同的 PHP 版本,集成环境比较好用,在MAC 上 MAMP 集成环境是比较好用的,但是在安 ...

  9. Joining Data with dplyr in R

    目录 inner_join Joining three tables left_join right-join full_join semi- and anti-join Stack Overflow ...

  10. 常用excel函数公式及操作示例

    一.数字处理 1.取绝对值 =ABS(数字) 2.取整 =INT(数字) 3.四舍五入 =ROUND(数字,小数位数) 二.判断公式 1.把公式产生的错误值显示为空 公式:C2 =IFERROR(A2 ...