com.jdotsoft.jarloader
Class JarClassLoader

java.lang.Object
  extended by java.lang.ClassLoader
      extended by com.jdotsoft.jarloader.JarClassLoader

public class JarClassLoader
extends ClassLoader

This class loader loads classes, native libraries and resources from the top JAR and from JARs inside top JAR. The loading process looks through JARs hierarchy and allows their tree structure, i.e. nested JARs.

The top JAR and nested JARs are included in the classpath and searched for the class or resource to load. The nested JARs could be located in any directories or subdirectories in a parent JAR.

All directories or subdirectories in the top JAR and nested JARs are included in the library path and searched for a native library. For example, the library "Native.dll" could be in the JAR root directory as "Native.dll" or in any directory as "lib/Native.dll" or "abc/xyz/Native.dll".

This class delegates class loading to the parent class loader and successfully loads classes, native libraries and resources when it works not in a JAR environment.

Create a Launcher class to use this class loader and start its main() method to start your application com.mycompany.MyApp

public class MyAppLauncher {

    public static void main(String[] args) {
        JarClassLoader jcl = new JarClassLoader();
        try {
            jcl.invokeMain("com.mycompany.MyApp", args);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    } // main()

} // class MyAppLauncher

An application could be started in two different environments:
1. Application is started from an exploded JAR with dependent resources locations defined in a classpath. Command line to start the application could point to the main class e.g. MyApp.main() or to the MyAppLauncher.main() class (see example above). The application behavior in both cases is identical. Application started with MyApp.main() uses system class loader and resources loaded from a file system. Application started with MyAppLauncher.main() uses JarClassLoader which transparently passes class loading to the system class loader.
2. Application is started from a JAR with dependent JARs and other resources inside the main JAR. Application must be started with MyAppLauncher.main() and JarClassLoader will load MyApp.main() and required resources from the main JAR.

Use VM parameters in the command line for logging settings (examples):

Known issues: some temporary files created by class loader are not deleted on application exit because JVM does not close handles to them. See details in shutdown().

See also discussion "How load library from jar file?" http://discuss.develop.com /archives/wa.exe?A2=ind0302&L=advanced-java&D=0&P=4549 Unfortunately, the native method java.lang.ClassLoader$NativeLibrary.unload() is package accessed in a package accessed inner class. Moreover, it's called from finalizer. This does not allow releasing the native library handle and delete the temporary library file. Option to explore: use JNI function UnregisterNatives(). See also native code in ...\jdk\src\share\native\java\lang\ClassLoader.class

Version:
$Revision: 1.36 $

Nested Class Summary
static class JarClassLoader.LogArea
           
static class JarClassLoader.LogLevel
           
 
Field Summary
static String KEY_LOGGER
          VM parameter key to turn on logging to file or console.
static String KEY_LOGGER_AREA
          VM parameter key to define log area.
static String KEY_LOGGER_LEVEL
          VM parameter key to define log level.
static String TMP_SUB_DIRECTORY
          Sub directory name for temporary files.
 
Constructor Summary
JarClassLoader()
          Default constructor.
JarClassLoader(ClassLoader parent)
          Constructor.
 
Method Summary
protected  String findLibrary(String sLib)
           
protected  URL findResource(String sName)
           
 Enumeration<URL> findResources(String sName)
           
 String getManifestMainClass()
          Returns the name of the jar file main class, or null if no "Main-Class" manifest attributes was defined.
 void invokeMain(String sClass, String[] args)
          Invokes main() method on class with provided parameters.
 boolean isLaunchedFromJar()
          Checks how the application was loaded: from JAR or file system.
protected  Class<?> loadClass(String sClassName, boolean bResolve)
          Class loader JavaDoc encourages overriding findClass(String) in derived class rather than overriding this method.
 
Methods inherited from class java.lang.ClassLoader
clearAssertionStatus, defineClass, defineClass, defineClass, defineClass, definePackage, findClass, findLoadedClass, findSystemClass, getPackage, getPackages, getParent, getResource, getResourceAsStream, getResources, getSystemClassLoader, getSystemResource, getSystemResourceAsStream, getSystemResources, loadClass, resolveClass, setClassAssertionStatus, setDefaultAssertionStatus, setPackageAssertionStatus, setSigners
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

KEY_LOGGER

public static final String KEY_LOGGER
VM parameter key to turn on logging to file or console.

See Also:
Constant Field Values

KEY_LOGGER_LEVEL

public static final String KEY_LOGGER_LEVEL
VM parameter key to define log level. Valid levels are defined in JarClassLoader.LogLevel. Default value is LogLevel#OFF.

See Also:
Constant Field Values

KEY_LOGGER_AREA

public static final String KEY_LOGGER_AREA
VM parameter key to define log area. Valid areas are defined in JarClassLoader.LogArea. Default value is JarClassLoader.LogArea.ALL. Multiple areas could be specified with ',' delimiter (no spaces!).

See Also:
Constant Field Values

TMP_SUB_DIRECTORY

public static final String TMP_SUB_DIRECTORY
Sub directory name for temporary files.

JarClassLoader extracts all JARs and native libraries into temporary files and makes the best attempt to clean these files on exit.

The sub directory is created in the directory defined in a system property "java.io.tmpdir". Verify the content of this directory periodically and empty it if required. Temporary files could accumulate there if application was killed.

See Also:
Constant Field Values
Constructor Detail

JarClassLoader

public JarClassLoader()
Default constructor. Defines system class loader as a parent class loader.


JarClassLoader

public JarClassLoader(ClassLoader parent)
Constructor.

Parameters:
parent - class loader parent.
Method Detail

isLaunchedFromJar

public boolean isLaunchedFromJar()
Checks how the application was loaded: from JAR or file system.

Returns:
true if application was started from JAR.

getManifestMainClass

public String getManifestMainClass()
Returns the name of the jar file main class, or null if no "Main-Class" manifest attributes was defined.

Returns:
Main class declared in JAR's manifest.

invokeMain

public void invokeMain(String sClass,
                       String[] args)
                throws Throwable
Invokes main() method on class with provided parameters.

Parameters:
sClass - class name in form "MyClass" for default package or "com.abc.MyClass" for class in some package
args - arguments for the main() method or null.
Throws:
Throwable - wrapper for many exceptions thrown while

(1) main() method lookup: ClassNotFoundException, SecurityException, NoSuchMethodException

(2) main() method launch: IllegalArgumentException, IllegalAccessException (disabled)

(3) Actual cause of InvocationTargetException See ://java.sun.com/developer/Books/javaprogramming /JAR/api/jarclassloader.html and ://java.sun.com/developer /Books/javaprogramming/JAR/api/example -1dot2/JarClassLoader.java


loadClass

protected Class<?> loadClass(String sClassName,
                             boolean bResolve)
                      throws ClassNotFoundException
Class loader JavaDoc encourages overriding findClass(String) in derived class rather than overriding this method. This does not work for loading classes from a JAR. Default implementation of loadClass() is able to load a class from a JAR without calling findClass().

Overrides:
loadClass in class ClassLoader
Throws:
ClassNotFoundException

findResource

protected URL findResource(String sName)
Overrides:
findResource in class ClassLoader
Returns:
A URL object for reading the resource, or null if the resource could not be found. Example URL: jar:file:C:\...\some.jar!/resources/InnerText.txt
See Also:
ClassLoader.findResource(java.lang.String)

findResources

public Enumeration<URL> findResources(String sName)
                               throws IOException
Overrides:
findResources in class ClassLoader
Returns:
An enumeration of URL objects for the resources
Throws:
IOException
See Also:
ClassLoader.findResources(java.lang.String)

findLibrary

protected String findLibrary(String sLib)
Overrides:
findLibrary in class ClassLoader
Returns:
The absolute path of the native library.
See Also:
ClassLoader.findLibrary(java.lang.String)


Copyright © 2012. All Rights Reserved.