博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jvm学习三:自定义ClassLoader
阅读量:4311 次
发布时间:2019-06-06

本文共 2647 字,大约阅读时间需要 8 分钟。

第一节我们说过一句话:所有的Java虚拟机实现必须在每个类或接口被Java程序“ 首次主动使用”时才初始化他们

但类加载器却不是这样:类加载器不需要等到某个类“被首次主动使用”时才加载

两句话的区别就在于红线标注的地方,所以我们要明确一点ClassLoader只负责类的加载,即 加载  》 连接 》初始化 的第一步

由上一节我们知道,jvm有三种加载器,每种加载器负责特定目录的类。根类加载器(BootStrap)和扩展加载器(Extension)不必说,它们负责加载的都是特定目录的类,而且这些类是固定的,我们不能说我们把自己编写的类加到java.lang目录下就能使这个类被根类加载器加载,那样就太不安全了。因为加载的类是固定的就很好理解,但是系统类加载器(System)就比较不好理解了,它是加载classpath定义的目录下的类。而且我们知道classpath路径是可以自定义的,也就是说它可以加载任意目录的类,只要我们在classpath下指定了该目录。

比如我们安装好jdk配置好环境变量之后,我们就可以在任意位置使用javac命令和java命令,但是你有没有想过,我们并没有指定类加载的路径,为什么我们在任何地方都能加载到目标类文件呢。原因很简单就是环境变量的配置,我们一般回配置两个参数path和classpath。path的作用是让我们在任意目录下都能找到javac和java命令,但是单单找到命令是不够的,有命令没有类文件一样白搭,所以classpath的设置就是帮我们找到类文件,classpath一般这样设置     .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar  。注意最开始的那个点,最不起眼却最重要,它代表当前文件夹,当我们在一个很偏僻的文件夹使用javac命令编译java文件,这个文件夹就是我们工作的当前文件夹,jvm就会到path下去寻找javac命令,path配置正确找到命令。然后到classpath下去寻找class文件,然后就发现了  "  .  " ,于是就会到当前文件夹下寻找,一下就找到了,类编译就完成了,java命令一样。

现在系统类加载器(System)已经很清楚了。那我们能不能自己编写自己的类加载器呢,答案是肯定的,当然,类加载很复杂,要我们从零做起是不现实的,我们只能根据已有的类加载器进行包装,定制自己的ClassLoader

自定义类加载器分为以下几个步骤:

1、定义类。继承ClassLoader

2、重写ClassLoader的 findClass方法
就是这么简单,下面是我自己写的自定义类加载器例子
 
 
public class MyClassLoader extends ClassLoader{    private String path;   //类的加载路径    private String name;   //类加载器的名字    public MyClassLoader() {}    public MyClassLoader(String path,String name){        this.path = path;        this.name = name;    }    //用于寻找类文件    public Class findClass(String name) {        byte[] b = loadClassData(name);        return defineClass(name, b, 0, b.length);    }    //用于加载类文件    private byte[] loadClassData(String name) {        name = path + name + ".class";             //使用输入流读取类文件        InputStream in = null;        //使用byteArrayOutputStream保存类文件。然后转化为byte数组        ByteArrayOutputStream out = null;        try {            in = new FileInputStream(new File(name));            out = new ByteArrayOutputStream();            int i = 0;            while ( (i = in.read()) != -1){                out.write(i);            }        }catch (Exception e){}        finally {            try {                out.close();                in.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return out.toByteArray();    }    public String getName() {        return name;    }    public void setPath(String path) {        this.path = path;    }}

  然后调用

 

public static void main(String[] args) {        MyClassLoader m = new MyClassLoader("/home/fanjie/code/","classLoad1");        Class c = m.findClass("Hello");        System.out.println(c.getClassLoader());    }

  结果 : classLoader.MyClassLoader@60e53b93

 

 

转载于:https://www.cnblogs.com/fanjie/p/6928347.html

你可能感兴趣的文章
HDU 5510 Bazinga KMP
查看>>
关于select @@IDENTITY的初识
查看>>
ASP.NET MVC ajax提交 防止CSRF攻击
查看>>
关于CSS伪类选择器
查看>>
适用于带文字 和图片的垂直居中方法
查看>>
Part 2 - Fundamentals(4-10)
查看>>
使用Postmark测试后端存储性能
查看>>
NSTextView 文字链接的定制化
查看>>
第五天站立会议内容
查看>>
CentOs7安装rabbitmq
查看>>
(转))iOS App上架AppStore 会遇到的坑
查看>>
解决vmware与主机无法连通的问题
查看>>
做好产品
查看>>
项目管理经验
查看>>
笔记:Hadoop权威指南 第8章 MapReduce 的特性
查看>>
JMeter响应数据出现乱码的处理-三种解决方式
查看>>
获取设备实际宽度
查看>>
图的算法专题——最短路径
查看>>
SQL批量删除与批量插入
查看>>
Notes on <High Performance MySQL> -- Ch3: Schema Optimization and Indexing
查看>>