1、什么是类加载器?

2、加载方式

ClassLoader类加载器,主要的作用是将class文件加载到jvm虚拟机中。jvm启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式加载和显示加载。

隐式加载:程序代码中不通过调用ClassLoader来加载需要的类,而是通过JVM类自动加载需要的类到内存中。例如,当我们在类中继承或者引用某个类的时候,

JVM在解析当前这个类的时,发现引用的类不在内存中,那么就会自动将这些类加载到内存中。

显示加载:代码中通过Class.forName(),this.getClass.getClassLoader.LoadClass(),自定义类加载器中的findClass()方法等。

显示加载的时候,当我们获取到class对象之后,需要调用class对象的new instans()生成实例。

3、类加载器的种类及作用

(1)BootStrap ClassLoader:主要加载%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。可以通System.getProperty("sun.boot.class.path")

(2)Extention ClassLoader:主要加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。也可以通过System.out.println(System.getProperty("java.ext.dirs"))查看加载类文件的路径。

(3)AppClassLoader:主要加载当前应用下的classpath路径下的类。之前我们在环境变量中配置的classpath就是指定AppClassLoader的类加载路径。

(4)用户自定义类加载器

4、继承关系

5、双亲委派机制

例如:当jvm要加载Test.class的时候,

  (1)首先会到自定义加载器中查找,看是否已经加载过,如果已经加载过,则返回字节码。

  (2)如果自定义加载器没有加载过,则询问上一层加载器(即AppClassLoader)是否已经加载过Test.class。

  (3)如果没有加载过,则询问上一层加载器(ExtClassLoader)是否已经加载过。

  (4)如果没有加载过,则继续询问上一层加载(BoopStrap ClassLoader)是否已经加载过。

  (5)如果BoopStrap ClassLoader依然没有加载过,则到自己指定类加载路径下("sun.boot.class.path")查看是否有Test.class字节码,有则返回,没有通

知下一层加载器ExtClassLoader到自己指定的类加载路径下(java.ext.dirs)查看。

  (6)依次类推,最后到自定义类加载器指定的路径还没有找到Test.class字节码,则抛出异常ClassNotFoundException。如下图:

7、自定义loaderclass

(1)新建一个java文件,保存在相应的目录。

(2)用cmd命令进入到world类的上级目录,运行javac命令,生成.class文件。

(3)创建自己定义的classload类。

  1. //继承ClassLoader类,重写findclass方法。
  2. public class MyClassloader extends ClassLoader {
  3.  
  4. private String path;
  5. private String classloaderName;
  6.  
  7. public MyClassloader(String path,String classloaderName){
  8. this.path = path;
  9. this.classloaderName = classloaderName;
  10. }
  11.  
  12. //用于寻找类文件
  13. @Override
  14. public Class findClass(String name){
  15. byte[] b =loadClassData(name);
  16. return defineClass(name,b,0,b.length);
  17. }
  18.  
  19. public byte[] loadClassData(String name) {
  20. name = path + name + ".class";
  21. InputStream in = null;
  22. ByteArrayOutputStream out = null;
  23.  
  24. try {
  25. in = new FileInputStream(new File(name));
  26. out = new ByteArrayOutputStream();
  27. int i = 0;
  28. while ((i = in.read()) != -1){
  29. out.write(i);
  30. }
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }finally {
  34. try {
  35. out.close();
  36. in.close();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. return out.toByteArray();
  42. }
  43. }

(4)创建测试类,测试结果。

  1. public class ClassLoderCheck {
  2.  
  3. public static void main(String[] args)
  4. throws IllegalAccessException, InstantiationException, ClassNotFoundException {
  5. MyClassloader classloader = new MyClassloader("D:/jvm/", "myclasscloderz");
  6. Class c = classloader.loadClass("World");
  7. System.out.println(c.getClassLoader());
  8. System.out.println(c.getClassLoader().getParent());
  9. System.out.println(c.getClassLoader().getParent().getParent());
  10. c.newInstance();
  11. }
  12. }

运行结果为:

自定义类加载器的作用:jvm自带的三个加载器只能加载指定路径下的类字节码。如果某个情况下,我们需要加载应用程序之外的类文件呢?比如本地D盘下的,或者去加载网络上的某个类文件,这种情况就可以使用自定义加载器了。

参考网址:cnblogs.com/gdpuzxs/p/7044963.html

手写一个类加载器demo的更多相关文章

  1. 手把手教你手写一个最简单的 Spring Boot Starter

    欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...

  2. 浅析MyBatis(二):手写一个自己的MyBatis简单框架

    在上一篇文章中,我们由一个快速案例剖析了 MyBatis 的整体架构与整体运行流程,在本篇文章中笔者会根据 MyBatis 的运行流程手写一个自定义 MyBatis 简单框架,在实践中加深对 MyBa ...

  3. Atiit 如何手写词法解析器

    Atiit 如何手写词法解析器 1.1. 通过编程直接从正则->nfa->dfa->表驱动词法解析一条龙自动生成.那是用程序自动生成是需要这样的,自己手写完全不必要这么复杂1 1.2 ...

  4. 实现简单的手写涂鸦板(demo源码)

    在一些软件系统中,需要用到手写涂鸦的功能,然后可以将涂鸦的结果保存为图片,并可以将"真迹"通过网络发送给对方.这种手写涂鸦功能是如何实现的了?最直接的,我们可以使用Windows提 ...

  5. 放弃antd table,基于React手写一个虚拟滚动的表格

    缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...

  6. 利用SpringBoot+Logback手写一个简单的链路追踪

    目录 一.实现原理 二.代码实战 三.测试 最近线上排查问题时候,发现请求太多导致日志错综复杂,没办法把用户在一次或多次请求的日志关联在一起,所以就利用SpringBoot+Logback手写了一个简 ...

  7. 手写一个简单的ElasticSearch SQL转换器(一)

    一.前言 之前有个需求,是使ElasticSearch支持使用SQL进行简单查询,较新版本的ES已经支持该特性(不过貌似还是实验性质的?) ,而且git上也有elasticsearch-sql 插件, ...

  8. 看年薪50W的架构师如何手写一个SpringMVC框架

    前言 做 Java Web 开发的你,一定听说过SpringMVC的大名,作为现在运用最广泛的Java框架,它到目前为止依然保持着强大的活力和广泛的用户群. 本文介绍如何用eclipse一步一步搭建S ...

  9. 剖析手写Vue,你也可以手写一个MVVM框架

    剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...

随机推荐

  1. 西安邀请赛-D(带权并查集+背包)

    题目链接:https://nanti.jisuanke.com/t/39271 题意:给定n个物品,m组限制,每个物品有个伤害值,现在让两个人取完所有物品,要使得两个人取得物品伤害值之和最接近,输出伤 ...

  2. bochs 2.6.8 常用命令集合

    b addr 在物理地址处设置断点 addr为物理内存地址,不加段基址 lb 在线性地址处设置断点  addr为线性物理地址,不加基址 vb 在虚拟地址上设置断点 addr为段基址:偏移地址, cs段 ...

  3. Linux在线安装MongoDB

    Mongo官网安装地址: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/ 以MongoDB3.4为例 1.创建 ...

  4. 说一下redis中5种数据类型的底层数据结构

      前言: 阅读 redis设计与实现 一书的记录.未完待续... redis我们都知道有5种数据类型,分别是string,list,hash,set,zset,那么你知道它们的底层数据结构实现吗? ...

  5. C中的函数指针的用法

    include<stdio.h> typedef int (*Cal)(int a,int b);//定义一个函数指针,第一个int是指向函数的返回值的类型,后面括号里面的两个int是指指 ...

  6. 098、Swarm 如何实现 Failover (Swarm05)

    参考https://www.cnblogs.com/CloudMan6/p/7898245.html   故障是在所难免的,容器可能崩溃,Docker Host 可能宕机,不过幸运的是,Swarm 已 ...

  7. mybatis-plus简单了解

    mybatis-plus入门了解和简单使用 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 特性: ...

  8. mybatis字符#与字符$的区别

    问题:使用in查询查询出一批数据,in查询的参数是字符串拼接的.调试过程中,把mybatis输出的sql复制到navicat中,在控制台将sql的参数也复制出来,替换到sql的字符 '?' 的位置,执 ...

  9. react如何通过shouldComponentUpdate来减少重复渲染

    转自:https://segmentfault.com/a/1190000016494335 在react开发中,经常会遇到组件重复渲染的问题,父组件一个state的变化,就会导致以该组件的所有子组件 ...

  10. java 枚举enum的使用(与在switch中的使用)

    实际开发中,很多人可能很少用枚举类型.更多的可能使用常量的方式代替.但枚举比起常量来说,含义更清晰,更容易理解,结构上也更加紧密.看其他人的博文都很详细,长篇大论的,这里理论的东西不说了,一起看看在实 ...