Mik*_* S. 1 java web-applications classloader
作为用于学术目的的 HTTP WebServer 项目的一部分,我正在尝试为 Web 应用程序类编写自己的自定义类加载器,但似乎无法正确完成。
一般来说,Web 应用程序位于它们自己的文件夹中,Web 应用程序的“.class”文件与其直接的父文件夹名称相同。(例如 Web1/Web1.class)。下面的代码可以正常工作,直到我到达该defineClass()方法,然后它会抛出以下异常:
java.io.FileNotFoundException: C:\inetpub\javawwwroot\WebApps\java\lang\Object\.Object.class (The system cannot find the path specified)
值得一提的是,下面代码中的C:\inetpub\javawwwroot\WebApps\部分等于m_WebAppsFullPath变量。
此外,当尝试使用
InputStream in = getResourceAsStream(clsFile);
代替 InputStream in = new FileInputStream(clsFile);
我得到一个空返回值...
更新:简而言之,如何加载既不在“CLASSPATH”中也不在我的项目的任何包中的特定类?
protected synchronized Class loadClass(String className, boolean resolve)
throws ClassNotFoundException
{
log("Loading class: " + className + ", resolve: " + resolve);
// 1. is this class already loaded?
Class cls = findLoadedClass(className);
if (cls != null)
{
return cls;
}
// 2. get class file name from class name
String classRelativePath = className.replace('.', '/');
String classFileName =
((className.lastIndexOf('.') != -1) ? className.substring(className.lastIndexOf('.')) : className) + ".class";
String clsFile = m_WebAppsFullPath + "\\" + classRelativePath + "\\" + classFileName;
// 3. get bytes for class
byte[] classBytes = null;
try
{
//InputStream in = getResourceAsStream(clsFile);
InputStream in = new FileInputStream(clsFile);
byte[] buffer = new byte[BUFFER_SIZE];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int n = -1;
while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n);
}
classBytes = out.toByteArray();
}
catch (IOException e) {
log("ERROR loading class file: " + e);
}
if (classBytes == null) {
throw new ClassNotFoundException("Cannot load class: " + className);
}
// 4. turn the byte array into a Class
try {
cls = defineClass(className, classBytes, 0, classBytes.length);
if (resolve) {
resolveClass(cls);
}
}
catch (SecurityException e) {
// loading core java classes such as java.lang.String
// is prohibited, throws java.lang.SecurityException.
// delegate to parent if not allowed to load class
cls = super.loadClass(className, resolve);
}
return cls;
}
Run Code Online (Sandbox Code Playgroud)
知道如何让它工作吗?
谢谢!
小智 5
目前,您不仅要尝试通过自己的类加载器加载自定义类,还要尝试加载它们所依赖的所有系统类。比如java.lang.Object,这是你的问题。
通常,Java 中的类加载器是链式的,这意味着您的类加载器已由另一个类加载器(很可能是系统类加载器)定义。因此,建议不要自己覆盖loadClass 方法,而是覆盖两个方法'findClass(String):Class 和loadClassData(String):Class。
以下是 Classloader 类的 Javadoc 的摘录:
ClassLoader 类使用委托模型来搜索类和资源。ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例会将类或资源的搜索委托给其父类加载器,然后再尝试查找类或资源本身。虚拟机的内置类加载器,称为“引导类加载器”,它本身没有父级,但可以作为 ClassLoader 实例的父级。
同一个 Javadoc 甚至列出了一个示例,如何正确定义自定义类加载器:
class NetworkClassLoader extends ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
. . .
}
}
Run Code Online (Sandbox Code Playgroud)
我想你可能想阅读:Javadoc for ClassLoader