Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4648386
Votes 168
Synopsis Simplify deployment and versioning by embedding JAR files within each other
Category java:jar
Reported Against 1.3 , 1.4 , 1.2.2
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 4-Low
Related Bugs 6370714 , 4682074 , 4735639 , 6542800 , 4418643
Submit Date 06-MAR-2002
Description




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 :
 customer  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  customer  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) 
======================================================================
Work Around
N/A
Evaluation
Will be considered for future releases.


  xxxxx@xxxxx   2002-05-25
Comments
  
  Include a link with my name & email   

Submitted On 19-MAR-2002
gbentley2000
I agree totally with this, and I did raise a bug about it 
long ago and was told it was going to be fixed...seemingly 
not...

Personally I'd like to see something like a:
    JarClassLoader
that understands about embedded Jar files, i.e. if it 
cannot find the desired class in the "parent" Jar it then 
examines any "child" Jar files, it should then recurse 
until all "child" Jars have been checked.

Also an extension to JarURLConnection would be useful to 
get access to internal Jars, along the lines of:
	jar:http://myhost/my.jar!/mydir/my_other.jar!/

Again, any level should be supportable...

Also, surely the CLASSPATH could then be specified to use 
the same syntax as JarURLConnection???

The only trouble I could see here is that there would be 
quite a number of places that would need updating.

However with the advent of J2EE EAR files surely there is 
a need for a standard method of doing this?  Also, since 
most of us want to deploy our Client Applications (and 
Server Applications) in a single file internal Jars are 
very useful, especially when you have 3rd-party Jars to 
embed.


Submitted On 18-APR-2002
tobidelbruck
I also completely agree with this. I have run into this
problem and it had me completely stumped because sometimes
it all seemed to work, but it only worked because I had my
CLASSPATH set to point to the jars already installed.  Now I
understand the problem.  I will try to make the installer
program install the external jars now in a subdirectory jars
of the install directory, and put the correct relative URL
(like jars/colt.jar) in the manifest Class-Path property.

This limitation is completely undocumented in sun's jar file
documentation
http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html
-tobi@ini.phys.ethz.ch


Submitted On 26-AUG-2002
chris_e_brown
Perhaps an even more robust solution:

I would still like to be able to deploy JAR files with embedded 
dependent libraries so that I can distribute "one-click 
runnable" applications.  However, versioning is one issue I 
didn't fully explore in my original proposal...  I might suggest 
that when an embedded JAR file has proper versioning 
information in the META-INF/ folder, that some sort of central 
JAR registry is updated, making that new version available to 
other applications or allowing my deployed application to 
benefit from subsequent more recent versions of the JAR file 
(superseding my embedded version) if and when they become 
available and are installed.

In more detail, I'd consider extending the Java Plug-in Control 
Panel (or other platform equivalent) to become the Runtime 
Control Panel, from where other JVM properties could be set.  
Such as a common JAR registry, that can be specific to one 
JVM or shared between several JVMs.  This could even 
support "javax" libraries and endorsed libraries.  It would be 
possible to manually install libraries, and have multiple 
versions side-by-side (such as javamail 1.1, 1.2, etc.), with 
applications either requesting version x.x specifically, or 
defining a range of acceptable versions, or just asking for any 
version of a specific library).

The relationship between embedded JARs and the above JAR 
registry/repository is that when I install an executable JAR file 
with embedded libraries, I'm not forced to use the embedded 
versions of libraries if the host computer contains more recent 
versions.  This is equivalent to static-linking of libraries, which 
has the advantage of ensuring compatibility, but the 
disadvantage of being inefficient with library updates and 
when a given library is used in lots of applications, and would 
therefore be embedded in lots of JAR files, which is a bit 
wasteful...

One other concern I've had is with licencing issues.  It might 
be possible to embed a library without making its licencing 
conditions explicity clear.  It might be worth extending the 
JAR file specification to state that if a library contains 
a "licence" file in it's META-INF folder that the user must 
agree to the licence before running the JAR file containing the 
embedded library.  This isn't foolproof, but does help legal 
requirements.  Obviously the licence could be removed, but 
that's a form of cracking, which is a different issue again (but 
that's no less secure than deploying code that can be 
reverse-engineered).

Last fun idea with a JAR registry/repositry: make JAR files 
deployable using technology similar to Java Web Start (or 
even Windows Update) where the user can choose to have 
latest JARs installed as and when they become available.


Submitted On 19-JAN-2004
MartinHilpert
my vote here!


Submitted On 09-FEB-2004
wensveen
I agree, please fix this problem. Solution needed urgently!
Suggest looking into namespace idea. IE: jar:// etc.


Submitted On 11-FEB-2004
theaps
So almost 2 years have passed and there STILL 
doesn't seem to be any acticity on this bug. I haven't 
checked related bugs yet, but taking this one for face 
value, I am suprised that there isn't at least some effort 
to address this problem. This to me seems like 
something MANY java applications would need! Wow, 
what a disappointment...


Submitted On 14-APR-2004
Christian_Schuhegger
my vote, too!!

there seems to be a workaround at:
http://www.yagga.net/java/metajar/

but i did not try it yet.


Submitted On 17-JAN-2005
paulbrickell
Although this comes in rather late, I would like to second chris_e_brown's suggestion. Any environment that wants to be considered prime time should support modular/component development. All the Java applications I have worked on have ended up as monolithic, with upgrades consisting of replacing everything. 

With a vibrant open source community providing all kinds of 'utility' classes We are already getting problems with incompatible versions of classes being required (Sun's very own version of dll hell). What about a jar registry and some metadata with dependency analysis. 

Come on Sun let catch up with .NET.


Submitted On 22-JAN-2006
buzmeg
This bug has gone moribund when it is still extant.  What is going on with it?  Has there been any activity?  If so where?


Submitted On 03-FEB-2006
I needed this as well. I found a reasonable solution at http://www-128.ibm.com/developerworks/java/library/j-onejar/#resources.
This solution uses an Eclipse plug-in, but can be made independent of Eclipse because the plugin exports an ant file.
But I think that the jar classloader should be modified to have this ability


Submitted On 24-FEB-2006
This gets my vote too ... give JAR files some structure like WARs to execute classes embedded in contained third-party JARs.  I'm really surprised this hasn't happened yet.


Submitted On 17-JUN-2006
DewinCymraeg
I've been frustrated by this in the passed. To me, it seems only logic.


Submitted On 03-JUL-2006
I also agree with this proposed RFE. As I am also working in very important production environment (stock exchange trading system) I have found very important to have secure and reliable distribution of java application. You know this sentence : I have same application like you running on my PC but it does not work  Unfortunately I think it is one of the greatest disadvantages of Java deployment issue not to be sure whether the application will run with same jar files if some of them are elsewhere or another version. 


Submitted On 28-JUL-2006
neerajapte
I vote for this as well.
Actually just because of this, we are giving up plans for using Java Web Start to deploy our application. Java Web Start requires a single jar. Our application has dependencies on other third party jars and we cannot include those as classes without license violations! What a bummer!!


Submitted On 03-AUG-2006
dmouse
Distribution of jar files is unnecessarily complex due to this.  We'd love to distribute all necessary jar files for a product in a single jar.  Due to this problem we can't.  This makes it unnecessarily messy to set up classpaths which quickly become unmanageable.  This bug has been here for 4 years and has 88 votes!


Submitted On 28-AUG-2006
evickroy
Someone stated this:
" Submitted On 28-JUL-2006

I vote for this as well.
Actually just because of this, we are giving up plans for using Java Web Start to deploy our application. Java Web Start requires a single jar. Our application has dependencies on other third party jars and we cannot include those as classes without license violations! What a bummer!!"

Java Webstart supports the use of more than one jar file.  Each jar file is an additional resource element.  If a jar file is already signed, then you can give that jar file its own JNLP file and reference it as a resource extension.  In Java 5, this is how you deploy a signed application that has jar files with different signatures.


Submitted On 01-SEP-2006
jhantin
Have you considered uberjar?

http://classworlds.codehaus.org/uberjar.html


Submitted On 06-DEC-2006
dineshkumarsingh
This bug is pending for more than 4 years..
Can it be fixed in coming 4 years............


Submitted On 22-MAR-2007
Five years now...

I also vote for this feature because it would greatly improve the deployment of Java applications!

Please, Sun, implement it! :-)


Submitted On 21-APR-2007
I am also strugling for this and requesting to solve this as soon as possible. 


Submitted On 25-MAY-2007
Volker.S
comeon Sun, please just integrated this fixed Classloader:
http://fjep.sourceforge.net/


Submitted On 03-JUN-2007
rpajerski
This is a barrier for Java on the desktop.  I need to call already installed, third-party Jars from my Swing app which I'd like to be able to distribute both as a regular Jar and via Web Start.  Neither option is possible due to this problem (short of writing my own classloader).  Even if I could bundle the third-party Jars (which is not legal in my case) that solution is not ideal b/c there are multiple versions of them.  I'm left with distributing a bunch of class files which will work but is messy and more confusing for my customer.  This is a bug b/c the concept of CLASSPATH does not work as expected:  the Jar classloader doesn't look everywhere it should.


Submitted On 09-JUN-2007
iabdel40
I came to this page after I spent three months looking for a solution to this proplem, I though it is possible to package jar files within one jar file in the same way as  a war or ear files.

I totally support this fix it make deployment very flexible, almost every application has dependency on third party library.

Isam M. Abdelhameed
NORC 'National Reaserch Center"


Submitted On 01-AUG-2007
beirtipol
I can't believe that this still hasn't been dealt with.

Over 5 years of fudging the packaging of an app.

PLEASE Fix it!


Submitted On 15-NOV-2007
I vote for this enhancement to be done ASAP as well :) I wish I could fix it myself, but I am just a newbie in java.


Submitted On 18-JAN-2008
kht
I can't add much to what's already been posted by others. I've been working on pure J2EE development for years where this is just a given with *.war, and *.ear files. 
Can someone from Sun at least respond?????? 


Submitted On 24-JAN-2008
http://one-jar.sourceforge.net/ has a solution to deploying all your jar-files as one jar file


Submitted On 17-OCT-2008
grima
I like the idea of a fatjar. There is also a lot of stuff around that will help you make one, but out-of-the-box support would totally make my day.



PLEASE NOTE: JDK6 is formerly known as Project Mustang