Jar Files and Packaging Programs
A resource is data a program uses that is not code, such as images, sounds, and text; the user normally does not need to know where it is stored.
Why Programs Carry More Than Code
Most beginning Java programs consist only of code, so it is natural to think of a program as a collection of classes and nothing else. Real programs often carry other material along with their code: a picture shown on screen, a sound played during a game, or a block of text read at startup. Java calls this kind of material a resource.
The learner using the program normally sees the picture or hears the sound without ever thinking about the file that holds it. That gap between what the user sees and where the data actually lives is the reason resources need a dedicated lookup mechanism. This article follows one running example, the image file cards.png used by a card program, and asks one question throughout: when the program asks for cards.png, what has to be true about where that file is stored for the request to succeed?
What Counts as a Resource
A resource is data a program uses that is not code, such as images, sounds, and text. The user normally does not need to know where it is stored.
- Image files, such as
cards.png, shown on screen - Sound files played during a game
- Text files, such as a block of text read at startup
The defining feature of a resource is that it is data rather than code. The program's classes tell it what to do; the resource supplies material the program uses while doing it.
Tracing the Two-Line Lookup
The first thing a program does with a resource is ask for it. The pattern below requests cards.png. Before reading the explanation, predict what the program needs in order to finish the request. Do not worry about the full meaning of each piece yet.
- Line 1 obtains a ClassLoader through the current object's class
- Line 2 hands the file name to that ClassLoader and stores the result in a URL variable
Notice that the code never states a folder path or a drive letter. The lookup supplies only the file name. Whatever makes the file findable has to come from the object that performs the search. That object is introduced in the next section.
Read the diagram as a single request. The program never opens a folder itself. It sends the file name to the ClassLoader, which performs the search, and it receives a URL in return. This delegation is why the user of the program can remain unaware of where the file lives.
The ClassLoader as a Search Object
The object that does the searching is a class loader. In Java it is represented by an object of type ClassLoader. Its everyday job is to find and load class files, and it can also find resource files that sit in the same kinds of places. Because one object handles both jobs, a resource request does not need its own separate search system.
The purpose of a ClassLoader can be summed up in one question: where should I look? Everything it can find, it finds by checking a fixed set of locations that it was given.
The ClassLoader's list of places to check is called the class path. The class path is the list of locations searched, which generally includes the standard classes location and the current directory, plus the jar file if the program is packaged in one. A resource is located by obtaining a ClassLoader and calling getResource with the file name, and that call returns a URL the program can use.
Class Path Order and Jar Position
The class path is an ordered list, and the position of each entry matters. The ClassLoader works through the entries in sequence rather than searching all of them at once. The standard classes location and the current directory are the ordinary entries, and a jar file is added to the list when the program is packaged in one.
The index map shows the default entries in the order described in the source. The source does not give a fixed rule for exactly where the jar file sits in that list, so the diagram shows only that it is one of the entries a packaged program adds. What the source does establish is that the ClassLoader searches the class path's locations, and a file is found only if one of those locations holds it.
Inside a Jar File
When a program is packaged in a jar file, the jar serves as one of the locations on the class path. The source describes packaging as the case where the jar file is part of the class path, which means the ClassLoader can look inside it for both class files and resource files. The program's code and its resources can therefore travel together as one unit while the lookup still works the same way for the code and the data.
A jar file is a packaged container that is searched like any other class path location. Its presence on the class path is what lets a program carry its resources with it.
Following the ClassLoader Search
Now follow one search for cards.png from start to finish. The ClassLoader takes the file name and checks the first class path location. If the file is there, the search stops and the URL is returned. If the file is not there, the ClassLoader moves on to the next location. The search continues entry by entry until the file is found or the list is exhausted.
The search has two possible stopping points. It stops with success the moment a location holds cards.png, and it stops with failure only after every location has been checked without a match. The flowchart is the same logic as the sequence diagram above, now shown at the level of individual location checks.
Where a Resource Lookup Fails
Because the lookup depends entirely on the class path, most failures come from a mismatch between where the file is stored and where the ClassLoader searches. The source notes that these failures are the most common cause of a resource that seems to be missing, and each of the following is worth checking.
Common mistake Storing cards.png in a folder that is not on any searched location
What it looks likeThe file sits in a sibling folder that the class path never lists.
Why it failsThe ClassLoader can only find a file in a location it was given. A file outside every searched location is invisible to the lookup.
Do this insteadPlace the file in a location the class path searches, such as the current directory or inside the packaged jar.
Common mistake Expecting the program to find a file by a folder path it was never given
What it looks likeWriting a full drive path into the getResource call instead of the file name.
Why it failsThe lookup supplies only the file name, and the ClassLoader decides where to look from its class path.
Do this insteadPass only the file name, and make sure the file is stored on a searched location.
Common mistake Assuming a missing resource means the code is broken, when the file is simply absent from every location checked
What do you think happens?
If cards.png is missing from every class path entry, what does the program receive from getResource?
Reveal answer
No URL. In Java, getResource returns null when the file cannot be found.
The search checks every location and finds no match, so there is no URL to return. The program receives nothing usable in place of the expected URL, which is the failure point the flowchart ends on.
Practice Tracing a Lookup
A card program calls getResource for "cards.png", but the file is stored in a folder that is not on the class path. Trace the search: which locations does the ClassLoader check, at what point does it stop, and what does the program receive?
Hints
- Start from the sequence diagram: the request goes to the ClassLoader first.
- Use the flowchart: each location is checked in turn until the list runs out.
- Think about whether the folder with the file is one of the entries listed on the class path.
Key Takeaways
- A resource is data a program uses that is not code, such as images, sounds, and text, and the user normally does not need to know where it is stored.
- A program requests a resource by obtaining a ClassLoader and calling
getResourcewith only the file name, which returns a URL the program can use. - The ClassLoader finds files by searching the class path, an ordered list of locations that generally includes the standard classes location and the current directory, plus the jar file when the program is packaged.
- A lookup fails when the file is not on any searched location, so the program receives no URL and the search must be traced back to where the file is stored.