2011-08-17 48 views
1

至于学术目的的HTTP Web服务器项目, 我试着写了Web应用的类我自己的自定义类加载器的一部分,但似乎无法做对了。爪哇 - 定制ClassLoader - 尝试使用类文件的完整路径加载类

一般来说,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);

我得到一个空的返回值...

UPDATE时:总之,我怎么能加载一个特定的类不在“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; 
} 

任何想法我怎么能得到它的工作?

谢谢!

+0

这将有助于如果你能展现完整的异常堆栈跟踪。 – 2011-08-17 12:33:48

+0

`... \对象\ .Object.class`确保你不想`... \ Object.class` – vickirk 2011-08-17 12:50:49

回答

4

此刻,你不仅尝试通过自己的类加载器加载自定义类,但所有的系统正clases他们依靠为好。像例如java.lang.Object,这是你的问题在这里。

一般来说,在Java类加载器的链接,这意味着,你的类加载器已被另外一个(最有可能的系统类加载器)中定义。因此,最好不要自己覆盖loadClass方法,而是覆盖两个方法的findClass(String):Class和loadClassData(String):Class。

下面是从ClassLoader类的Javadoc中的excerp:

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 
      . . . 
    } 
} 

我想你可能想阅读:Javadoc for ClassLoader