2011-07-21 32 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读取定位资源弄死类加载器的问题。

相关问题