Launcher启动类


本文是双亲委派机制的源码分析部分,类加载机制中的双亲委派模型对于jvm的稳定运行是非常重要的
不过源码其实比较简单,接下来简单介绍一下
 
我们先从启动类说起
有一个Launcher类   sun.misc.Launcher;
 
仔细看下这简短的几行注释,可以得到有用的信息
ps:直接IDE里面查看反编译的,看不到注释的,可以下载openJDK查看源码,我的这个版本是openjdk-8-src-b132-03_mar_2014
 
sun.misc.Launcher
这个类是系统用于启动主应用的启动器
 
构造方法 Launcher() 中做了四件事情
创建          扩展          类加载器
创建          应用程序    类加载器
设置ContextClassLoader
如果需要安装安全管理器 security manager
其中launcher是staitc的,所以初始化的时候就会创建对象,也就是触发了构造方法,所以初始化的时候就会执行上面四个步骤
 
ExtClassLoader 和  AppClassLoader  都是Launcher的静态内部类
而且,他们也都是ClassLoader的实现类
 
看下ExtClassLoader的创建中的关键几步
 
也在看下AppClassLoader的创建中的关键几步
 
另外还有
Launcher类中的静态变量
 
你应该可以想得到下面这三个到底是什么东西,如果真不懂,你需要再去研究下
System.getProperty("sun.boot.class.path")
System.getProperty("java.ext.dirs")
System.getProperty("java.class.path")
 
 
 

ClassLoader的构造方法

 
 
前面说过,对于虚拟机来说只有两种类加载器
启动类加载器以及其他所有,而其他所有都是java.lang.ClassLoader的子类
所以想要自定义类加载器,必须要继承实现ClassLoader
而且,我们上面说到的,java给我们提供的AppClassLoader 和 ExtClassLoader 也都是ClassLoader的子类
 
看下ClassLoader的构造方法 和变量parent
你会发现,其实构造方法实际上只有双参数版本这一种
第二个参数为parent,这个parent是一个ClassLoader,  用于记录他的  父    类加载器
 
不管调用哪个构造方法
parent必然会被初始化
要么是你调用带参数的构造方法, 显式指定一个来设置parent
如果你不指定,默认的构造方法,会使用  getSystemClassLoader返回的AppClassLoader  设置parent
 
 
 

ps:
本文中的不少地方,我都在"父类加载器" 的"父 "和"类加载器"中间加了几个空格
千万不要理解成父类加载器  ,<父    类加载器> 指的是类加载器的加载顺序层级结构的优先顺序   而不是平时说的继承关系中的父类 父 意味着他的上一层级
 
getSystemClassLoader 获取AppClassLoader 的过程
 
那么再回头看一眼  应用程序   类加载器的构造
扩展  类加载器作为参数传递给了他,他最终调用的就是ClassLoader 的一个参数的构造方法  
将ExtClassLoader 设置为 AppClassLoader  的parent
 
而ExtClassLoader,他的parent 是null
 
ps:启动  类加载器 是虚拟机的一部分,可能c/c++/java实现的,所以不是java语言的一部分
所以对于java本身来说,可以说他是不存在的,但是JVM是知道他的
所以说,此处为null ,parent为null说明他的父    类加载器是启动类加载器   或者可能就是启动  类加载器本身

loadClass与findClass

想要实现类 加载器,需要继承ClassLoader
并且有两个重要的方法
看下两个重要方法的声明,你可能就感觉出来了,想想public 和 protected都是啥意思?
 
loadClass方法是类加载器执行   加载类逻辑   的方法,包括检查是否已经加载,调用父类加载,失败则自己尝试使用 findClass方法加载
findClass当前类加载器 实际执行加载二进制流的具体行为方法
 
Launcher.APPClassLoader中的loadClass方法,最终调用的是super.loadClass  , 实际上就是ClassLoader的loadClass方法
Launcher.ExtClassLoader  根本就没有实现自己的loadClass 方法,所以使用的也是ClassLoader中的
 
 
再来看看ClassLoader的loadClass方法
他会调用parent的loadClass方法,如果他的parent不为空,将会一直调用父 类加载器, 直到最顶级的  启动   类加载器 
如果 启动   类加载器仍旧找寻不到, 那么调用自身的findClass 
 
如果自己调用findClass加载失败呢?
很显然, 函数调用结束之后,会返回到调用点位置,调用栈的形式嘛
也就是经过
必然要继续执行他的下一段
如果没抛出异常的话,就会走到下面这里
显然这就完成了一整个的双亲委派的类加载模式
 
 

总结

Launcher作为启动器
创建了ExtClassLoader 以及AppClassLoader
他们都是ClassLoader的子类,并且ClassLoader有一个parent  指向他的父   类加载器
正是这个属性完成了自顶而下的 优先级层级顺序的确定
对于sun内置的ExtClassLoader 以及AppClassLoader  以及启动  类加载器 Bootstrap  他们的层级为
Bootstrap>ExtClassLoader>ExtClassLoader
并且,他们各自有不同的分工
通过ClassLoader的loadClass方法,确定了他们的调用逻辑,也就是双亲委派机制
每个层级都会向上传递类加载请求,只有上层  父     类加载器调用失败,才会自己尝试加载
双亲委派机制的意义重大,带来了更高的安全性等优点
不过他的实现逻辑却是的确很简单
一个loadClass就搞定了
findClass是类加载器自身加载类的具体行为
所以,如果你不需要破坏双亲委派机制,只需要覆盖这个方法即可
如果你想要完全自定义你的类加载器的逻辑机制,直接覆盖loadClass,当然,你可能还需要继续覆盖findClass
 
 

[五]类加载机制双亲委派机制 底层代码实现原理 源码分析 java类加载双亲委派机制是如何实现的的更多相关文章

  1. Koa源码分析(三) -- middleware机制的实现

    Abstract 本系列是关于Koa框架的文章,目前关注版本是Koa v1.主要分为以下几个方面: Koa源码分析(一) -- generator Koa源码分析(二) -- co的实现 Koa源码分 ...

  2. dubbo源码分析5-dubbo的扩展点机制

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  3. Android源码分析—深入认识AsyncTask内部机制

    本文转载http://blog.csdn.net/singwhatiwanna/article/details/17596225该博主博文,谢谢该博主提供的好文章! 前言 什么是AsyncTask,相 ...

  4. HashMap在JDK1.8中并发操作,代码测试以及源码分析

    HashMap在JDK1.8中并发操作不会出现死循环,只会出现缺数据.测试如下: package JDKSource; import java.util.HashMap; import java.ut ...

  5. [置顶] Android源码分析-点击事件派发机制

    转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17339857 概述 一直想写篇关于Android事件派发机制的文章,却一直没 ...

  6. Android源码分析-点击事件派发机制

    转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17339857 概述 一直想写篇关于Android事件派发机制的文章,却一直没 ...

  7. 插件开发之360 DroidPlugin源码分析(二)Hook机制

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52124397 前言:新插件的开发,可以说是为插件开发者带来了福音,虽然还很多坑要填补, ...

  8. Kettle 4.2源码分析第四讲--KettleJob机制与Database插件简介(含讲解PPT)

    1.  Job机制 一个job项代表ETL控制流中的一项逻辑任务.Job项将会顺序执行,每个job项会产生一个结果,能作为别的分支上job项的条件. 图 1 job项示例 1.1. Job类图简介 图 ...

  9. RecyclerView 源码分析(二) —— 缓存机制

    在前一篇文章 RecyclerView 源码分析(一) -- 绘制流程解析 介绍了 RecyclerView 的绘制流程,RecyclerView 通过将绘制流程从 View 中抽取出来,放到 Lay ...

随机推荐

  1. 全民https时代,Let's Encrypt免费SSL证书的申请及使用(Tomcat版)

    近几年,在浏览器厂商的强力推动下,HTTPS的使用率大增.据统计,Firefox加载的网页中启用HTTPS的占比为67%,谷歌搜索结果中HTTPS站点占比已达50%,HTTPS网站已获得浏览器和搜索引 ...

  2. 彻底卸载Windows Service

    前言,我使用Quartz.net + quartz.config + quartz_jobs.xml 写了个Windows Service,使用如下bat脚本执行服务的安装,启动,暂停,卸载 @ech ...

  3. es6的基本数据详解

    一.Set 基本用法:   1)ES6提供了新的数据机构-Set. 它类似于数组,但是成员的值都是唯一的,没有重复的值.Set本身是一个构造函数,用来生成Set数据结构. 先来看一段最简单的代码: 1 ...

  4. Java语法细节 - 内存和枚举

    目录 Java申请DirectBuffer ByteBuffer的position,limit,capacity,flip操作之间的关系 枚举实现单例模式 Java申请DirectBuffer /*- ...

  5. C语言复习4_while循环

    1.while循环 循环三要素: 1).循环变量的初值 2).循环变量的判断 3).循环变量的更新 #include <stdio.h> #include <stdlib.h> ...

  6. ASP.NET Core 2.1对GDPR的支持

    欧盟的<通用数据保护条例>(General Data Protection Regulation,以下简称 GDPR)已经于 2018 年 5 月 25 日正式施行.GDPR 涵盖了包括数 ...

  7. JSP的执行原理

    在一个JSP文件第一次被请求时,JSP引擎把该JSP文件转换成为一个Servlet.而这个引擎本身也是一个Servlet.JSP的运行过程如下所示: (1)JSP引擎先把该JSP文件转换成一个Java ...

  8. 从SQL注入到内网漫游

    前言 在一次渗透实战中,发现了一个注入点,最后成功的漫游了内网. 正文 在渗透中遇到一个站点,顺手测试了一下,在搜索框随便输入了一个字符加个单引号直接报错了,差不多可以确认这里存在注入了.一般这种站安 ...

  9. php免杀教程【绝对原创】

    .函数回调. 使用其他函数进行调用,并执行. 如:array_map('a'.'s'.'se'.'r'.'t',array($_POST['x'])); 详细教程 + 测试结果(安全狗+360主机卫士 ...

  10. [Swift]LeetCode724. 寻找数组的中心索引 | Find Pivot Index

    Given an array of integers nums, write a method that returns the "pivot" index of this arr ...