为什么要自定义ClassLoader进行类加载
假如,你开发的java程序都需要从E:\classloader1目录下的类文件中加载class,而不是系统指定的系统目录或者classpath目录下加载,则如何解决? 需要自定义classloader。
ClassLoader:加载各种class文件到JVM中。ClassLoader是抽象类。
类的加载过程分为加载阶段、连接阶段、初始化。
- 加载阶段:寻找class文件。
- 连接阶段:验证class文件的正确性;为类的静态变量准备内存,并为其初始化默认值;把类中符号引用转换为直接引用。
- 初始化阶段:为累的静态变量赋予正确的初始值,也就是在代码的值。
JVM目前对类的初始化时一次lazy。所以何时初始化就会根据不同情况而不同,如果主动使用,则会进行类的初始化。
类的6种主动使用情况:
- 通过调用静态变量会导致类的初始化。 但是若是静态常量,则不会。
- 调用静态方法,会导致类的初始化过程。
- 调用class.forName。
- 调用子类会导致父类初始化,但是如果只是通过子类调用父内的静态方法后者变量,则不会导致子类初始化。
- 调用main方法的类也会被初始化。
- 调用 new关键字,必然会进行类的初始化,但是数组除外。
类的被动使用:除了主动的以外,都是被动的。
类的加载过程中阶段,常量是在javac编译阶段就替换了值,所以不会再类的连接阶段进行默认初始化(给相应类变量一个相关类型在没有被设置时候的默认值)。
类的初始化阶段中,赋值动作和静态语句块的执行代码,这个是按照顺序执行。虚拟机会保证这些动作会优先执行,因此父类的静态变量总是能够得到优先赋值。
JVM默认的加载类去寻找特定的几个目录下的类进行加载。比如当前路径,classpath等。若想自定义路径,或者在加载过程中,有些个性化的需求,则需要自定义加载类进行加载。
自定义加载类,还有一个好处,可以根据需求,进行单独卸载和重新加载,这样就可以进行无需停机的热部署。
下面时自定义加载类的使用方法:
- 先编写一个简单的类,用于测试被自定义类加载。
'''
package classLoaderStudy;
public class ClassLoaderHello {
static
{
System.out.println("hello world");
}
public String welcome()
{
return "Hello world";
}
}
'''
- 编写自定义加载类,
其中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();}}
}
'''
- 测试
将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进行类加载相关推荐
- Java Se:自定义ClassLoader
JVM是如何知道java.lang包中的类的?JVM又是如何知道我们应用中的类的?我们的应用中明明是有某个类, 但是JVM却抛出ClassNotFoundException,这是为什么?XxxImpl ...
- 【Android 逆向】类加载器 ClassLoader ( 启动类加载器 | 扩展类加载器 | 应用类加载器 | 类加载的双亲委托机制 )
文章目录 一.类加载器 二.类加载的双亲委托机制 一.类加载器 Java 虚拟机 ClassLoader 类加载器 : Bootstrap ClassLoader : 启动类加载器 , 该 加载器由 ...
- 自定义ClassLoader和双亲委派机制
转载自 自定义ClassLoader和双亲委派机制 ClassLoader ClassLoad:类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.Java 源程序(.j ...
- Java高级进阶:自定义ClassLoader
转载自 Java高级进阶:自定义ClassLoader 假如我们的类不在classpath下,而我们又想读取一个自定义的目录下的class,如果做呢? 读取自定义目录的类 示例读取c:/test/co ...
- Java Class的热替换 自定义ClassLoader加载.class
本文是java热替换的实验,参考了 Java 类的热替换 -- 概念.设计与实现 http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/i ...
- springboot自定义ClassLoader实现同一个jar支持多版本的使用场景【附源码】
springboot自定义ClassLoader实现同一个jar支持多版本的使用场景 背景 最近业务提出一个业务场景:系统目前支持hive3.1.0版本的数据源适配,但是有个别部门使用的数据源是hiv ...
- 自定义classloader实现JAVA热替换
这几天学习了下JVM的原理,在看一个视频教程,上面上一个这样的题目: 1. 实现热替换. 运行一个程序HelloMain,他会循环调用另外一个类Worker.doit()方法.此时,对Worke ...
- java 自定义classloader_编写自定义classloader实现类的动态加载
目标:实现类的动态加载 原理:使用java的自定义classloader机制实现类的动态加载. 代码实现://自定义classloader public class StrategyClassLoad ...
- Android自定义ClassLoader耗时问题追查
(点击上方蓝字,快速关注我们) 最近在优化西瓜视频客户端冷启动速度时,发现在关闭插件 ClassLoader 注入的情况下,启动速度提升了300ms左右,但是西瓜在启动阶段并没有使用到插件,那么这么大 ...
最新文章
- 15-jQuery补充
- [POJ] 3687 Labeling Balls(拓扑排序)
- Anaconda建立新的环境,出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url 解决过程
- aida64 extreme 序列号_轻声问海关,规范申报错了谁负责?底料来源四川行不行?没有公式定价行不行?序列号是料号行不行?...
- PIC单片机精通_串口通讯与串口调试实例
- MySQL将utf8字符集改为utf8mb4
- Python Django中,页面改变但链接地址没有跳转,解决方法
- idea lombok插件安装_mac安装的软件和idea的插件推荐
- LeetCode 142 环形链表 II
- linux系统加多个网卡,Linux环境下填加多个IP段在同一网卡
- SQL Server列名显示无效
- drop table可以删除多张表吗_delete、truncate、drop 有啥区别?该怎么选择?
- 免费python课程排行榜-Python培训机构排行榜哪家更好?老男孩Python全栈开发
- Day002 20210207
- 【小甲鱼c语言】C语言函数大全语法着色版(免费下载)
- ssdp java_SSDP协议的Android实现以及使用
- 《穷查理宝典》的读后感作文4000字
- 2020,网络安全领域有什么新趋势
- JavaSE基础知识点整理总结
- Lab3:自行车码表
热门文章
- mysql怎么判断2个时间戳为同一天_php如何判断两个时间戳是一天
- 设置背景色为渐变色 css
- springmvc05 传值
- 进阶13 Lambda表达式
- python类带参数_Python函数参数传递机制(超级详细)
- jquery 获取 radio值 与 jQuery filter() 方法
- mysql 时间戳截断_列的Mysql时间戳数据被截断
- php.ini 没有pdo,检查了启用的php.ini文件“ extension = php_pdo_mysql.dll”,但仍然出错...
- rman一致性备份oracle数据库可以在非归档模式下么,探索ORACLE之RMAN_03一致性备份...
- android滚动悬停布局,android布局滑动到顶端悬浮,录音