假如,你开发的java程序都需要从E:\classloader1目录下的类文件中加载class,而不是系统指定的系统目录或者classpath目录下加载,则如何解决? 需要自定义classloader。

ClassLoader:加载各种class文件到JVM中。ClassLoader是抽象类。

类的加载过程分为加载阶段、连接阶段、初始化。

  1. 加载阶段:寻找class文件。
  2. 连接阶段:验证class文件的正确性;为类的静态变量准备内存,并为其初始化默认值;把类中符号引用转换为直接引用。
  3. 初始化阶段:为累的静态变量赋予正确的初始值,也就是在代码的值。

JVM目前对类的初始化时一次lazy。所以何时初始化就会根据不同情况而不同,如果主动使用,则会进行类的初始化。

类的6种主动使用情况:

  1. 通过调用静态变量会导致类的初始化。 但是若是静态常量,则不会。
  2. 调用静态方法,会导致类的初始化过程。
  3. 调用class.forName。
  4. 调用子类会导致父类初始化,但是如果只是通过子类调用父内的静态方法后者变量,则不会导致子类初始化。
  5. 调用main方法的类也会被初始化。
  6. 调用 new关键字,必然会进行类的初始化,但是数组除外。

类的被动使用:除了主动的以外,都是被动的。

类的加载过程中阶段,常量是在javac编译阶段就替换了值,所以不会再类的连接阶段进行默认初始化(给相应类变量一个相关类型在没有被设置时候的默认值)。

类的初始化阶段中,赋值动作和静态语句块的执行代码,这个是按照顺序执行。虚拟机会保证这些动作会优先执行,因此父类的静态变量总是能够得到优先赋值。

JVM默认的加载类去寻找特定的几个目录下的类进行加载。比如当前路径,classpath等。若想自定义路径,或者在加载过程中,有些个性化的需求,则需要自定义加载类进行加载。
自定义加载类,还有一个好处,可以根据需求,进行单独卸载和重新加载,这样就可以进行无需停机的热部署。

下面时自定义加载类的使用方法:

  1. 先编写一个简单的类,用于测试被自定义类加载。
    '''
    package classLoaderStudy;
    public class ClassLoaderHello {
    static
    {
    System.out.println("hello world");
    }
    public String welcome()
    {
    return "Hello world";
    }

}
'''

  1. 编写自定义加载类,

其中findClass是必须重写的,功能就是读入class文件位字节流,然后调用ClassLoader的自带方法defineClass方法对类在方法区进行定义,这样,才能使用这个自定义类。
'''
package classLoaderStudy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class MyClassLoader extends ClassLoader{

   private final static Path DEFAULT_CLASS_DIR = Paths.get("E:",  "classloader1");private final Path classDir;public MyClassLoader(){super();this.classDir = DEFAULT_CLASS_DIR;}public MyClassLoader(String classDir){super();this.classDir = Paths.get(classDir);}public MyClassLoader(String classDir,ClassLoader parent){super(parent);this.classDir = Paths.get(classDir);}private byte[] readClassBytes(String name)throws ClassNotFoundException{String classPath = name.replace(".", "/");Path classFullPath =  classDir.resolve(Paths.get(classPath+".class"));if(!classFullPath.toFile().exists()){throw new ClassNotFoundException("The Class "+name+" not  found");}try(ByteArrayOutputStream baos = new ByteArrayOutputStream()){Files.copy(classFullPath, baos);return baos.toByteArray();}catch(IOException e){throw new ClassNotFoundException("Load the class "+  name +"  occur error.",e);}}@Override/** (non-Javadoc)* @see java.lang.ClassLoader#findClass(java.lang.String)* 必须要重写这个类*/protected Class<?> findClass(String name) throws ClassNotFoundException{byte[] classBytes = this.readClassBytes(name);if(null == classBytes || classBytes.length == 0){throw new ClassNotFoundException("can not load the class ");}return this.defineClass(name, classBytes, 0,classBytes.length);}@Overridepublic String toString(){return "My ClassLoader";}public static void main(String[] args) {MyClassLoader classLoader = new MyClassLoader();Class<?> aClass  =null;try {aClass =  classLoader.loadClass("classLoaderStudy.ClassLoaderHello");} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println(aClass.getClassLoader());try {Object helloWorld = aClass.newInstance();System.out.println(helloWorld);Method welcomeMethod = aClass.getMethod("welcome");String result = (String) welcomeMethod.invoke(helloWorld);System.out.println(result);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}catch (Exception e){e.printStackTrace();}}

}
'''

  1. 测试

classLoaderStudy\\ClassLoaderHello.class文件拷贝到 E:\\classloader1目录下,
E:\\classloader1\\classLoaderStudy\\ClassLoaderHello.class并将工程中的 ClassLoaderHello.java文件和ClassLoaderHello.class文件删除,从而确保不会加载工程中的这个类,以便测试自定义加载类。
在Eclipse中运行MyClassLoader类,结果如下
'''
My ClassLoader
hello worldbr/>classLoaderStudy.ClassLoaderHello@7d4991ad
Hello world
'''

转载于:https://blog.51cto.com/ggwhsd/2347326

为什么要自定义ClassLoader进行类加载相关推荐

  1. Java Se:自定义ClassLoader

    JVM是如何知道java.lang包中的类的?JVM又是如何知道我们应用中的类的?我们的应用中明明是有某个类, 但是JVM却抛出ClassNotFoundException,这是为什么?XxxImpl ...

  2. 【Android 逆向】类加载器 ClassLoader ( 启动类加载器 | 扩展类加载器 | 应用类加载器 | 类加载的双亲委托机制 )

    文章目录 一.类加载器 二.类加载的双亲委托机制 一.类加载器 Java 虚拟机 ClassLoader 类加载器 : Bootstrap ClassLoader : 启动类加载器 , 该 加载器由 ...

  3. 自定义ClassLoader和双亲委派机制

    转载自 自定义ClassLoader和双亲委派机制 ClassLoader ClassLoad:类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.Java 源程序(.j ...

  4. Java高级进阶:自定义ClassLoader

    转载自 Java高级进阶:自定义ClassLoader 假如我们的类不在classpath下,而我们又想读取一个自定义的目录下的class,如果做呢? 读取自定义目录的类 示例读取c:/test/co ...

  5. Java Class的热替换 自定义ClassLoader加载.class

    本文是java热替换的实验,参考了 Java 类的热替换 -- 概念.设计与实现 http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/i ...

  6. springboot自定义ClassLoader实现同一个jar支持多版本的使用场景【附源码】

    springboot自定义ClassLoader实现同一个jar支持多版本的使用场景 背景 最近业务提出一个业务场景:系统目前支持hive3.1.0版本的数据源适配,但是有个别部门使用的数据源是hiv ...

  7. 自定义classloader实现JAVA热替换

    这几天学习了下JVM的原理,在看一个视频教程,上面上一个这样的题目: 1. 实现热替换.    运行一个程序HelloMain,他会循环调用另外一个类Worker.doit()方法.此时,对Worke ...

  8. java 自定义classloader_编写自定义classloader实现类的动态加载

    目标:实现类的动态加载 原理:使用java的自定义classloader机制实现类的动态加载. 代码实现://自定义classloader public class StrategyClassLoad ...

  9. Android自定义ClassLoader耗时问题追查

    (点击上方蓝字,快速关注我们) 最近在优化西瓜视频客户端冷启动速度时,发现在关闭插件 ClassLoader 注入的情况下,启动速度提升了300ms左右,但是西瓜在启动阶段并没有使用到插件,那么这么大 ...

最新文章

  1. 15-jQuery补充
  2. [POJ] 3687 Labeling Balls(拓扑排序)
  3. Anaconda建立新的环境,出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url 解决过程
  4. aida64 extreme 序列号_轻声问海关,规范申报错了谁负责?底料来源四川行不行?没有公式定价行不行?序列号是料号行不行?...
  5. PIC单片机精通_串口通讯与串口调试实例
  6. MySQL将utf8字符集改为utf8mb4
  7. Python Django中,页面改变但链接地址没有跳转,解决方法
  8. idea lombok插件安装_mac安装的软件和idea的插件推荐
  9. LeetCode 142 环形链表 II
  10. linux系统加多个网卡,Linux环境下填加多个IP段在同一网卡
  11. SQL Server列名显示无效
  12. drop table可以删除多张表吗_delete、truncate、drop 有啥区别?该怎么选择?
  13. 免费python课程排行榜-Python培训机构排行榜哪家更好?老男孩Python全栈开发
  14. Day002 20210207
  15. 【小甲鱼c语言】C语言函数大全语法着色版(免费下载)
  16. ssdp java_SSDP协议的Android实现以及使用
  17. 《穷查理宝典》的读后感作文4000字
  18. 2020,网络安全领域有什么新趋势
  19. JavaSE基础知识点整理总结
  20. Lab3:自行车码表

热门文章

  1. mysql怎么判断2个时间戳为同一天_php如何判断两个时间戳是一天
  2. 设置背景色为渐变色 css
  3. springmvc05 传值
  4. 进阶13 Lambda表达式
  5. python类带参数_Python函数参数传递机制(超级详细)
  6. jquery 获取 radio值 与 jQuery filter() 方法
  7. mysql 时间戳截断_列的Mysql时间戳数据被截断
  8. php.ini 没有pdo,检查了启用的php.ini文件“ extension = php_pdo_mysql.dll”,但仍然出错...
  9. rman一致性备份oracle数据库可以在非归档模式下么,探索ORACLE之RMAN_03一致性备份...
  10. android滚动悬停布局,android布局滑动到顶端悬浮,录音