JDK-8156745 : java.specification.version change from "1.8" to "9" (without "1." prefix) blocks jai_imageio-1.1
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: linux
  • CPU: x86
  • Submitted: 2016-04-24
  • Updated: 2019-08-02
  • Resolved: 2016-05-11
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+114)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+114, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Darwin graytoo.local 14.5.0 Darwin Kernel Version 14.5.0: Tue Sep  1 21:23:09 PDT 2015; root:xnu-2782.50.1~1/RELEASE_X86_64 x86_64

but is applicable to all platforms


A DESCRIPTION OF THE PROBLEM :
Some packages like jai_imageio, which though no longer supported by Oracle have worked fine despite major JRE releases, fail due to the change of the java.specification.version System property to no longer include a "1." prefix, i.e., from "1.8" to "9".

Though jai_imageio is no longer supported by Oracle, it is widely used in medical imaging where access to JPEG 2000, JPEG lossless and JPEG-LS codecs is crucial (since these are used in the DICOM medical image standard), and the loss of jai_imageio compatibility in Java 9 will be a significant barrier to continued use of Java for medical imaging. It would be a shame for this to occur because of something as trivial as a version string format change.

Though the proximate cause is poor code in com.sun.media.imageioimpl.common.ImageUtil.processOnRegistration (ImageUtil.java:1408) (which does not defend against changes to the string format (vide infra)), the root cause is the "gratuitous" change prescribed by JEP 223 that removes the "1." prefix, as opposed to the other changes that are the purpose of JEP 223.

The offending code from com.sun.media.imageioimpl.common.ImageUtil.java is:

	String jvmVendor = System.getProperty("java.vendor");
String jvmVersionString =
System.getProperty("java.specification.version");
int verIndex = jvmVersionString.indexOf("1.");
// Skip the "1." part to get to the part of the version number that
// actually changes from version to version
// The assumption here is that "java.specification.version" is
// always of the format "x.y" and not "x.y.z" since that is what has
// been practically observed in all JDKs to-date, an examination of
// the code returning this property bears this out. However this does
// not guarantee that the format won't change in the future,
// though that seems unlikely.
jvmVersionString = jvmVersionString.substring(verIndex+2);

int jvmVersion = Integer.parseInt(jvmVersionString);

and it is that last parseInt (line 1408) that throws:

Caused by: java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(java.base@9-internal/NumberFormatException.java:65)
at java.lang.Integer.parseInt(java.base@9-internal/Integer.java:705)
at java.lang.Integer.parseInt(java.base@9-internal/Integer.java:813)
at com.sun.media.imageioimpl.common.ImageUtil.processOnRegistration(ImageUtil.java:1408)


REGRESSION.  Last worked in version 8u73

ADDITIONAL REGRESSION INFORMATION: 
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)

(this has worked fine with Java 1.5, 1.6, 1.7 and 1.8, and it is only this change in 9 that causes failure :().





STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Using the source code below, try and read a JPEG image using just the JRE ... succeeds

2. Using the source code below, try and read a JPEG image with jai_imageio.jar in the CLASSPATH ... fails with exception caused while trying to parse java.specification.version string and expecting it to be "1.n"


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java -cp . TestImageIOReadsAtAll davwork.jpg

Got image BufferedImage@18eed359: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@57536d79 transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 350 height = 300 #numDataElements 3 dataOff[0] = 2

ACTUAL -
When CLASSPATH includes jai_imageio.jar (from jai_imageio-1.1) fails with Exception (see below).


ERROR MESSAGES/STACK TRACES THAT OCCUR :
java -cp ./jai_imageio.jar:. TestImageIOReadsAtAll davwork.jpg
Exception in thread "main" java.lang.ExceptionInInitializerError
	at TestImageIOReadsAtAll.main(TestImageIOReadsAtAll.java:12)
Caused by: java.lang.NumberFormatException: For input string: ""
	at java.lang.NumberFormatException.forInputString(java.base@9-ea/NumberFormatException.java:65)
	at java.lang.Integer.parseInt(java.base@9-ea/Integer.java:705)
	at java.lang.Integer.parseInt(java.base@9-ea/Integer.java:813)
	at com.sun.media.imageioimpl.common.ImageUtil.processOnRegistration(ImageUtil.java:1408)
	at com.sun.media.imageioimpl.plugins.wbmp.WBMPImageReaderSpi.onRegistration(WBMPImageReaderSpi.java:95)
	at javax.imageio.spi.SubRegistry.registerServiceProvider(java.desktop@9-ea/ServiceRegistry.java:773)
	at javax.imageio.spi.ServiceRegistry.registerServiceProvider(java.desktop@9-ea/ServiceRegistry.java:328)
	at javax.imageio.spi.IIORegistry.registerApplicationClasspathSpis(java.desktop@9-ea/IIORegistry.java:214)
	at javax.imageio.spi.IIORegistry.<init>(java.desktop@9-ea/IIORegistry.java:138)
	at javax.imageio.spi.IIORegistry.getDefaultInstance(java.desktop@9-ea/IIORegistry.java:159)
	at javax.imageio.ImageIO.<clinit>(java.desktop@9-ea/ImageIO.java:66)
	... 1 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.File;
import java.util.Iterator;
import java.util.Locale;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi;

public class TestImageIOReadsAtAll {

	public static void main(String args[]) {
		try {
			BufferedImage image = null;
			File f = new File(args[0]);
			if (args.length == 1) {
				image = ImageIO.read(f);
			}
			else {
				Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(args[1]);
				int whichReader = Integer.valueOf(args[2]).intValue();
				int i=0;
				while (readers.hasNext()) {
					ImageReader reader = (ImageReader)readers.next();
					if (i == whichReader) {
						ImageReaderSpi spi = reader.getOriginatingProvider();
						System.out.println("Using reader "+i+" from "+spi.getDescription(Locale.US)+" "+spi.getVendorName()+" "+spi.getVersion());
						reader.setInput(ImageIO.createImageInputStream(f));
						image = reader.read(0);
						break;
					}
				}
			}
			if (image == null) {
				throw new Exception("Couldn't find a reader");
			}
			else {
				System.out.println("Got image "+image);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None.

In particular, cannot fix and rebuild jai_imageio-1.1, because though the Java source is available, the complete native codec source was never made available by Sun/Oracle.



Comments
Closing this as Won't Fix as any program that explicitly checks version string may need to be updated re: JEP223/JDK-8061493.
11-05-2016