2011-07-21 15 views
2

Javaアプリケーションは、ネットワーク共有上で利用可能ないくつかのリソースに依存しています。このネットワーク共有はクラスパス上にあり、リソースは実行時にMyClass.class.getResourceAsStream("/myfile.jpg")を使用して読み取られます。Javaクラスパスのネットワークディレクトリからリソースを正しく読み込むにはどうすればよいですか?

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

起動時に共有が利用可能になると、すべてがスムーズに実行されます。共有にある画像ファイルとプロパティファイルは、getResourceAsStream()を使用して読み取ることができます。ただし、アプリケーションの起動時に共有がオンラインでない場合、のリソースが読み取られる前に共有がオンラインになっても、getResourceAsStream()を使用して読み取ることはできません。

eclispse + decompilerを使用していくつかの掘り出しを行うと、1つの違いに気付きました。デフォルトのクラスローダーはURLClassLoaderを継承し、そのucpメンバー(URLClassPath)にはURLClassPath.Loaderインスタンスのリストが含まれています。最初のシナリオでは、URLClassPath.FileLoaderURLClassPath.JarLoaderが含まれています。 2番目のシナリオでは、jarローダーのみが含まれています。

javaのように、クラスパスエントリが無効であると判断し、完全に破棄します。

これはなぜですか?どうすればそれを避けることができますか?

  1. 私はで変更のために、現在のファイルをこのようにロードあまりにも多くの分野があります。

    更新 私たちはので、いくつかの理由のリソースをロードされる機構を変更することができません瞬間

  2. リソースによって、実際に私は何の問題カスタムクラスローダを作成していないサードパーティのコンポーネント

によってロードされている状況がありますが、Iどのようにそれを行うにはいくつかのガイダンスが必要です。

私はこれを試みたが、期待される結果を取得することができませんでした:、

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] 

だから私のクラスローダが作成されている:私はjava -cp . -Djava.system.class.loader=MyUrlClassLoader ClassLoaderMain

この出力を実行すると

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()); 
    } 
} 

をロードクラスが呼び出されていますが、ロードしているクラスのクラスローダーではないようですか?

+0

おそらく最も安全な方法は、独自のクラスローダーを作成することです。あなたが完全にコントロールしていることを意味します。 – biziclop

+0

シンプルなケースでこれをどうやってやるのですか?私が今までに見たリソースはすべて、実行時にクラスを名前(Class.forName( "string")など)でロードするために使用されているようです。新しいクラスローダーを手動で作成して呼び出すために、 'getResourceAsStream()'へのすべての呼び出しを変更する必要はありません。 – Travis

+0

FileとFileInputStreamを使用してファイルにアクセスできないのはなぜですか? – pauli

答えて

0

URLClassLoaderから派生した私自身のClassLoaderを作成して解決しました。

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を使用して検索して読み取ることで、クラスローダーの問題を解決できます。

関連する問題