Questions regarding InvalidJarIndexException?
I went through the JAR specification document and found that an in-memory hashtable
is created using INDEX.LST
file to speed up the class file look up process.
If any one can answer my following questions -
When is the
hashtable
constructed? When the application loads or when the request comes for loading the applet?Since all the classes are already part of the archive, why should one get
InvalidJarIndexException
. How can indexes become invalid? e.g. In my case I getInvalidJarIndexException
when I useindex=true
along withindexjars
in my ant build but I do not see any exceptions when indexjars are not used.How should I go about resolving the
InvalidJarIndexException
if I want to st开发者_高级运维ick with indexing?Role of java browser plugin in downloading jar files?
JarIndex seems to be useful for applets and networking. It can prevent from loading unnecessary archives.
Here we have a so called root jar which includes an INDEX.LIST
file and that file includes a mapping from class to library. The classloader will read the file, create an internal hashtable and use this table to determine, where a class can be found. If the library has not been loaded yet, then it will load it to load the class. Otherwise it would have to load all libraries at once just to resolve a single class (because a class name never gives any clue where a class can be found)
Once the classloader finds such an index, it trusts that information and will complain with an exception if the information is not true. Say the index tells the classloader that com.example.MyClass
can be found inside http://example.com/a.jar
, then it will download (if not already done) the jar and only look inside this library. If there's no such class it will not look in different jars (or even download additional jars) but will have a hump with you (and throw an exception).
If you encounter such an exception you might be pretty lost. The problem (corrupt INDEX.LIST file) can't be fixed on the consumers side. But because the classloader expects the INDEX.LIST
file in the first jar on the classpath, changing the order of libraries in the classpath expression could solve such a problem by disabling the indexer feature.
Further Reading
- Possible InvalidJarIndexException due to bug in sun.misc.JarIndex.merge()
Working Example with ant
I created two very simple classes to print Hello world:
package test;
public class Hello {
public static void main(String[] args) {
System.out.println(HelloTextFactory.createResponse());
}
}
and
package test;
public class HelloTextFactory {
public static String createResponse() {
return "Hello world";
}
}
and an ant file (build.xml) to create the archives:
<project name="test">
<target name="jar" description="description">
<delete file="main.jar" />
<delete file="factory.jar" />
<jar destfile="factory.jar" includes="test/HelloTextFactory.class" basedir="bin" />
<jar destfile="main.jar" includes="test/Hello.class" basedir="bin" index="true">
<indexjars>
<fileset dir="." id="jars">
<include name="factory.jar" />
</fileset>
</indexjars>
<manifest>
<attribute name="Main-Class" value="test.Hello" />
<attribute name="Class-Path" value="factory.jar" />
</manifest>
</jar>
</target>
</project>
This build file assumes that the classes have been compiled into the bin
folder before running the script.
Running the build script creates two jars, main.jar contains an index and java -jar main.jar
runs successfully. Then I moved the second class into a different package and started the build again. And again, it created a working application.
During experimentation I realized that
- it is necessary to force creation of all jars, especially the main jar. If ant rebuilds
factory.jar
the index will not be updated and may be invalid. That's why I added thedelete
tasks. main.jar
has to be created after all other jars are created.
I've never came across this problem, so I'm unfraid I won't help you much, but I'll do my best to lighten things up.
It's constructed when the class loader loads: the class loader itself looks for an
index.list
file and use it if it's available.You can get this exception if the
index.list
file is corrupted, because if the class loader has found an index file, it won't look in the classpath anymore to load a class: it will only use the index. Here, it seems it can't even load it, so it throwsInvalidJarIndexException
Try to manually generate the
index.list
with thejar
tool, using the-i
option. If it works, then it's an ant issue: compare the generated files to investigate. If it still doesn't work, inspect the index.list file manually (bad encoding ? truncated long paths ? missing classes ?).Irrelevant. The class loading process is done by the class loader. The way the jar file is actually run doesn't matter.
Edit to add Devil Jin's comment:
The indexing in ant had bugs earlier. You need to use versions 1.6 or after to get indexing working. To get a jar indexed you have to set index=true along with specifying jar files within indexjars tag. ant.apache.org/manual/Tasks/jar.html#indexjars
Could this snippet help you in investigating it:
echo -e "\n`jar -tf main.jar | sed -e '/.class/d' -e '/.properties/d' -e '/services\/./d' -e '/.res/d' -e '/NOTICE/d' -e '/LICENSE/d' -e '/MANIFEST.MF/d' -e 's/.$//'`"
or just
jar -tf main.jar
精彩评论