2011-08-17 55 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