Pinyin causing Glassfish and Jetty to Fail

For as long as I can remember I’ve been hitting a bug when I start one of my web applications under GlassFish. The error message is about an ArrayIndexOutOfBounds exception and is related to Pinyin. I’ve looked for a solution a few times but never found an answer that worked. It seems to be one of those issues that a lot of people think they have found a solution for but none of them work. As far as I could tell the problem was not fatal to the application so I gave up looking but it has always worried me a little.

Well after not doing anything about it for ages I hit exactly the same issue when I tried to load a new, much simpler, application using Jetty. As the application was so simple I decided to do some digging into the cause. The stack trace I was getting was:

[WARNING] Failed startup of context o.e.j.m.p.JettyWebAppContext@3703bf3c
{/,file:///C:/Users/path/simple-webapp/src/main/webapp/,STARTING}{file:///C:/Users/path/simple-webapp/src/main/webapp/}
java.lang.RuntimeException: Error scanning entry com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class from jar 
file:///C:/Users/Username/.m2/repository/com/ibm/icu/icu4j/2.6.1/icu4j-2.6.1.jar
 at org.eclipse.jetty.annotations.AnnotationParser.parseJar(AnnotationParser.java:922)
 at org.eclipse.jetty.annotations.AnnotationParser.parse(AnnotationParser.java:839)
 at org.eclipse.jetty.annotations.AnnotationConfiguration$ParserTask.call(AnnotationConfiguration.java:161)
 at org.eclipse.jetty.annotations.AnnotationConfiguration$1.run(AnnotationConfiguration.java:543)
 at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
 at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
 at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 48188
 at org.objectweb.asm.ClassReader.readClass(Unknown Source)
 at org.objectweb.asm.ClassReader.accept(Unknown Source)
 at org.objectweb.asm.ClassReader.accept(Unknown Source)
 at org.eclipse.jetty.annotations.AnnotationParser.scanClass(AnnotationParser.java:986)
 at org.eclipse.jetty.annotations.AnnotationParser.parseJarEntry(AnnotationParser.java:967)
 at org.eclipse.jetty.annotations.AnnotationParser.parseJar(AnnotationParser.java:918)
 ... 6 more

Unlike the GlassFish stack trace this one actually caused my application to fail to deploy so I had no choice but to track down the issue. It turns out the error message under Jetty actually nails the problem. The icu4j jar file has at least one bad class file in it that trips up the byte code scanner (I don’t know why the regular VM doesn’t struggle with this). The version I’m using here, 2.6.1, is known to be particularly problematical.

The first step to diagnose this issue is to run:

mvn dependency:tree

on the application to determine what is brining in icu4j.jar. In my case it was Jaxen 1.1.1. Since that wasn’t the latest version of Jaxen I decided to upgrade to Jaxen 1.1.6 first to see if that moved me to a better version of icu4j. As luck would have it Jaxen 1.1.6 doesn’t even appear to use icu4j any more so my application was fixed. From what I’ve read if you do have to use icu4j then it’s a bit pot luck which version doesn’t trigger this issue. I’ve heard version 51.1 is good but I haven’t had need to try it myself.