BFO PDF Library 2.23 - the Java 11 release

Lets start with the big item on the change log: our recent release of the PDF Library is the first one we've verified to work against Java 11, and it drops support for Java 4.

Java 11 and BFO

Java 11 was released officially last month. The fact that Java 9 and Java 10 both went end-of-life after six months might explain why we can count the number of customers that asked us about support for Java 9 on the fingers of one... well, there was one of you. Not an overwhelming takeup.

But we expect Java 11 to be different, for several reasons.

  • It's the "long term" support version.
  • Oracle have updated their licensing for Java.

Anyone with a passing familiarity with Oracle knows that when they mention licensing you should probably pay attention. We're not going to delve too deep into that as it's explained here: Java Is Still Free. But the main point which has caught most peoples attention is this: there will be no further free updates for commercial use of Oracle's JDK after January 2019.

So many customers will be considering migrating away from Oracle Java 8. After testing, our recommendation is to migrate to OpenJDK 11.

  • We've found that rendering a PDF to a bitmap is quite a bit faster under Java 11 than Java 8. Our nightly test run is down from 38 minutes to 30, and the bulk of this runtime is spent rasterizing and rendering images.
  • There have been improvements made to the JIT compiler since Java 9 which we are slowly taking advantage of. In particular, the possiblity of using vectorization instructions is something we're planning work on with our new color conversion classes (more on that later). The best discussion we have seen on this topic is this presentation.
  • OpenJDK 11 and Oracle JDK 11 are both giving identical results with our test harness. By contrast, OpenJDK 8 had this bug which we are unable to workaround. It was fixed in Oracle JDK8, but not in OpenJDK until v9.

It's not all roses, and there are some things to be aware of with Java 11. First, Java Web Start has been dropped. Although it was clunky it did have it's uses, and I know we had suggested this to several customers as a migration path away from Applets. At the moment there is no clear direct replacement, but we will be testing a few alternatives out over the next few months and will write an article on what we find.

We're also no longer supporting Java 1.4. The last email we had from a customer using this was in 2015, some 13 years after it was released, so we hope this won't affect many of you.

Finally, now that applets are gone there is no reason to break the Jar up into smaller parts. From 2.23 on there will just be a single application Jar called bfopdf.jar. If you have the bfopdf-cmap.jar, bfopdf-qrcode.jar and bfopdf-stamp.jar files in your CLASSPATH, you can safely delete them.

Color

One of the weakest points for Java has always been Color management. The AWT has a tendency to presume everything is in sRGB, and conversion from other color spaces is done by the java.awt.color package, which is implemented as a native wrapped to the LittleCMS package (in Java 8) or the legacy Sun CMS package prior to that.

There are quite a few problems with this implementation, mostly revolving around threading. The legacy package prior to Java 7 will crash very rarely, but will - occasionally - imperceptably shift all the colors, which plays havoc with our test harness.

In Java 8, 9, 10 and 11 it's a lot worse. Under heavy concurrency we were seeing unexplained exceptions or segmentation faults very frequently1. We have been advising customers to set the sun.java2d.cmm System property to sun.java2d.cmm.kcms.KcmsServiceProvider to work around this, but it's not an ideal solution.

The good news is the 2.23 release includes our own, pure Java ICC profile parser, which has no thread issues and is just as fast as the native code version. This is largely a drop-in replacement for the ICC_ColorSpace and ICC_Profile classes, and it supports ICC v4. This is good news for those running Java 7 and earlier, which only supports ICC v2

This change in implementation will result in a slight color shift, but there's a good reason for this. Try this code out

   ColorSpace srgb = Color.red.getColorSpace();
   System.out.println(Arrays.toString(srgb.toCIEXYZ(new float[] { 1, 1, 1 })));
  

You should see the values 0.9642, 1, 0.8249 which is the D50 illuminant 2. The second value is Y and this is always 1 for white. What you actually get is 0.9607544 0.9963074 0.822052, which is almost but not quite white. Convert this back to sRGB using the fromCIEXYZ method and you'll see 0.9967 instead of 1. #FFFFFF has become #FEFEFE. This lack of precision doesn't come from LittleCMS, which we tested against during development, so we presume it's the JNI interface flooring something instead of rounding. Either way it's now gone, which will mean an imperceptible change in the colors of any bitmaps create from PDF. We're certain they are imperceptible because we checked, by hand, over 7000 renderings so you don't have to.

Removal of legacy code and bugfixes

Finally, we've taking this opportunity to remove a few methods deprecated over 10 years ago. These won't be missed. We also removed the RemoteSignatureHandlerFactory class and its associated classes, which we believe has never been used and hasn't worked in some time. This is fortunate as Benoit Côté-Jodoin from GoSecure identified a potential security hole in the class, and we'd like to thank him for bringing it to our attention.

And of course there are the usual array of minor bugfixes, all documented in the CHANGELOG.

Report Generator 1.1.65

To take advantage of these changes we've also put out a refresh of our Report Generator, which is built on the latest PDF library and contains a couple of minor bugfixes too.

Download

Download both products from the https://bfo.com/download/ as usual.

[1] To put a number on this claim, our test harness was failing to complete roughly 40% of the time. The vast majority of these were Exceptions, but we did have some native code failures too where the JVM just crashed. To reproduce this we are running 32 simultaneous threads doing PDF to bitmap conversion, most of which will involve color conversion. This is a fairly unusual workload.
[2] Although sRGB is defined to use the D65 whitepoint, the number you are retrieving with this method has been convolved to D50, as that is how it is defined in Java. The reason for this is probably because the ICC profile presumes (in v2) or requires (in v4) that the conversion space is defined against D50. If you were confused before, you probably still are. Sorry. We've been at it 17 years and are still getting it wrong.