فشل Javassist في السبات: نوع ثابت غير صالح: 60
سؤال
أقوم بإنشاء أداة CLI لإدارة تطبيق موجود. كل من التطبيق والاختبارات تبني بشكل جيد وتدير بشكل جيد ، لكن على الرغم من أنني أتلقى فشل Javassist عند تشغيل أداة CLI الموجودة داخل الجرة:
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
بما أنني أعلم أن الجرة جيدة حيث أن اختبارات الوحدة والتكامل تعمل ضدها ، فقد اعتقدت أنها قد تكون مشكلة مع Javassist ، لذلك جربت Cglib. ثم يظهر مزود Bytecode باسم CGLIB ، لكن ما زلت أحصل على نفس تتبع المكدس بالضبط مع وجود Javassist فيه.
Cglib بالتأكيد في classpath:
$ unzip -l flexipol-jar-with-dependencies.jar | grep cglib | wc -l
383
لقد حاولت مع كل من Hibernate 3.4 و 3.5 والحصول على نفس الخطأ بالضبط. هل هذه مشكلة مع جافاسيست؟
تحديث: يمكنني تشغيل التطبيق بنجاح ضمن Eclipse (النقر بزر الماوس الأيمن-> تشغيل AS-> تطبيق Java) ، ولكن فشل استخدام جرة مع مراعاة Maven. أفترض أن الفرق هو أنه مع عدم تفتيش Eclipse Javassist على الجرة المحتوية ، بل إنه يتفقد جميع ملفات الفصل (وربما بعض الجرار المعتمدة على الطرف الثالث).
المحلول
المشكلة ناتجة في النهاية عن فئة غير صالحة في 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 من خلال تبعياته المتعدية وهذا هو السبب في أنني لم أدرك تلك الصفحة على أنها تشير إلى الخطأ وملف موجود داخل الجرة باعتباره الجاني وسبب المشكلة. إليكم كيف انتهى الأمر بتضمينه في حزمة الجرة مع الاعتماد على:
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