java的类加载机制默认情况下是采用委托模型:当加载某个类时JVM会首先尝试用当前类加载器的父类加载器加载该类,若父类加载器加载不到再由当前类加载器来加载,因此这种模型又叫做“父优先”模型。
但是在实际项目中我们可能会要求先从当前类加载加载再从父类加载器加载,如项目中的某类的版本可能和container中的不一致的时候,若还从container加载就会报jar包冲突的异常,实际上jar包冲突的问题在实际开发过程中是经常会遇到的。如我们在开发Loong时就遇到了类似问题。
解决方案是通过扩展自定义的ClassLoader,重写loadClass方法,先从当前类加载器加载再从父类加载器加载。
public class MCFClassLoader extends URLClassLoader {
public MCFClassLoader(URL[] urls) {
super(urls);
}
public MCFClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public MCFClassLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class c = findLoadedClass(name);
if (c == null) {
try {
c = findClass(name);
} catch (ClassNotFoundException e) {
return super.loadClass(name);
}
}
return c;
}
}
通过上面的ClassLoader就解决了我们遇到的问题。
思考:通过扩展URLClassLoader可以实现好多有趣的功能,如支持多父、支持加载顺序配置等等。
作为补充给出一个使用上面的ClassLoader的示例代码:
public ClassLoader getDSClassLoader(String moudleName) {
if (DSClassLoader == null) {
try {
DSClassLoader = new MCFClassLoader(
new URL[] {
new URL("......xxx.jar"),
new URL("......yyy.jar")},
ConnectorConfigurationParserServiceImpl.class
.getClassLoader());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return DSClassLoader;
}
上面的例子说明当xxx.jar或yyy.jar中有需要加载的类时就从这些jar包里加载,即使所在的container里有同样的类,这样可在一定程度上避免jar包版本冲突的问题!
分享到:
相关推荐
当一个类加载器接收到加载类的请求时,它首先会委托其父类加载器去尝试加载,如果父类加载器无法加载,再由当前加载器尝试。这个过程一直向上,直到Bootstrap类加载器,如果Bootstrap也无法加载,再回退到原始的类...
在Java中,类加载器按照层次结构进行组织,包括引导类加载器、扩展类加载器和应用程序类加载器,每个都有特定的职责。 1. **引导类加载器(Bootstrap ClassLoader)**:这是最基础的类加载器,由JVM本身实现,主要...
类加载机制遵循双亲委派模型,即一个类加载请求会首先交给父加载器处理,只有当父加载器无法加载时,才会由当前加载器尝试。这样设计可以避免类的重复加载,保证核心类的一致性。 3. **类的生命周期** 类的生命...
扩展类加载器的父加载器是引导类加载器,尽管在Java中它表现为`null`。 3. **系统类加载器(Application ClassLoader)**:也称为应用类加载器,同样由Java编写,主要负责加载应用的类,即用户代码所在的`CLASSPATH...
JVM采用**父类委托机制**来加载类,这意味着当一个类加载器接收到加载请求时,它首先会委托给其父类加载器尝试加载,直到达到Bootstrap类加载器(顶级加载器)。如果父类加载器找不到所需类,那么请求会回溯到子类...
类加载器遵循双亲委派模型,这意味着当一个类加载器尝试加载类时,它首先会将请求委托给其父类加载器,直到到达顶层的Bootstrap ClassLoader,如果父类加载器无法找到该类,子类加载器才会尝试自己加载。 在Tomcat...
系统类加载器在加载类时,会先尝试让扩展类加载器加载,如果扩展类加载器无法加载,则再由系统类加载器自己尝试加载。这样的设计是为了保证核心类库的唯一性和安全性,避免用户自定义的类覆盖了 JDK 内置的核心类。 ...
2. **扩展类加载器(Extension Class Loader)**:由Java编写,具体为`sun.misc.Launcher$ExtClassLoader`,它是引导类加载器的子加载器,负责加载%JAVA_HOME%\jre\lib\ext目录下的类库或java.ext.dirs系统变量指定...
此外,还可以查看类加载器加载的类路径,了解类的来源和加载顺序。 总之,JVM的类加载机制是Java运行时的关键部分,它保证了程序的稳定性和安全性,同时也提供了灵活性,使得我们可以自定义加载逻辑,满足特定场景...
如果未被加载,则将该请求转交给其父类加载器处理。 2. **递归调用**:这一过程会一直递归进行,直到请求到达顶层的启动类加载器。 3. **最终处理**:如果父类加载器无法处理该请求,则交由子类加载器自行处理。如果...
它首先会尝试让其父类加载器加载类,如果父类加载器无法加载,则会在扩展目录下查找类文件。 - **Application类加载器**:也称为系统类加载器,负责加载用户应用程序的类库,这些类库通常位于CLASSPATH环境变量所...
扩展类加载器加载JRE扩展目录下的jar文件,这些库提供了对Java标准版的扩展功能。 4. **Application类加载器** 应用程序类加载器也称为系统类加载器,它负责加载用户类路径(CLASSPATH)中的类。在WebLogic中,它...
这个"Java类的基本运行顺序"教程可能还涵盖了如何通过自定义类加载器来扩展类的加载行为,以及如何调试类加载问题等内容。了解这些基础知识对于理解和优化Java应用程序的性能至关重要,尤其是在大型企业级应用中。 ...
WebSphere应用服务器默认的类加载顺序是先从系统类加载器(System ClassLoader)开始,然后是扩展类加载器(Extension ClassLoader),最后是应用程序类加载器(Application ClassLoader)。这种机制可能导致应用中...
这些扩展类库是由系统类加载器(System ClassLoader)加载的,位于JRE的扩展目录下。这些库为Java平台提供了额外的功能支持。 3. **环境变量CLASSPATH中的jar和class文件** CLASSPATH环境变量配置了开发者指定的...
- **父级优先(Parent First)**:类装载器首先委托给其父类装载器,只有在父类装载器找不到类时才尝试自己查找。 - **子级优先(Child First)**:类装载器首先在自己的类路径中查找类,只有在自己的类路径中找不到时才...
- 不可以创建名为`Java.lang.System`的类,因为Java的命名空间是全局的,且JVM的类加载机制会优先寻找根类加载器,根加载器会加载JRE核心库中的`java.lang.System`,导致自定义的类无法加载。 类加载器的设计使得...
当一个类加载器收到加载类的请求时,它首先会将任务委托给父加载器,只有当父加载器无法加载时,子加载器才会尝试自己去加载。这一机制保证了Java核心库的稳定性,避免用户自定义类覆盖系统类。 在实际应用中,我们...