Executable Jar Class-Path and INDEX.LST

13 05 2007

I’ve just spent a couple of hours trying to make a jar executable and wondering why it wasn’t finding classes in other jars, until eventually finding forum discussions here and here.

Basically, if the jar has a META-INF/INDEX.LST file then this needs to list all of the packages used, including those in “Class-Path” jars as well as those in the containing jar itself. This makes perfect sense once you realize what the purpose of INDEX.LST is and how it is used, as defined in the Jar File Specification.

But I wish I’d know about this when starting out! Two hours of double-checking the manifest’s “Main-Class” and “Path-Class” entries and looking for typos or syntax errors; trying different relative locations for the dependent jars; and reading and re-reading umpteen articles on how to make jars executable (none of which mentioned INDEX.LST).

It’s probably all very obvious to anyone that deals with this stuff all the time, but it’s not something I’ve had to dig into very often, and I guess I was a bit unlucky in what I thought I already know and the documentation that I came across along the way. I was also somewhat misled by seeing INDEX.LST as an “optimization” and taking this as meaning a speed-up that doesn’t actually affect behaviour – and therefore didn’t look more closely at exactly what it does. I really ought to know better, but from the content of the forum messages I’m not the only one who has been bitten by this.

So, just to spell this out for future reference, to make a jar executable when it uses classes and resources from other jars:

  • Its manifest needs a “Main-Class” entry specifying the canonical class name of the class whose “main” method is to be invoked.
  • Its manifest needs a “Class-Path” entry listing the other jars that need to be on the class path. This is a space-separated list of jars specified by their location “relative” to the executable jar’s own location (in the URI sense of “relative”: essentially, an absolute or relative path within the same host). In particular, if the jars will all be in the same directory, these are just the jar names on their own.
  • The syntax of manifest files is rather sensitive and pedantic, so you need to take care over exact spacing, line length, continuation lines etc.
  • When invoking the jar (typically as “java -jar xxxx.jar”), the java command ignores any “-cp” or “-classpath” argument, as the classpath is determined from the “Class-Path” entry of the jar’s manifest instead.
  • But in addition: The executable jar must either not have a META-INF/INDEX.LST file, or if it does have such an INDEX.LST file this needs to list the contents of both the executable jar and all of the other jars as well. Anything not in this list will not be found on the class path, regardless of the “Class-Path” entry in the manifest and regardless of any command-line “-classpath” (which is ignored anyway).

If you are using the Apache Ant jar task to build the jar, you can set the task’s “index” attribute to false to prevent it from generating the INDEX.LST file (with this being the default), or (for Ant 1.6.2 onwards) you can set it to true and supply a nested “indexjars” element to specify the jars whose contents should be included in the INDEX.LST file (though depending on your build process and the relationships between the jars, this might be more trouble than it’s worth).

In general I guess INDEX.LST should only be included if the jars are actually intended for loading over a network, where it serves its purpose of optimizing the fetching of the jars. In other scenarios it just introduces more complexity, undesirable dependencies and more ways for classes to not be found, so it’s probably simpler and safer to omit it.

It has always seemed to be just asking for trouble to have jar files specifying internally what other jars they need plus exactly what they are called, where they are located and what they contain… and to prevent any external setting of the classpath or any installation-specific configuration… but that’s jars for you: welcome to “jar hell”.

Hopefully JSR 277 (Java Module System) will sort some of this out and give us a much better approach for handling dependencies between jars.

Advertisements

Actions

Information

11 responses

26 02 2008
brian liddle

I don’t suppose you have an example of using the index attribute? I didn’t see one with ant but I agree, it sure looks like an after thought when you read the fine print….

26 02 2008
closingbraces

@Brian,

The Ant user manual for Ant 1.7.0 shows the “jar” task as having a boolean “index” attribute, no different to any other such attributes (e.g. use something like ‘<jar destfile=”xxxx.jar” index=”true” …’).

When used on its own this produces an INDEX.LST that just lists the jar’s own content, but if you want to include the contents of other jars you can specify them via a nested “indexjars” element whose value is an Ant “path-like structure” specifying the jars. It’s all there in the normal Ant documentation. I think it’s since Ant 1.6.2/1.6.3 onwards so if you can’t see it maybe you’ve got an earlier version of Ant.

If it’s examples of the INDEX.LST file itself that you’re looking for, there are examples in http://mail-archives.apache.org/mod_mbox/ant-dev/200211.mbox/%3C20021105133426.6963.qmail@nagoya.betaversion.org%3E
and http://javahowto.blogspot.com/2006/08/to-use-or-not-to-use-jar-index.html or look in the jars within Apache Tomcat – many of them (at least for Apache Tomcat 5.5.17) have META-INF/INDEX.LST files (albeit typically just listing their own content).

30 12 2008
Jeyakumar

Hi,
i am searching for this one very long time.now i found.. Really good …but i want to write the above operation in ant bulid.xml . So all the things happen with running of one build.xml file

please give me some suggestion , how to make it all in build.xm

30 12 2008
closingbraces

@Jeyakumar,

As per previous comment, you can do this with Ant’s “jar” task by specifying index=”true” and using a nested “indexjars” element that specifies the jars whose contents are to be included in the index. See Ant’s “jar” task documentation for details.

2 07 2009
anupam

i was finding this stuff for many hours and finally found here.
thanks alot

1 10 2009
Oskar

I was lost, bewildered and depressed and heading towards doom, and by a strike of pure golden luck, I stumbled here, and your information shone like a beakon of light! Er… I ment to say, thankyou, you saved my weekend and days and days of trying to get my ant build working. My culprit was the list file, that was unneccesary as per the information you host on this site! Thanks again!

2 10 2009
closingbraces

Oskar, you’re very welcome – glad it was of help.

I struggle to find time for blogging, and as I try to only cover things that I can’t find elsewhere and always worry about getting the details correct, it often seems like hard work. So it was a really nice treat to hear that this was useful to you – thanks for letting me know!

15 07 2010
dhalsim2

Thanks! I spent a lot more than your two hours trying to figure this out. Your post solved my problem.

20 05 2011
al

Very helpful. Took me forever to figure this out! Thanks alot.

12 03 2012
lwpro2

cool summary. thanks.

7 05 2013
FQL

Thanks a lot! I was also not understanding how I could be mispelling names and such.
I build the executable jar with maven assembly plugin and it generates this INDEX.LST file. I could not read a property file outside the jar but in the same directory while INDEX.LST existed. So, I deleted it inside the jar and bingo!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: