手写一个类加载器demo

摘要:
jvm启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式加载和显示加载。如果没有加载过,则询问上一层加载器是否已经加载过。依次类推,最后到自定义类加载器指定的路径还没有找到Test.class字节码,则抛出异常ClassNotFoundException。

1、什么是类加载器?

手写一个类加载器demo第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%libext目录下的jar包和class文件。也可以通过System.out.println(System.getProperty("java.ext.dirs"))查看加载类文件的路径。

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

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

4、继承关系手写一个类加载器demo第2张

手写一个类加载器demo第3张

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。如下图:

手写一个类加载器demo第4张

7、自定义loaderclass

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

手写一个类加载器demo第5张

手写一个类加载器demo第6张

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

手写一个类加载器demo第7张

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

//继承ClassLoader类,重写findclass方法。
public class MyClassloader extendsClassLoader {

  privateString path;
  privateString classloaderName;

  publicMyClassloader(String path,String classloaderName){
    this.path =path;
    this.classloaderName =classloaderName;
  }

  //用于寻找类文件
@Override
  publicClass findClass(String name){
    byte[] b =loadClassData(name);
    return defineClass(name,b,0,b.length);
  }

  public byte[] loadClassData(String name) {
    name = path + name + ".class";
    InputStream in = null;
    ByteArrayOutputStream out = null;

    try{
      in = new FileInputStream(newFile(name));
      out = newByteArrayOutputStream();
      int i = 0;
      while ((i = in.read()) != -1){
      out.write(i);
      }
    } catch(Exception e) {
      e.printStackTrace();
    }finally{
      try{
        out.close();
        in.close();
      } catch(IOException e) {
        e.printStackTrace();
      }
    }
    returnout.toByteArray();
  }
}

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

public classClassLoderCheck {

  public static voidmain(String[] args)
      throwsIllegalAccessException, InstantiationException, ClassNotFoundException {
    MyClassloader classloader = new MyClassloader("D:/jvm/", "myclasscloderz");
    Class c = classloader.loadClass("World");
    System.out.println(c.getClassLoader());
    System.out.println(c.getClassLoader().getParent());
    System.out.println(c.getClassLoader().getParent().getParent());
    c.newInstance();
  }
}

运行结果为:

手写一个类加载器demo第8张

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

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

免责声明:文章转载自《手写一个类加载器demo》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux中的LVM逻辑卷管理(转载)<QT>将matplotlib图形嵌入到PySide2界面中下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

svn常见问题汇总

要添加到版本库,必须更新工作副本中的文件。5.更新时,系统会提示您文件冲突,将工作副本中的文件与服务器中的文件进行比较“当版本管理系统更改计算机上的工作副本时”,它会尝试将您的意图写入计算机上的日志文件,因此日志文件记录可能与您的上次工作状态不一致。Subversion客户端将在提交内容之前在本地工作副本中写入日志。首先删除隐藏文件夹中tmp下的临时文件。服...

Ubuntu 18.04 安装微信(附企业微信)

Ubuntu软件市场也是有的,所以安全性不用担心开源地址:https://github.com/geeeeeeeeek/electronic-wechat下面介绍几种安装的方式:1.直接解压运行先选择你系统版本:解压一下:tar-zxvfxxx.tar.gz算了,还是简单为新手分析一下==》tar命令可以解包.tar和.tar.gz。为啥我的没有微信图标?...

Vue跨层级传递slot的方法

但是我需要通过插槽在父组件中指定一个模板,而B组件引用C组件。组件C的部分模板需要在组件A中配置。模板引用A组件:{{node.text}}<模板引用B组件:spanslot=“nodeMenu”slot scope=“{node}”>node=“node”>/span>/div>2.2如...

Vue浏览器调试工具VueTools安装以及使用

ue-devtools是一款基于chrome浏览器的插件,用于vue应用的调试,这款vue调试神器可以极大地提高我们的调试效率。vue-devtools使用起来还是比较简单的,上手非常的容易,这里就细讲其使用说明了。安装方法二:这里以chrome浏览器为例:1、打开chrome网上应用店,搜索vue.js注:如果打不开页面需要代理选择第一个,点击添加至chr...

matlab中figure 创建图窗窗口

示例figure将f指定的图窗作为当前图窗,并将其显示在其他所有图窗的上面。figure;同时使用多个图窗创建两个图窗,然后创建一个线图。f1=figure;f2=figure;plot;将当前图窗设置为f1,使其成为下一个绘图的目标。figure;scatter;输入参数全部折叠f-目标图窗Figure对象目标图窗,指定为Figure对象。默认情况下,Nu...

iostat

-pdevice|ALL和-x选项互斥。它们用于显示块设备和系统分区的统计信息。您还可以在-p之后指定设备名称,例如#iostat phda或显示所有设备:#iostat pALL-t输出数据时,打印数据收集时间---等待I/O svctm的平均时间:服务时间,从生成IO请求到完成IO的时间。从源代码中可以看出:--完成I/O需求的平均时间*=util---...