ObjectWeb ASM is a great library that's used to parse Java class files. It's used in all kinds of projects, such as Hibernate, Corba, JAX-WS, Jersey, Spring, Hudson, to name a few.

But I have a pet peeve to this otherwise great library, namely its insistence on small size (which by itself isn't a bad thing), and its consequences.

One of the choices that made to achieve this was to omit the debug information entirely from the class files, including the line number tables. This is unlike every other OSS Java projects. So you can't step through the ASM code from the debugger, your IDE won't offer any assistance while editing, and it generally makes it hard to use.

Another choice they made to achieve the small size is to ignore the backward compatibility. Whenever ASM changes, and it has to change every so often (at least every time a class file format changes), it doesn't do anything to keep the existing applications working. For example, from 2.x to 3.x, theClassReader.accept method, which parses the class file, has changed in an incompatible way. It used to takeClassVisitor and boolean, which was a flag, but in 3.x it needed to take more flags, so they opted for taking an integer as a bit mask.

It was entirely possible to retain the backward compatibility by defining the following simple one line method, but no, keepingasm.jar smaller was more important for ASM, so they just removed the method instead.

public void accept(ClassVisitor cv, boolean skipDebug) {
  accept(cv, skipDebug?SKIP_DEBUG:0);
}

The end result is that if your application is using one framework that uses one version of ASM underneath, and if you have another library that uses another version of ASM underneath, then there just isn't any way to make them work together — using the latest version of ASM breaks libraries/frameworks/apps that are built with earlier versions. Google can tell you how widespread this problem is.

In the face of this, framework/library developers works around the problem by doing package renaming. So everyone ends up getting their own private copy of ASM. and the result is far from optimal. For example, if I remember correctly, GlassFish now has 4 copies of ASM in it, one used by Corba, one used by EclipseLink, one used by JAX-WS, and another one by Jersey. The CDI implementation might have another one, too. Needless to say, size increase by this far outweigh the minimal size decrease obtained by not keeping the backward compatibility.

I think ASM developers should step back and really think hard if reducing the jar file size by a few 10KBs is really worth this much pain throughout the food chain. More concretely, I humbly propose:

  • ASM ships their jars with full debug info, like everyone else does. If small footprint is important for some users, a minimized jar can be delivered separately.
  • ASM retains backward compatibility in their API for minor releases, and for every API-breaking major release, ASM should deliver an official package renamed jar. This allows me to write a library/framework that depends on ASM 2.x, and my library can peacefully coexist with someone else's library that uses ASM 3.x. Official package renamed jars cut the # of duplicates.