有时候,根据自己项目的需求,需要重新实现属于自己的类加载器,以满足项目的灵活性和扩展性,下面我们就来实现自己的类加载器.
实现自己的类加载器必须首先继承一个父类加载器.
编写一个类加载器会涉及到以下几个方法:
1. findClass(String name) 根据类的路径查找类,必须重写的方法
2.defineClass(String name, byte[] b, int off, int len) 由父类实现,直接调用
3.loadClass(String name)首先调用父类的findClass方法找,找不到则调用自身重写的findClass方法找,也不需要我们实现.loadClass(String name)默认会调用loadClass(name,false)方法,表示只加载,不发生连接操作.JDK的ClassLoader类的loadClass(String name,boolean resolve)方法的实现如下:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
// 如果该类以前被调用,则直接调用
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// 自己实现的findClass方法被调用
c = findClass(name);
}
}
if (resolve) { //进行类的连接,与其他类发生联系
resolveClass(c);
}
return c;
}
可以看出ClassLoader采用了模版模式,在父类加载器加载不到想要的类时,采用自己实现的方法.
自己写的类加载器及测试代码如下:
public class MyClassLoader extends ClassLoader {
private String path = "c:/bin/";
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String namePath = name.replace(".", "/");
String classPath = path + namePath + ".class";
InputStream is = null;
ByteArrayOutputStream os = null;
try {
is = new FileInputStream(new File(classPath));
os = new ByteArrayOutputStream();
int b = 0;
while ((b = is.read()) != -1) {
os.write(b);
}
byte[] bytes = os.toByteArray();
os.flush();
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(os!=null)
os.close();
if(is!=null)
is.close();
} catch (IOException e1) {
os=null;
is = null;
}
}
return null;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) {
MyClassLoader myLoader = new MyClassLoader();
try {
Class myClass = myLoader.loadClass("com.ldh.loader.HelloWorld");
Object obj = myClass.newInstance();
Method method = myClass.getMethod("say", null);
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
HelloWolrd类如下:
public class HelloWorld {
public void say(){
System.out.println("hello,world");
}
}
我把HelloWorld类放在c:/bin/目录下.
最后谈一下loadClass()和forName()的区别.
从上可以看出调用loadClass(name),相当于调用loadClass(name,false),表示只加载类,不连接初始化类,调用newInstance()才真正完成连接初始化操作.
Class.forName("xxxx")等同于Class.forName("xxxx",true,loader).true,表示载入实例的同时也载入静态初始化区块;false,表示只会加载该类别,但不会调用其静态初始化区块,只有等到整个程序第一次实例化某个类时,静态初始化区块才会被调用
在大多情况下loadClass()和forName()可以互用, 可以把ClassLoader.loadClass()看成是更底层的操作.在某些必须初始化类的场合,比如加载JDBC驱动,只能使用forName()方法了
从上可以看出,实现自己的类加载器相当简单,只要继承一个父类加载器,重写findClass方法就可以了.
分享到:
相关推荐
本篇文章将深入探讨如何实现自定义类加载器以及其背后的原理。 1. **类加载器的工作原理** - 类加载过程分为三个阶段:加载、验证、准备、解析和初始化。在加载阶段,类加载器寻找并加载类的二进制数据。 - Java...
类加载器的设计遵循双亲委派模型,它分为三个主要部分:启动类加载器、扩展类加载器和应用类加载器。 #### 二、类加载过程 类加载过程主要包括三个步骤: 1. **加载**:通过类的全限定名找到该类的二进制字节流。...
这种设计遵循了**委托模式**,即自定义类加载器在尝试加载类之前会先询问其父加载器是否能加载该类,只有在父加载器无法加载时才会尝试自己加载。 #### 八、类的卸载与重载 1. **卸载**: Java类一旦被加载到JVM中...
本篇文章将深入探讨“网络类加载器实现”,这是一个允许从网络上动态加载类的高级技术,对于理解和扩展Java应用程序的灵活性具有重要意义。 首先,我们来了解一下Java类加载的基本过程。类加载分为三个阶段:加载、...
- 引导(Bootstrap)类加载器:这是最基础的类加载器,由本地代码实现,负责加载JRE的基础类库,如rt.jar,它不直接暴露给开发者。 - 扩展(Extension)类加载器:由ExtClassLoader实现,加载JRE/lib/ext目录下的...
类加载器的知识不仅仅局限于基础概念,还包括类加载的时机(静态加载、动态加载)、类加载器的实现(如自定义类加载器)、类的卸载、以及类加载器与安全策略的关系等。深入理解和掌握这些知识点,对于开发高效、安全...
在开发环境中,为了快速调试和更新,可以通过自定义类加载器实现类的热替换,达到无需重启应用就能更新代码的效果。 9. **类加载器的可见性** 子类加载器可以访问父类加载器加载的类,但反之不行,这保证了先加载...
当一个类加载器接收到加载类的请求时,它首先会委托其父加载器尝试加载,只有当父加载器无法找到对应的类时,才会尝试自己加载。这种设计确保了类的唯一性,防止类的重复加载和安全问题。 ### 自定义类加载器的创建...
类加载器不仅关乎程序的运行,还在实现动态加载、插件系统等方面发挥着重要作用。以下是对类加载器的详细介绍: 1. 类加载机制: Java的类加载分为加载、验证、准备、解析和初始化五个阶段。加载阶段是类加载器的...
系统类加载器在加载类时,会先尝试让扩展类加载器加载,如果扩展类加载器无法加载,则再由系统类加载器自己尝试加载。这样的设计是为了保证核心类库的唯一性和安全性,避免用户自定义的类覆盖了 JDK 内置的核心类。 ...
1. Bootstrap ClassLoader:这是最基础的类加载器,由JVM本身实现,负责加载JRE的`<JAVA_HOME>/lib`目录下的核心类库,或者被`-Xbootclasspath`参数指定的路径中的类。 2. Extension ClassLoader:扩展类加载器,...
自定义Java类加载器允许我们根据特定需求扩展默认的加载机制,例如,从非标准位置加载类或者实现动态加载。在Java中,类加载过程分为加载、验证、准备、解析和初始化五个阶段。 首先,让我们了解Java中的默认类加载...
1. **引导类加载器(Bootstrap ClassLoader)**:这是最基础的类加载器,由JVM本身实现,主要负责加载JDK核心库,如rt.jar中的类,这些类通常位于JRE的lib目录下。 2. **扩展类加载器(Extension ClassLoader)**:由...
当一个类加载器接收到加载类的请求时,它首先会委托父类加载器尝试加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。这样设计的目的是保证Java核心类库的稳定性,防止用户自定义类覆盖系统核心类。...
在“java 类加载器 加密”这个主题中,我们将探讨如何利用类加载器实现类的加密和解密,以及如何通过反射执行main方法。 首先,我们理解一下类加载器的工作原理。Java中的类加载器主要有三种:Bootstrap ...
每个类加载器在尝试加载类时,会先委托给父类加载器,只有当父类加载器无法加载时,才会尝试自己加载。这种机制保证了Java的核心类库只被加载一次,同时也确保了类的唯一性。 Tomcat的类加载器工作流程可以总结为:...
4. **隔离的运行环境**:每个类都可以有自己的类加载器,从而实现类的隔离,避免了不同版本库之间的冲突,这对于多模块或多版本的项目尤为有用。 5. **灵活性**:由于可以从Maven仓库动态加载,可以方便地实现热...
在自定义类加载器时,需要重写`findClass()`方法,以实现自己的加载逻辑。 接着,类加载器与类的关系需要深入理解。每个类都有一个对应的类加载器,而类加载器之间存在父子关系,形成了层次结构。不同类加载器加载...