Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4648386

Simplify deployment and versioning by embedding JAR files within each other

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 1.2.2, 1.3.0, 1.4.0, 5.0
    • tools
    • jar
    • generic, x86
    • generic, linux, windows_2000



      Name: jl125535 Date: 03/06/2002


      FULL PRODUCT VERSION :
      java version "1.4.0-rc"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
      Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]

      ADDITIONAL OPERATING SYSTEMS :
      Any O/S that supports the Java platform.


      A DESCRIPTION OF THE PROBLEM :
      Executable JAR files are a good and relatively simple way
      of deploying Java applications. When the JAR file contains
      a "Main-Class:" attribute, it becomes possible to launch
      the application by double-clicking on the file's icon (if
      supported by the client OS) or from the command line, as
      follows:

      java -jar some_app.jar

      or, where there are multiple entry-points (not just one
      main class):

      java -cp some_app.jar com.mycompany.MyMainClass

      However, there is a limitation with this approach. If the
      application contained within the JAR file depends upon
      other external JAR files, there is no straightforward way
      of bundling these files within the "main" JAR file.

      According to the JAR specifications, there is a Class-Path:
      attribute that can be specified in JAR manifest files.
      However, such paths can only be resolved relative to the
      URL from which the JAR file was loaded.

      For example, if the JAR file was loaded
      from "C:\java\apps\appli.jar", and the Class-Path:
      references "lib/other.jar", the class loader will look
      in "C:\java\apps\lib\" for "other.jar". It won't look at
      the JAR file entry "lib/other.jar". This example
      uses "file://" URLs, but the same sort of approach also
      applies to HTTP URLs, etc.

      As far as I aware, and based on my own attempts, there's no
      way to specify a Class-Path that makes the class loader
      look in embedded jar files. See the preceeding paragraph
      for a description.

      I suggest perhaps allow the Class-Path attribute to
      recognise by some path prefix or special URL protocol
      ("jar://", "self://"?) that the path refers to the inside
      of the JAR file. Alternatively, a new attribute could be
      added, such as "Jar-Internal-Class-Path:", specifically for
      finding classes (and, for that matter, any other resources
      that can be retrieved via getResource()). I prefer the
      second approach personally, as it avoids protocol
      conflicts, and is easier to understand and resolve. This
      should be recursive (embedded JARs should be recursively
      search for other embedded JARs).


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create a JAR file, "test.jar", containing some classes.

      2. Create another class that refers to classes contained
      within "test.jar". This should ideally be an executable
      class, i.e.: it should contain a "main()" method.

      3. Create another JAR file, "main.jar", including the class
      created in step 2 and the JAR file from step 1. Set the
      Main-Class: attribute to refer to the class from step 2.

      4. Try running the "main.jar", from a location that does
      not contain the other jar file (from step 1) or class file
      (from step 2); if these files are in the same folder
      as "main.jar" when you run it, then classes can be loaded
      from the current folder -- it won't need to look in the jar
      file (you may therefore wish to place "main.jar" in some
      other arbitrary folder before running it). It should
      complain that the class from step 2 cannot be found.

      5. Try step 3 with various different settings for the Class-
      Path: attribute in the META-INF/MANIFEST.MF file.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      I would like the classes from the embedded JAR file to
      become accessible. Instead, I get error messages as shown
      below (example).


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "main" java.lang.NoClassDefFoundError: B
              at A.main(A.java:3)


      This bug can be reproduced always.

      CUSTOMER WORKAROUND :
      1./
      Ask the end-user to manually install the required external
      libraries himself, either as an "extension" for the JVM or
      in a specific location. This is not desirable, as it makes
      the deployment process more complicated; depending on the
      type of end user, this may be quite offputting (non-
      trivial).

      2./
      Deploy the application as an archive (such as a ZIP file),
      and ask the user to decompress it. The main class is
      decompressed into a user-specified folder, and the external
      libraries are placed in the same folder or some subfolder.

      This allows Class-Path: to resolve, but is an additional
      step that could be eliminated by enhancing Java.
      Furthermore, this requires that the user has the
      appropriate decompression software.

      3./
      Possibly writing a custom classloader... if possible, this
      is a relatively time-consuming and complicated approach for
      the developer (not so much writing the classloader, as in
      understanding class visibility etc between different
      classloaders, which can often be confusing -- and it would
      be nice to maintain a high-level relatively abstract
      approach to software development in Java, instead of
      forcing developers to worry about "plumbing").
      Additionally, this may require granting certain security
      permissions (not sure about that though). This may be one
      means of implementing the enhancement, but I would prefer
      that this is integrated into the standard APIs and class-
      loading behaviour, and is transparent for the developer.

      4./
      Decompress all external JAR, then merge the contents of
      these JAR files into the main JAR file. If the "reverse
      domain name" convention for classes is respected, this
      should work for class files from different JAR files, but
      may cause conflicts for resources such
      as "conf/gui.conf", "i18n/text_en.properties", "images/splas
      h.png" in some cases where common names are used.
      Furthermore, there may be conflicts between different
      manifest files and it becomes difficult to include signed
      or sealed code correctly.
      (Review ID: 139046)
      ======================================================================

            Unassigned Unassigned
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: