I have worked on a project in Java using Eclipse that requires loading some images and displaying them. At first, I loaded them this way:
InputStream stream = MyClass.class.getClass().getResourceAsStream("/resources/ui/icons/" + name);
Image img = ImageIO.read(stream).getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);
And this worked fine, whether I'm running it from Eclipse or from an executable jar. But I recently got a new laptop, and when I tried to run it on the new machine, the jar would not run; stream
always turns out to be null
. However, this problem does not occur when I'm running from inside Eclipse.
Finally, after some experimentation, I changed the code to call getResourceAsStream()
directly on MyClass.class
without calling getClass()
:
InputStream stream = MyClass.class.getResourceAsStream("/resources/ui/icons/" + name);
Image img = ImageIO.read(stream).getScaledInstance(size.width, size.height, Image.SCALE_SMOOTH);
And for some reason, it works. My new laptop has the same OS (Windows 10) and other settings as the old one, but it runs Eclipse Photon instead of Oxygen.
So, what is the difference between the two ways of loading resources? (I've heard that it's something about ClassLoaders, but I cannot remember the exact words.) Why did switching to a new machine break the first one? And even with the second one, am I doing it correctly?
MyClass.class returns the java.lang.Class instance representing the class MyClass
. Calling .getClass on that returns the Class instance representing java.lang.Class
itself, and calling getResourceAsStream
on THAT will attempt to locate the resource in java.base (where java.lang.Class
lives). Generally, not what you want. In other words, your first example is the same as java.lang.Class.class.getResourceAsStream(...)
.
The second example is the proper way to do it.
The reason the first thing does work in a few places is because it's up to exactly how Class.getResourceXXX was specified in Java SE 8 and older. The specification changed in Java SE 9 to deal with classes where the Class is a named module.