有关InvalidJarIndexException的问题?

时间:2010-08-05 17:06:50

标签: java indexing jar applet

我浏览了JAR规范文档,发现使用hashtable文件创建了一个内存中INDEX.LST,以加快类文件查找过程。

如果有人可以回答我的以下问题 -

  1. hashtable何时构建?当应用程序加载或请求加载小程序时?

  2. 由于所有课程都已归档,因此为什么要获得InvalidJarIndexException。索引如何变得无效?例如在我的情况下,当我在我的ant构建中使用InvalidJarIndexExceptionindex=true时,我得到indexjars但是当我没有使用indexjars时我没有看到任何异常。

  3. 如果我想坚持索引,我应该如何解决InvalidJarIndexException

  4. java浏览器插件在下载jar文件中的作用?

3 个答案:

答案 0 :(得分:0)

我从来没有遇到过这个问题,所以我不能不帮助你,但我会尽力减轻你的负担。

  1. 它是在类加载器加载时构造的:类加载器本身会查找index.list文件并在可用时使用它。

  2. 如果index.list文件已损坏,您可以获得此异常,因为如果类加载器找到了索引文件,它将不再在类路径中查找以加载类:它将< strong>仅使用索引。在这里,似乎它甚至无法加载它,因此抛出InvalidJarIndexException

  3. 尝试使用index.list选项,使用jar工具手动生成-i。如果它有效,那么这是一个蚂蚁问题:比较生成的文件进行调查。如果它仍然不起作用,请手动检查index.list文件(错误编码?截断长路径?缺少类?)。

  4. 无关。类加载过程由类加载器完成。 jar文件实际运行的方式并不重要。

  5. 编辑以添加Devil Jin的评论:

      

    蚂蚁中的索引早先出现了错误。   您需要使用1.6或更高版本   使索引工作。得到一个罐子   索引你必须设置index = true   以及在其中指定jar文件    indexjars 标记。   ant.apache.org/manual/Tasks/jar.html#indexjars

答案 1 :(得分:0)

JarIndex似乎对applet和网络很有用。它可以防止加载不必要的档案。

这里我们有一个所谓的根jar ,它包含一个INDEX.LIST文件,该文件包含从类到库的映射。类加载器将读取文件,创建内部哈希表并使用此表来确定可以找到类的位置。如果尚未加载库,则会加载它以加载类。否则,它必须立即加载所有库才能解析单个类(因为类名永远不会提供任何可以找到类的线索)

一旦类加载器找到这样的索引,它就会信任该信息,并且如果信息不正确则会引发异常。假设索引告诉类加载器com.example.MyClass可以在http://example.com/a.jar中找到,然后它将下载(如果尚未完成)jar并且只查看该库内部。如果没有这样的类,它将在不同的罐子中查找(甚至下载额外的罐子)但是会有一个驼峰(并抛出异常)。

如果你遇到这样的例外,你可能会很丢失。问题(损坏的INDEX.LIST文件)无法在消费者方面修复。但是因为类加载器需要类路径中第一个jar中的INDEX.LIST文件,所以更改类路径表达式中库的顺序可以通过禁用索引器功能来解决这个问题。


进一步阅读


使用ant的工作示例

我创建了两个非常简单的类来打印Hello world:

package test;

public class Hello {
    public static void main(String[] args) {
        System.out.println(HelloTextFactory.createResponse());
    }
}

package test;

public class HelloTextFactory {
    public static String createResponse() {
        return "Hello world";
    }
}

和一个用于创建档案的ant文件(build.xml):

<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>

此构建文件假定在运行脚本之前已将类编译到bin文件夹中。

运行构建脚本会创建两个jar,main.jar包含一个索引,java -jar main.jar成功运行。然后我将第二个类移动到另一个包中并再次启动构建。再次,它创建了一个有效的应用程序。

在实验过程中,我意识到了

  • 有必要强制创造所有的罐子,尤其是主罐子。如果ant重建factory.jar,则索引将不会更新,并且可能无效。这就是我添加delete任务的原因。
  • 在创建所有其他jar后,必须创建
  • main.jar

答案 2 :(得分:0)

此代码段可以帮助您调查它:

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/.$//'`"

或只是

jar -tf main.jar