自定义 Class 加载程序 java 不同的行为
Custom Class Loader in java different behaviour
我正在做一个需要从文件系统动态加载class的项目,我用谷歌搜索发现我需要使用自定义ClassLoader
。我已经实现了我自己的 class 加载程序,当我在控制台上 运行 它工作正常,当我尝试在服务器上部署应用程序时出现问题,它导致 ClassNotFoundException
.
问题是我正在尝试加载的 class 包含对另一个 class 的一些引用,该应用程序已经加载但它正在尝试从同一位置加载引用。
public class HandlerClassLoader extends ClassLoader {
static Logger log = Logger.getLogger(HandlerClassLoader.class.getName());
URLClassLoader ucl;
private ProcessDefinition processDefinition = null;
boolean flag = false;
public URL[] loadJars() throws MalformedURLException {
PropertiesFiles propFiles = new PropertiesFiles();
File f = new File(propFiles.getValue("jarslocation"));
log.debug("Loading JARS files from " + f.getAbsolutePath());
List<URL> urls = new ArrayList<URL>();
String filesName[] = f.list();
for (String jars : filesName)
if (jars.endsWith("jar")) {
urls.add(new URL("file:///"
+ propFiles.getValue("jarslocation") + "/" + jars));
}
URL[] array = urls.toArray(new URL[urls.size()]);
return array;
}
public HandlerClassLoader() {
super(Thread.currentThread().getContextClassLoader());
log.debug("Called to the " + this.getClass().getName()
+ " No Parameter Constructor");
try {
ucl = new URLClassLoader(loadJars());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
public HandlerClassLoader(ClassLoader parent,
ProcessDefinition processDefinition) {
super(parent);
log.debug("Called to the " + this.getClass().getName()
+ " Parameterized Constructor");
try {
ucl = new URLClassLoader(loadJars());
} catch (MalformedURLException e) {
e.printStackTrace();
}
this.processDefinition = processDefinition;
}
public Class<?> findClass(String className) throws ClassNotFoundException {
log.debug("findClass method of " + this.getClass().getName()
+ " is called with className : " + className);
return ucl.loadClass(className);
}
我认为委托原则不起作用,或者服务器必须有不同的 classloader 实现。
很有可能,您没有委托给正确的 parent。我假设选择 Thread.currentThread().getContextClassLoader()
会导致在应用程序服务器上使用错误的 class 加载程序,而这只是系统 class 加载程序(class 路径)当 运行 来自控制台应用程序。
因此,您需要确保您交给自定义 class 加载程序的 parent 能够看到您打算由它加载的 classes .
最后一点,实现您自己的 class 加载程序是一项棘手的工作。例如,您没有考虑定位资源或定义包。您正在使用的 third-party 库可能需要这两者。如果您真的只需要从磁盘加载文件,请考虑使用 URLClassLoader
.
我正在做一个需要从文件系统动态加载class的项目,我用谷歌搜索发现我需要使用自定义ClassLoader
。我已经实现了我自己的 class 加载程序,当我在控制台上 运行 它工作正常,当我尝试在服务器上部署应用程序时出现问题,它导致 ClassNotFoundException
.
问题是我正在尝试加载的 class 包含对另一个 class 的一些引用,该应用程序已经加载但它正在尝试从同一位置加载引用。
public class HandlerClassLoader extends ClassLoader {
static Logger log = Logger.getLogger(HandlerClassLoader.class.getName());
URLClassLoader ucl;
private ProcessDefinition processDefinition = null;
boolean flag = false;
public URL[] loadJars() throws MalformedURLException {
PropertiesFiles propFiles = new PropertiesFiles();
File f = new File(propFiles.getValue("jarslocation"));
log.debug("Loading JARS files from " + f.getAbsolutePath());
List<URL> urls = new ArrayList<URL>();
String filesName[] = f.list();
for (String jars : filesName)
if (jars.endsWith("jar")) {
urls.add(new URL("file:///"
+ propFiles.getValue("jarslocation") + "/" + jars));
}
URL[] array = urls.toArray(new URL[urls.size()]);
return array;
}
public HandlerClassLoader() {
super(Thread.currentThread().getContextClassLoader());
log.debug("Called to the " + this.getClass().getName()
+ " No Parameter Constructor");
try {
ucl = new URLClassLoader(loadJars());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
public HandlerClassLoader(ClassLoader parent,
ProcessDefinition processDefinition) {
super(parent);
log.debug("Called to the " + this.getClass().getName()
+ " Parameterized Constructor");
try {
ucl = new URLClassLoader(loadJars());
} catch (MalformedURLException e) {
e.printStackTrace();
}
this.processDefinition = processDefinition;
}
public Class<?> findClass(String className) throws ClassNotFoundException {
log.debug("findClass method of " + this.getClass().getName()
+ " is called with className : " + className);
return ucl.loadClass(className);
}
我认为委托原则不起作用,或者服务器必须有不同的 classloader 实现。
很有可能,您没有委托给正确的 parent。我假设选择 Thread.currentThread().getContextClassLoader()
会导致在应用程序服务器上使用错误的 class 加载程序,而这只是系统 class 加载程序(class 路径)当 运行 来自控制台应用程序。
因此,您需要确保您交给自定义 class 加载程序的 parent 能够看到您打算由它加载的 classes .
最后一点,实现您自己的 class 加载程序是一项棘手的工作。例如,您没有考虑定位资源或定义包。您正在使用的 third-party 库可能需要这两者。如果您真的只需要从磁盘加载文件,请考虑使用 URLClassLoader
.