Download the JDK
Search the Tutorials
Hide the TOC
Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR-related APIs
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
The JarClassLoader Class

> The `JarClassLoader` class extends `java.net.URLClassLoader`. As its name implies, `URLClassLoader` is designed to be used for loading classes and resources that are accessed by searching a set of URLs. The URLs can refer either to directories or to JAR files.

> In addition to subclassing `URLClassLoader`, `JarClassLoader` also makes use of features in two other new JAR-related APIs, the `java.util.jar` package and the `java.net.JarURLConnection` class. In this section, we'll look in detail at the constructor and two methods of `JarClassLoader`.

### The JarClassLoader Constructor

> The constructor takes an instance of `java.net.URL` as an argument. The URL passed to this constructor will be used elsewhere in `JarClassLoader` to find the JAR file from which classes are to be loaded.

> >     public JarClassLoader(URL url) {
> >         super(new URL[] { url });
> >         this.url = url;
> >     }

> The `URL` object is passed to the constructor of the superclass, `URLClassLoader`, which takes a `URL[]` array, rather than a single `URL` instance, as an argument.

### The getMainClassName Method

> Once a `JarClassLoader` object is constructed with the URL of a JAR-bundled application, it's going to need a way to determine which class in the JAR file is the application's entry point. That's the job of the `getMainClassName` method:

> >     public String getMainClassName() throws IOException {
> >         URL u = new URL("jar", "", url + "!/");
> >         JarURLConnection uc = (JarURLConnection)u.openConnection();
> >         Attributes attr = uc.getMainAttributes();
> >         return attr != null
> >                        ? attr.getValue(Attributes.Name.MAIN_CLASS)
> >                        : null;
> >     }

> You may recall from a previous lesson that a JAR-bundled application's entry point is specified by the `Main-Class` header of the JAR file's manifest. To understand how `getMainClassName` accesses the `Main-Class` header value, let's look at the method in detail, paying special attention to the new JAR-handling features that it uses:

> ### The JarURLConnection class and JAR URLs

> The `getMainClassName` method uses the JAR URL format specified by the `java.net.JarURLConnection` class. The syntax for the URL of a JAR file is as in this example:

> >     jar:http://www.xxx.yyy/jarfile.jar!/

> The terminating `!/` separator indicates that the URL refers to an entire JAR file. Anything following the separator refers to specific JAR-file contents, as in this example:

> >     jar:http://www.xxx.yyy/jarfile.jar!/mypackage/myclass.class

> The first line in the `getMainClassName` method is:

> >     URL u = new URL("jar", "", url + "!/");

> This statement constructs a new `URL` object representing a JAR URL, appending the `!/` separator to the URL that was used in creating the `JarClassLoader` instance.

> ### The java.net.JarURLConnection class

> This class represents a communications link between an application and a JAR file. It has methods for accessing the JAR file's manifest. The second line of `getMainClassName` is:

> >     JarURLConnection uc = (JarURLConnection)u.openConnection();

> In this statement, `URL` instance created in the first line opens a `URLConnection`. The `URLConnection` instance is then cast to `JarURLConnection` so it can take advantage of `JarURLConnection`'s JAR-handling features.

> ### Fetching Manifest Attributes: java.util.jar.Attributes

> With a `JarURLConnection` open to a JAR file, you can access the header information in the JAR file's manifest by using the `getMainAttributes` method of `JarURLConnection`. This method returns an instance of `java.util.jar.Attributes`, a class that maps header names in JAR-file manifests with their associated string values. The third line in `getMainClassName` creates an `Attributes` object:

> >     Attributes attr = uc.getMainAttributes();

> To get the value of the manifest's `Main-Class` header, the fourth line of `getMainClassName` invokes the `Attributes.getValue` method:

> >     return attr != null
> >                    ? attr.getValue(Attributes.Name.MAIN_CLASS)
> >                    : null;

> The method's argument, `Attributes.Name.MAIN_CLASS`, specifies that it's the value of the `Main-Class` header that you want. (The `Attributes.Name` class also provides static fields such as `MANIFEST_VERSION`, `CLASS_PATH`, and `SEALED` for specifying other standard manifest headers.)

### The invokeClass Method

> We've seen how `JarURLClassLoader` can identify the main class in a JAR-bundled application. The last method to consider, `JarURLClassLoader.invokeClass`, enables that main class to be invoked to launch the JAR-bundled application:

> >     public void invokeClass(String name, String[] args)
> >         throws ClassNotFoundException,
> >                NoSuchMethodException,
> >                InvocationTargetException
> >     {
> >         Class c = loadClass(name);
> >         Method m = c.getMethod("main", new Class[] { args.getClass() });
> >         m.setAccessible(true);
> >         int mods = m.getModifiers();
> >         if (m.getReturnType() != void.class || !Modifier.isStatic(mods) ||
> >             !Modifier.isPublic(mods)) {
> >             throw new NoSuchMethodException("main");
> >         }
> >         try {
> >             m.invoke(null, new Object[] { args });
> >         } catch (IllegalAccessException e) {
> >             // This should not happen, as we have disabled access checks
> >         }
> >     }

> The `invokeClass` method takes two arguments: the name of the application's entry-point class and an array of string arguments to pass to the entry-point class's `main` method. First, the main class is loaded:

> >     Class c = loadClass(name);

> The `loadClass` method is inherited from `java.lang.ClassLoader`.

> Once the main class is loaded, the reflection API of the `java.lang.reflect` package is used to pass the arguments to the class and launch it. You can refer to the tutorial on The Reflection API for a review of reflection.

« Previous • Trail • Next »
Previous page: Using JAR-related APIs
Next page: The JarRunner Class