沉睡森林@漂在北京

本处文章除注明“转载”外均为原创,转载请注明出处。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  152 随笔 :: 4 文章 :: 114 评论 :: 0 Trackbacks
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 URLClassLoaderJarClassLoader also makes use of features in two other new JAR-related APIs, the java.util.jarpackage and the java.net.JarURLConnection class. In this section, we'll look in detail at the constructor and two methods ofJarClassLoader.

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 inJarClassLoader 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 URLinstance, 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 theJarClassLoader 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 JarURLConnectionso 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 thegetMainAttributes 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.Nameclass also provides static fields such as MANIFEST_VERSIONCLASS_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.

posted on 2010-06-01 23:50 王总兵 阅读(291) 评论(0)  编辑  收藏 所属分类: Other

只有注册用户登录后才能发表评论。


网站导航: