自定义ClassLoader相信很多人都用过,网上文章也有很多。但如何使用自定义的ClassLoader有时确实比较头痛。
如果启动入口自己可以控制还好说,大不了通过自定义ClassLoader加载所有类就可以了,但如果控制不了,比如说是通过TOMCAT或脚本来启动的,但又要用自定义的ClassLoader来加载外部类,那就郁闷了。
我碰到的情形就是如此,其中的ClassLoaderC是tomcat的类加载器,而classLoaderD是自定义的类加载器。通常来说,我们只能选择访问C或D其中一个下面的类。有没办法能同时访问它们下两个的类呢?
其中一种办法是Thread.currentThread().setContextClassLoader。相对比较方便,但这在多线程环境下很容易产生问题。
还有一种办法是通过反射调用,修改ClassLoaderC的parent为ClassLoaderD。我们知道ClassLoader的委托机制是先让parent(父)类加载器寻找,只有在parent找不到的时候才从自己的类路径中去寻找。这样我们通过修改parent就能达到同时访问的目的。当然,由于parent是私有的,而且没有提供写方法,所以还需要用反射来设置。
之前还尝试了另一种方法,即ClassLoader.addClass,但发现类是进去了,但package里没有,还是会加载不到类。
这种方法目前还在试用,大家觉得有什么问题欢迎提出来:)
public class ContainerClassLoader extends ClassLoader {
private Map<String, Class<?>> loadedClasses = new HashMap<String, Class<?>>();
private static ContainerClassLoader INSTANCE;
private ContainerClassLoader() {
super(ContainerClassLoader.class.getClassLoader().getParent());
}
/**
* 初始化
*/
public static void init() {
INSTANCE = new ContainerClassLoader();
try {
INSTANCE.addThisToParentClassLoader(ContainerClassLoader.class
.getClassLoader());
} catch (Exception e) {
System.err.println("设置classloader到容器中时出现错误!");
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (loadedClasses.containsKey(name)) {
return loadedClasses.get(name);
}
return super.loadClass(name, resolve);
}
/**
* 将this替换为指定classLoader的parent ClassLoader
*
* @param classLoader
*/
private void addThisToParentClassLoader(ClassLoader classLoader) throws Exception {
Field field = ClassLoader.class.getDeclaredField("parent");
field.setAccessible(true);
field.set(classLoader, this);
}
}
- 大小: 10.5 KB
分享到:
相关推荐
自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热部署等。本案例将深入探讨如何创建一个自定义的ClassLoader,利用Java反射和注解技术...
在类加载过程中,遵循“双亲委派模型”:当一个类加载器需要加载某个类时,它首先会委托它的父加载器尝试加载,只有当父加载器无法加载时,当前加载器才会尝试自己加载。这种机制避免了类的重复加载,并确保了核心...
JVM代理和类加载器是Java开发中的高级话题,它们允许我们实现诸如动态字节码修改、代码加密、插件系统等复杂功能。通过自定义类加载器,我们可以定制加载流程,如在加载过程中进行加密操作,增强代码的安全性。而JVM...
- **取消双亲委派模型**:改为当前`ClassLoader`优先加载,这样可以避免不一致的JAR被父`ClassLoader`加载,从而实现隔离。 - **便捷地共享依赖**:允许共享那些没有`serialVersionUID`冲突的类库,提高效率。 - **...
总之,Classloader热部署是Java开发中的高级技巧,它通过巧妙地管理和操作类加载器,实现了代码的动态更新,极大地提高了开发效率。理解并掌握这些技术,对于提升Java应用的开发和维护能力至关重要。
ClassLoader提供了多种途径来获取ClassLoader,例如使用系统类加载器、当前类加载器或当前线程类加载器。例如: ```java ClassLoader classLoader = ClassLoader.getSystemClassLoader(); Class cls = classLoader....
在Android应用开发中,动态换肤是一项非常吸引用户的功能,它允许用户根据个人喜好更改应用程序的外观和风格。实现这一功能通常需要借助插件化开发技术。本文将深入探讨插件化开发的基本原理以及如何利用它来实现...
这种模式通常用于在不修改目标对象的情况下,为对象添加额外的功能或者行为。动态代理分为两类:基于接口的代理(Java动态代理)和基于具体类的代理(CGLIB)。本文主要介绍基于接口的Java动态代理。 #### 二、Java...
通常,我们会将主题定义为不同的样式文件(style.xml),然后在运行时动态替换掉当前的主题。通过改变主题,用户可以根据自己的喜好调整应用的外观,提升使用体验。 实现主题切换通常有以下步骤: 1. 定义不同主题...
当一个类需要加载时,它会首先尝试由父ClassLoader加载,只有当父ClassLoader无法找到该类时,才会由当前ClassLoader加载。这种机制防止了类的冲突,并确保了系统类如`String`只能由JRE的ClassLoader加载。 在JVM中...
通过动态代理,我们可以在不修改原有代码的情况下增加新的功能,比如日志记录、事务管理等。 #### 二、Java动态代理的基本原理 Java动态代理的核心是`java.lang.reflect.Proxy`类和`java.lang.reflect....
在Android中,类加载器(ClassLoader)遵循双亲委派模型,即首先由父加载器尝试加载,如果父加载器无法加载,再由当前加载器尝试。默认情况下,Android使用`PathClassLoader`加载应用的.dex文件。加固过程中,通常...
反射提供的功能,能在运行时(动态)的 ...Instrumentation是Java提供的一个来自JVM的接口,该接口提供了一系列查看和操作Java类定义的方法,例如修改类的字节码、向classLoader的classpath下加入jar文件等。
在描述中提到的Java动态加载类的主要目的是为了不改变主程序代码,仅通过修改配置文件就能实现对不同对象的操作和功能的变更。这种方式特别适合于需要频繁更新功能的系统,因为它大大降低了修改程序和重新部署的...
因此,分析当前加载的.so文件所在的ClassLoader是非常重要的。 ```java // 示例代码,用于获取当前加载的.so文件路径 String path = System.getProperty("java.library.path"); Log.i("Xposed", "Library path: " +...
3. **Javassist**:除了字节码操作,Javassist还提供了扫描类的能力,可以用于动态修改类。 五、实战示例 以下是一个简单的文件系统扫描示例: ```java import java.io.File; import java.io.FilenameFilter; ...
字节码也可以被反编译,用于分析代码逻辑或进行动态代码修改,如Java代理。 **类加载机制(Class Loading)**: 类加载是JVM启动时或运行过程中动态加载类的过程。这个过程包括加载、验证、准备、解析和初始化五个阶段...
装饰者模式指的是在不必改变原类(Input)文件和使用继承的情况下,动态地扩展一个对象的功能。 它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 实现步骤 :通过对原类文件继承,对原有...
总结来说,Java程序调用已编译的`.class`文件主要是通过自定义类加载器或内置的`ClassLoader`实现,这样可以实现动态加载和执行外部代码,尤其适用于插件系统、模块化应用等场景。在实际开发中,理解类加载机制以及...