Say, you have a resource file in your project Project/src/com/example/icon.PNG
. But this is not where the program is going to look for it. The program is going to look for your file in classpath, which is either under /out
, or /target
folder, the one which contains your compiled classes.
Get to know you classpath precise by running System.getProperty("java.class.path")
. It has same structure as your OS $PATH
variable.
In context of location of resource files, absolute means relative to the classpath, as if the classpath was /
of your filesystem.
In context of location of resource files, relative means relative to the compiled class file.
When accessing resource files in Java, there are three pairs of options to consider:
- You may access a resource either by using
ClassLoader
(i.e. this.getClass().getClassLoader()
, or MyClass.class.getClassLoader()
), or using Class
(i.e. MyClass.class
, or this.getClass()
);
- You may access a resource either by providing an absolute or a relative path;
- You may either obtain resource's URL (i.e.
this.getClass().getClassLoader().getResource("com/example/icon.PNG")
, or com.example.MyClass.class.getResource("icon.PNG")
), or you may obtain InputStream instead (i.e. MyClass.class.getClassLoader().getResourceAsStream("com/example/icon.PNG"))
, or this.getClass().getResourceAsStream("/com/example/icon.PNG")
)
YOU CANNOT USE RELATIVE PATHS WITH CLASSLOADER
Absolute paths (relative to your classpath) start with /
when you access it via Class, but never start with /
when you access it via ClassLoader. For example:
this.getClass().getResourceAsStream("/com/example/icon.PNG")
finds the file;
this.getClass().getClassLoader().getResourceAsStream("/com/example/icon.PNG")
returns null
this.getClass().getResourceAsStream("com/example/icon.PNG")
returns null
this.getClass().getClassLoader().getResourceAsStream("com/example/icon.PNG")
finds the file
com.example.package1.MyObj1.class.getResource("../icon.PNG")
finds the file
com.example.MyClass.class.getResource("icon.PNG")
finds the file
com.example.MyClass.class.getResource("com/example/icon.PNG")
returns null
Last but not least - it would be enough to have read access rights for the resource file in order to copy it to classpath (to out/production/
, or target/
, etc.) so even if it is root owned, read-only access rights (chmod 444 icon.PNG
) then it still would be enough to build your app. If the resource file is unreadable in build time, your classpath simply won't built at all, so no worries here. If you do make a trick and take away read access rights on the resource which is already on the classpath (i.e. you do chmod 000 /target/Project/com/example/icon.PNG
), then the obtained URL still won't be null, but you're going to simply read 0 bytes from it, with no error.