{"id":371,"date":"2007-10-21T00:00:00","date_gmt":"2007-10-21T00:00:00","guid":{"rendered":"http:\/\/www.strongd.net\/?p=371"},"modified":"2007-10-21T00:00:00","modified_gmt":"2007-10-21T00:00:00","slug":"The JarClassLoader Class","status":"publish","type":"post","link":"https:\/\/www.strongd.net\/?p=371","title":{"rendered":"The JarClassLoader Class"},"content":{"rendered":"<p><DIV id=PageTitle>The JarClassLoader Class<\/DIV><br \/>\n<BLOCKQUOTE>The <TT>JarClassLoader<\/TT> class extends <TT>java.net.URLClassLoader<\/TT>. As its name implies, <TT>URLClassLoader<\/TT> 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.<br \/>\n<P>In addition to subclassing <TT>URLClassLoader<\/TT>, <TT>JarClassLoader<\/TT> also makes use of features in two other new JAR-related APIs, the <TT>java.util.jar<\/TT> package and the <TT>java.net.JarURLConnection<\/TT> class. In this section, we&#8217;ll look in detail at the constructor and two methods of <TT>JarClassLoader<\/TT>. <\/P><\/BLOCKQUOTE><br \/>\n<H3>The JarClassLoader Constructor<\/H3><br \/>\n<BLOCKQUOTE>The constructor takes an instance of <TT>java.net.URL<\/TT> as an argument. The URL passed to this constructor will be used elsewhere in <TT>JarClassLoader<\/TT> to find the JAR file from which classes are to be loaded.<br \/>\n<BLOCKQUOTE><PRE>public JarClassLoader(URL url) {<br \/>\n    super(new URL[] { url });<br \/>\n    this.url = url;<br \/>\n}<br \/>\n<\/PRE><\/BLOCKQUOTE>The <TT>URL<\/TT> object is passed to the constructor of the superclass, <TT>URLClassLoader<\/TT>, which takes a <TT>URL[]<\/TT> array, rather than a single <TT>URL<\/TT> instance, as an argument. <\/BLOCKQUOTE><br \/>\n<H3>The getMainClassName Method<\/H3><br \/>\n<BLOCKQUOTE>Once a <TT>JarClassLoader<\/TT> object is constructed with the URL of a JAR-bundled application, it&#8217;s going to need a way to determine which class in the JAR file is the application&#8217;s entry point. That&#8217;s the job of the <TT>getMainClassName<\/TT> method:<br \/>\n<BLOCKQUOTE><PRE>public String getMainClassName() throws IOException {<br \/>\n    URL u = new URL(&#8220;jar&#8221;, &#8220;&#8221;, url + &#8220;!\/&#8221;);<br \/>\n    JarURLConnection uc = (JarURLConnection)u.openConnection();<br \/>\n    Attributes attr = uc.getMainAttributes();<br \/>\n    return attr != null<br \/>\n                   ? attr.getValue(Attributes.Name.MAIN_CLASS)<br \/>\n                   : null;<br \/>\n}<br \/>\n<\/PRE><\/BLOCKQUOTE>You may recall from a <A href=\"http:\/\/www.strongd.net\/blog\/show\/369#1.2\">previous lesson<\/A> that a JAR-bundled application&#8217;s entry point is specified by the <TT>Main-Class<\/TT> header of the JAR file&#8217;s manifest. To understand how <TT>getMainClassName<\/TT> accesses the <TT>Main-Class<\/TT> header value, let&#8217;s look at the method in detail, paying special attention to the new JAR-handling features that it uses:<br \/>\n<H3>The JarURLConnection class and JAR URLs<\/H3>The <TT>getMainClassName<\/TT> method uses the JAR URL format specified by the <TT>java.net.JarURLConnection<\/TT> class. The syntax for the URL of a JAR file is as in this example:<br \/>\n<BLOCKQUOTE><PRE>jar:http:\/\/www.xxx.yyy\/jarfile.jar!\/<br \/>\n<\/PRE><\/BLOCKQUOTE>The terminating <TT>!\/<\/TT> 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:<br \/>\n<BLOCKQUOTE><PRE>jar:http:\/\/www.xxx.yyy\/jarfile.jar!\/mypackage\/myclass.class<br \/>\n<\/PRE><\/BLOCKQUOTE><br \/>\n<P>The first line in the <TT>getMainClassName<\/TT> method is: <\/P><br \/>\n<BLOCKQUOTE><PRE>URL u = new URL(&#8220;jar&#8221;, &#8220;&#8221;, url + &#8220;!\/&#8221;);<br \/>\n<\/PRE><\/BLOCKQUOTE>This statement constructs a new <TT>URL<\/TT> object representing a JAR URL, appending the <TT>!\/<\/TT> separator to the URL that was used in creating the <TT>JarClassLoader<\/TT> instance.<br \/>\n<P><\/P><br \/>\n<H3>The java.net.JarURLConnection class<\/H3>This class represents a communications link between an application and a JAR file. It has methods for accessing the JAR file&#8217;s manifest. The second line of <TT>getMainClassName<\/TT> is:<br \/>\n<BLOCKQUOTE><PRE>JarURLConnection uc = (JarURLConnection)u.openConnection();<br \/>\n<\/PRE><\/BLOCKQUOTE>In this statement, <TT>URL<\/TT> instance created in the first line opens a <TT>URLConnection<\/TT>. The <TT>URLConnection<\/TT> instance is then cast to <TT>JarURLConnection<\/TT> so it can take advantage of <TT>JarURLConnection<\/TT>&#8216;s JAR-handling features.<br \/>\n<H3>Fetching Manifest Attributes: java.util.jar.Attributes<\/H3>With a <TT>JarURLConnection<\/TT> open to a JAR file, you can access the header information in the JAR file&#8217;s manifest by using the <TT>getMainAttributes<\/TT> method of <TT>JarURLConnection<\/TT>. This method returns an instance of <TT>java.util.jar.Attributes<\/TT>, a class that maps header names in JAR-file manifests with their associated string values. The third line in <TT>getMainClassName<\/TT> creates an <TT>Attributes<\/TT> object:<br \/>\n<BLOCKQUOTE><PRE>Attributes attr = uc.getMainAttributes();<br \/>\n<\/PRE><\/BLOCKQUOTE><br \/>\n<P>To get the value of the manifest&#8217;s <TT>Main-Class<\/TT> header, the fourth line of <TT>getMainClassName<\/TT> invokes the <TT>Attributes.getValue<\/TT> method: <\/P><br \/>\n<BLOCKQUOTE><PRE>return attr != null<br \/>\n               ? attr.getValue(Attributes.Name.MAIN_CLASS)<br \/>\n               : null;<br \/>\n<\/PRE><\/BLOCKQUOTE><br \/>\n<P><\/P>The method&#8217;s argument, <TT>Attributes.Name.MAIN_CLASS<\/TT>, specifies that it&#8217;s the value of the <TT>Main-Class<\/TT> header that you want. (The <TT>Attributes.Name<\/TT> class also provides static fields such as <TT>MANIFEST_VERSION<\/TT>, <TT>CLASS_PATH<\/TT>, and <TT>SEALED<\/TT> for specifying other standard manifest headers.) <\/BLOCKQUOTE><br \/>\n<H3>The invokeClass Method<\/H3><br \/>\n<BLOCKQUOTE>We&#8217;ve seen how <TT>JarURLClassLoader<\/TT> can identify the main class in a JAR-bundled application. The last method to consider, <TT>JarURLClassLoader.invokeClass<\/TT>, enables that main class to be invoked to launch the JAR-bundled application:<br \/>\n<BLOCKQUOTE><PRE>public void invokeClass(String name, String[] args)<br \/>\n    throws ClassNotFoundException,<br \/>\n           NoSuchMethodException,<br \/>\n           InvocationTargetException<br \/>\n{<br \/>\n    Class c = loadClass(name);<br \/>\n    Method m = c.getMethod(&#8220;main&#8221;, new Class[] { args.getClass() });<br \/>\n    m.setAccessible(true);<br \/>\n    int mods = m.getModifiers();<br \/>\n    if (m.getReturnType() != void.class || !Modifier.isStatic(mods) ||<br \/>\n        !Modifier.isPublic(mods)) {<br \/>\n        throw new NoSuchMethodException(&#8220;main&#8221;);<br \/>\n    }<br \/>\n    try {<br \/>\n        m.invoke(null, new Object[] { args });<br \/>\n    } catch (IllegalAccessException e) {<br \/>\n        \/\/ This should not happen, as we have disabled access checks<br \/>\n    }<br \/>\n}<br \/>\n<\/PRE><\/BLOCKQUOTE><br \/>\n<P>The <TT>invokeClass<\/TT> method takes two arguments: the name of the application&#8217;s entry-point class and an array of string arguments to pass to the entry-point class&#8217;s <TT>main<\/TT> method. First, the main class is loaded: <\/P><br \/>\n<BLOCKQUOTE><PRE>Class c = loadClass(name);<br \/>\n<\/PRE><\/BLOCKQUOTE>The <TT>loadClass<\/TT> method is inherited from <TT>java.lang.ClassLoader<\/TT>.<br \/>\n<P><\/P><br \/>\n<P>Once the main class is loaded, the reflection API of the <TT>java.lang.reflect<\/TT> package is used to pass the arguments to the class and launch it. You can refer to the tutorial on <A href=\"http:\/\/java.sun.com\/docs\/books\/tutorial\/reflect\/index.html\">The Reflection API<\/A> for a review of reflection. <\/P><\/BLOCKQUOTE><br \/>\n<DIV><\/DIV><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/www.strongd.net\/?p=371\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">The JarClassLoader Class<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-371","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/371","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=371"}],"version-history":[{"count":0,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/371\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}