6

我正在创建一个 cli 工具来管理现有应用程序。应用程序和测试都构建良好并且运行良好,但尽管我在运行 jar 中存在的 cli 工具时收到 javassist 失败:

INFO: Bytecode provider name : javassist
...
INFO: Hibernate EntityManager 3.5.1-Final
Exception in thread "main" javax.persistence.PersistenceException: Unable to configure EntityManagerFactory
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:371)
        at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:55)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
        ...
        at com.sophware.flexipol.admin.AdminTool.<init>(AdminTool.java:40)
        at com.sophware.flexipol.admin.AdminTool.main(AdminTool.java:69)
Caused by: java.lang.RuntimeException: Error while reading file:flexipol-jar-with-dependencies.jar
        at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:131)
        at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:467)
        at org.hibernate.ejb.Ejb3Configuration.addMetadataFromScan(Ejb3Configuration.java:457)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:347)
        ... 11 more
Caused by: java.io.IOException: invalid constant type: 60
        at javassist.bytecode.ConstPool.readOne(ConstPool.java:1027)
        at javassist.bytecode.ConstPool.read(ConstPool.java:970)
        at javassist.bytecode.ConstPool.<init>(ConstPool.java:127)
        at javassist.bytecode.ClassFile.read(ClassFile.java:693)
        at javassist.bytecode.ClassFile.<init>(ClassFile.java:85)
        at org.hibernate.ejb.packaging.AbstractJarVisitor.checkAnnotationMatching(AbstractJarVisitor.java:243)
        at org.hibernate.ejb.packaging.AbstractJarVisitor.executeJavaElementFilter(AbstractJarVisitor.java:209)
        at org.hibernate.ejb.packaging.AbstractJarVisitor.addElement(AbstractJarVisitor.java:170)
        at org.hibernate.ejb.packaging.FileZippedJarVisitor.doProcessElements(FileZippedJarVisitor.java:119)
        at org.hibernate.ejb.packaging.AbstractJarVisitor.getMatchingEntries(AbstractJarVisitor.java:146)
        at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:128)
        ... 14 more

因为我知道 jar 在单元和集成测试上运行时很好,我认为这可能是 javassist 的问题,所以我尝试了 cglib。字节码提供程序然后显示为 cglib,但我仍然得到完全相同的堆栈跟踪,其中存在 javassist。

cglib 肯定在类路径中:

$ unzip -l flexipol-jar-with-dependencies.jar | grep cglib | wc -l
383

我已经尝试过使用休眠 3.4 和 3.5 并得到完全相同的错误。这是 javassist 的问题吗?

更新:我可以在 Eclipse 中成功运行应用程序(右键单击->运行方式->Java 应用程序),但使用 maven 生成的 jar-with-dependencies 失败。我认为不同之处在于 Eclipse javassist 不是检查包含的 jar,而是检查所有的类文件(可能还有一些依赖的 3rd-party jar)。

4

1 回答 1

19

该问题最终是由无效类引起的,icu4j-2.6.1本文所示。具体来说,这个文件是无效的:

com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class

这是识别损坏文件的简单方法:

for x in PATH_TO_EXTRACTED_JAR/**/*.class; do
    java -cp PATH_TO/javassist.jar javassist.tools.Dump $x >/dev/null 2>&1 || echo "$x is invalid"
done

maven 通过其传递依赖项间接包含此文件,这就是为什么我不认为该页面引用了错误,而 jar 中包含的文件是问题的罪魁祸首和原因。以下是它最终包含在我的 jar-with-dependencies 包中的方式:

jaxen-1.1.1 -> xom-1.0 -> icu4j-2.6.1

在将以下排除项添加到jaxen依赖项后,一切对我来说都正常工作(但如果您需要它的本地化部分,请小心):

<exclusions>
    <exclusion>
        <groupId>com.ibm.icu</groupId>
        <artifactId>icu4j</artifactId>
    </exclusion>
</exclusions>

另一种选择是从 jar 文件中删除有问题的文件:

#!/bin/sh                                                                                                                                                                                                                                    
shopt -s extglob
shopt -s globstar
for x in **/*.jar ; do
    zip -d $x 'com/ibm/icu/impl/data/*_zh*' >/dev/null 2>&1 && echo "Removed corrupted files from $x"
done
于 2010-06-29T19:11:55.003 回答