JDK-4929170 : getMetadataFormat() fails with user supplied ImageReaders
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2003-09-26
  • Updated: 2004-03-30
  • Resolved: 2004-03-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b45Fixed
Related Reports
Relates :  
Description
Calling IIOMetadata.getMetadataFormat() for a user supplied ImageReader plugin
(such as those offered by the JAI Image I/O Tools package) may throw an
exception depending on the caller's classloader.  Here is a snippet from the
submitter's testcase that demonstrates the exception:

-----------------snip--------------------

ByteArrayOutputStream ostream = new ByteArrayOutputStream();
FileCacheImageOutputStream fcios = null;
try {
    fcios = new FileCacheImageOutputStream(ostream, null);
} catch(IOException ex) {
    System.err.println("There was a problem creating the
FileCacheImageOuputStream: "+ex.toString());
    return null;
}

Iterator writers =
    ImageIO.getImageWritersByFormatName("jpeg2000");
if(!writers.hasNext()) {
    System.err.print("No ImageWriter available for chosen output format");
    return null;
}

//Debugging output here to show class loader issue of
//getMetadataFormat() implementation.
try {
    System.err.println("java.system.class.loader =
"+System.getProperty("java.system.class.loader"));
    System.err.println("Loading class first way");
    Class cls =
Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat"
, true, this.getClass().getClassLoader());
    System.err.println("Loaded class first way: "+cls);
    System.err.println("Loading class second way");
    cls =
Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat"
, true, ClassLoader.getSystemClassLoader()); //This was
ImageFactory.java:150
    System.err.println("Loaded class second way: "+cls);
    Method meth = cls.getMethod("getInstance", null);
    System.err.println((IIOMetadataFormat) meth.invoke(null, null));
} catch(Exception ex) {
    System.err.println("There was a problem loading the native metadata");
    ex.printStackTrace();
}

--------------------------snip-----------------------------

And the output from executing this code:

-------------------output/exceptions-----------------------

java.system.class.loader = null
Loading class first way
Loaded class first way: class
com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat
Loading class second way
There was a problem loading the native metadata
java.lang.ClassNotFoundException:
com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat
	at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:219)
	at
com.gwha.hmi.service.objectgateway.handlers.ImageFactory.getTranscodedImageI
nputStream(ImageFactory.java:150)
	at
com.gwha.hmi.service.objectgateway.handlers.VectorGraphicsHandler.getRasterI
mageInputStream(VectorGraphicsHandler.java:417)
	at
com.gwha.hmi.service.objectgateway.handlers.VectorGraphicsHandler.getObjectI
nputStream(VectorGraphicsHandler.java:304)
	at
com.gwha.hmi.service.objectgateway.ObjectGateway.openFileForReading(ObjectGa
teway.java:282)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261)
	at sun.rmi.transport.Transport$1.run(Transport.java:148)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:144)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
	at
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:7
01)
	at java.lang.Thread.run(Thread.java:534)
Error: One factory fails for the operation "ImageWrite"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at javax.media.jai.FactoryCache.invoke(FactoryCache.java:130)
	at
javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1682)
	at
javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperatio
nRegistry.java:481)
	at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:340)
	at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:830)
	at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:878)
	at javax.media.jai.RenderedOp.getRendering(RenderedOp.java:899)
	at javax.media.jai.JAI.createNS(JAI.java:1103)
	at javax.media.jai.JAI.create(JAI.java:977)
	at
com.sun.media.jai.operator.ImageWriteDescriptor.create(ImageWriteDescriptor.
java:964)
	at
com.gwha.hmi.service.objectgateway.handlers.ImageFactory.getTranscodedImageI
nputStream(ImageFactory.java:162)
	at
com.gwha.hmi.service.objectgateway.handlers.VectorGraphicsHandler.getRasterI
mageInputStream(VectorGraphicsHandler.java:417)
	at
com.gwha.hmi.service.objectgateway.handlers.VectorGraphicsHandler.getObjectI
nputStream(VectorGraphicsHandler.java:304)
	at
com.gwha.hmi.service.objectgateway.ObjectGateway.openFileForReading(ObjectGa
teway.java:282)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:261)
	at sun.rmi.transport.Transport$1.run(Transport.java:148)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:144)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
	at
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:7
01)
	at java.lang.Thread.run(Thread.java:534)
Caused by: java.lang.IllegalStateException: Can't obtain format
	at
javax.imageio.metadata.IIOMetadata.getMetadataFormat(IIOMetadata.java:388)
	at
com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadata.<init>(J2KMetadata.ja
va:86)
	at
com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadata.<init>(J2KMetadata.ja
va:151)
	at
com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLib.write(J2KI
mageWriterCodecLib.java:277)
	at
com.sun.media.jai.imageioimpl.ImageWriteCRIF.create(ImageWriteCRIF.java:555)
	at
com.sun.media.jai.imageioimpl.ImageWriteCRIF.create(ImageWriteCRIF.java:205)
	... 29 more
Caused by: java.lang.ClassNotFoundException:
com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat
	at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:219)
	at
javax.imageio.metadata.IIOMetadata.getMetadataFormat(IIOMetadata.java:383)
	... 34 more

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2 FIXED IN: tiger-beta2 INTEGRATED IN: tiger-b45 tiger-beta2
21-08-2004

WORK AROUND If you know the exact classname of the IIOMetadataFormat subclass, call: Class.forName(formatName, true, this.getClass().getClassLoader()); in order to manually load the format class.
21-08-2004

EVALUATION It appears that getMetadataFormat() attempts to load the IIOMetadataFormat instance using the system ClassLoader, which may not have knowledge of a user supplied ImageReader or IIOMetadataFormat class. I believe this issue is similar to 4481957, and the fix should be about the same: first try to use the current thread's context ClassLoader, and failing that use the system ClassLoader. We should try to fix this for Tiger, since it's important that the JAI plugins and other third-party plugins work seamlessly with the javax.imageio API. ###@###.### 2003-09-26
26-09-2003