2011-07-21 59 views
2

我們的Java應用程序依賴於網絡共享上可用的一些資源。此網絡共享位於類路徑中,並且在運行時使用MyClass.class.getResourceAsStream("/myfile.jpg")讀取資源。如何從java classpath中的網絡目錄正確加載資源?

java -Djava.class.path=\\myserver\myshare:C:\myjar.jar MainClass 

當共享在啓動時可用時,一切都運行順利。位於共享中的圖像和屬性文件可以使用getResourceAsStream()來讀取。但是,如果股票不在線應用程序啓動時,即使份額聯機讀取之前的任何資源,它們不能使用getResourceAsStream()讀取。

否則使用eclispse +反編譯一些挖,我注意到一個區別。默認類加載器繼承自URLClassLoader,其成員(URLClassPath)包含URLClassPath.Loader實例的列表。在第一種情況下,它包含URLClassPath.FileLoaderURLClassPath.JarLoader。在第二種情況下,它只包含一個jar加載器。

這就像Java的確定類路徑條目是無效的,並完全放棄它。

這是爲什麼?我怎樣才能避免它?

更新 我無法改變,使我們加載的,因爲幾個原因資源的機制:

  1. 有目前加載文件這樣對我的改變有太多的領域此刻
  2. 在有些情況下由資源實際上是由一個第三方組件

裝我沒有問題,創建自定義的類裝載器的情況下,我只需要一些指導如何做到這一點。

我想這個問題,但未能獲得預期的結果:

import java.net.URL; 
import java.net.URLClassLoader; 

public class MyUrlClassLoader extends URLClassLoader { 
    public MyUrlClassLoader(ClassLoader parent) { 
     super(new URL[0], parent); 
     System.out.println("MyUrlClassLoader ctor"); 
    } 

    @Override 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
     System.out.println("url find class " + name); 
     return super.findClass(name); 
    } 

    @Override 
    public Class<?> loadClass(String name) throws ClassNotFoundException { 
     System.out.println("url load class " + name); 
     return super.loadClass(name); 
    } 

    @Override 
    public URL getResource(String name) { 
     System.out.println("url get resource " + name); 
     return super.getResource(name); 
    } 
} 


import java.net.URL; 

public class ClassLoaderMain { 
    public static void main(String[] args) throws ClassNotFoundException { 
     URL url = ClassLoaderMain.class.getResource("/myfile.txt"); 
     System.out.print("Loaded? "); 
     System.out.println(url != null); 

     System.out.println(ClassLoaderMain.class.getClassLoader().toString()); 
     System.out.println(MyUrlClassLoader.class.getClassLoader().toString()); 
     System.out.println(FakeClass.class.getClassLoader().toString()); 
    } 
} 

當我運行java -cp . -Djava.system.class.loader=MyUrlClassLoader ClassLoaderMain

此輸出:

MyUrlClassLoader ctor 
url load class java.lang.System 
url load class java.nio.charset.Charset 
url load class java.lang.String 
url load class ClassLoaderMain 
Loaded? true 
[email protected] 
[email protected] 
[email protected] 

所以正在創建我的類加載器,並且正在調用load類,但它似乎不是它正在加載的類的類加載器?

+0

最安全的辦法大概是寫自己的類加載器。這意味着你完全控制。 – biziclop

+0

我會如何去做這個簡單的情況?到目前爲止,我所見過的所有資源似乎都在運行時用於按名稱加載類(例如,Class.forName(「string」))。我寧願不必每次調用'getResourceAsStream()'手動創建一個新的類加載器並調用它。 – Travis

+0

爲什麼不能使用File和FileInputStream來訪問文件? – pauli

回答

0

我結束了創建我自己的ClassLoader,從一個URLClassLoader獲得解決這個。

import java.io.File; 
import java.net.MalformedURLException; 
import java.net.URI; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.List; 

public class CustomClassLoader extends URLClassLoader { 

    public CustomClassLoader(ClassLoader parent) { 
     // System classloader will filter inaccessible URLs. 
     // Force null parent to avoid using system classloader. 
     super(createURLReferences(), null); 
    } 

    /** 
    * Build an array of URLs based on the java.class.path property. 
    * @return An array of urls to search for classes. 
    */ 
    private static URL[] createURLReferences() { 
     String classpath = System.getProperty("java.class.path"); 
     String[] classpathEntries = classpath.split(System.getProperty("path.separator")); 
     List<URL> urls = new ArrayList<URL>(); 
     for (String classpathEntry : classpathEntries) { 
      File classpathFile = new File(classpathEntry); 
      URI uri = classpathFile.toURI(); 
      try { 
       URL url = uri.toURL(); 
       urls.add(url); 
      } catch (MalformedURLException e) { 
       System.out.println("Ignoring classpath entry: " + classpathEntry); 
      } 
     } 

     return urls.toArray(new URL[urls.size()]); 
    } 
} 
0

@Travis:您可以通過使用的java.net.URL API來定位和使用的OpenStream()API讀取定位資源弄死類加載器的問題。

相關問題