getResource() can't load content in a jar

I can successfully load resources that stand in some package of my src/ dir in eclipse. Now, I export the jar (right click src, export, jar, and keep default settings) and can't have the resource loaded in another eclipse project.

I build the path to the resource by indicating a class standing in the same package name:

URL out = getClass().getClassLoader().getResource(packageName(getClass())+"file.glsl");
// out is null when loaded from a jar!!   

protected static String packageName(Class<?> clazz){
    return packageName(clazz.getPackage());
}
protected static String packageName(Package p){
    return c + p.getName().replace('.', c) + c;
}
protected static char c = File.separatorChar;

Do you see any wrong way? I tried:

  • getClass().getResource()
  • getClass().getClassLoader().getResource()
  • getClass().getClassLoader().getResourceAsStream()
  • Thread.currentThread().getContextClassLoader().getResource()
  • adding/removing the '/' char at the begining of the package name
  • using either '/', '', or File.separatorChar, and even '.', all failed.
  • I verified that:

  • jar contains the resource (expanding the jar content in eclipse project's "Referenced Libraries")
  • packageName(getClass())+filename) returns a clean name: "orgjzy3dplot3drenderingddpalgorithmsdual_peeling_init_vertex.glsl"
  • I endlessly retrieve a null :/


    EDIT: screenshot and code to show that "that should work"

    在这里输入图像描述

    You can retrieve this a SSCCE zipped eclipse project here

    A user class

    public class User {
        public static void main(String[] args) {
            Loader pair = new Loader(SomeClass.class, "shade_vertex.glsl");
            System.out.println("found:" + pair.getURL());
    
        }
    }
    

    Providing class dynamically with new SomeClass().getClass() produce the same result.

    The loader

    package com.pkg.loader;
    
    import java.io.File;
    import java.net.URL;
    
    public class Loader {
        public Loader(Class<?> c, String file) {
            this(packageName(c.getPackage()), file);
        }
    
        public Loader(Package p, String file) {
            this(packageName(p), file);
        }
    
        protected Loader(String pack, String file) {
            this.pack = pack;
            this.file = file;
        }
    
        public String getStringPath() {
            return pack+file;
        }
    
        public URL getURL() {
            URL out = Thread.currentThread().getContextClassLoader().getResource(getStringPath());
            if(out==null)
                throw new RuntimeException("unable to find shader URL for :'"+getStringPath()+"'");
            return out;
        }
    
        protected static String packageName(Class<?> clazz){
            return packageName(clazz.getPackage());
        }
    
        protected static String packageName(Package p){
            return c + p.getName().replace('.', c) + c;
        }
    
        protected static char c = File.separatorChar;
    
        protected String pack;
        protected String file;
    }
    

    The marker class

    public class SomeClass {}
    

    First, try not to place source files directly in the default package (src). Create at least one package to wrap your source because when jars are exported, the src folder isn't included. So if you create your own default package, then you'll have some defined root directory to base your resource paths on.

    After you've created your own default package, your problem might already be fixed, but if it wasn't then try this:

    YourClass.class.getResource("/your_root_package/blah/blah/file.glsl");
    

    It works for me for images:

    public static Image ICON32 = Toolkit.getDefaultToolkit().getImage(MainFrame.class.getResource("/files/images/icon32.png"));
    

    Yeah, so, hope this helps. :)


    The problem is actually this line:

    protected static char c = File.separatorChar;
    

    This will be a backslash on Windows, but paths for Class#getResource() must be forward slashes in order to work correctly. The JRE is probably looking for your path as a relative path and interpreting the backslash literally.

    In any case, what you should be using for this particular example is:

    URL out = getClass().getResource("file.glsl");
    

    Class#getResource() already handles resolving this relative to the class, so it doesn't make sense to duplicate that code in your app.

    链接地址: http://www.djcxy.com/p/66124.html

    上一篇: 在通过Java Webstart运行时,invokeLater中的NullPointerException

    下一篇: getResource()无法加载jar中的内容