JDK-6677403 : AccessControlException in ImageIO static initializer on Solaris 10 with JAI Tools extension
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 5.0u11
  • Priority: P2
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: solaris_10
  • CPU: sparc
  • Submitted: 2008-03-19
  • Updated: 2011-01-19
  • Resolved: 2010-10-22
Related Reports
Relates :  
Relates :  
Description
On Solaris 10 & 11 machines running certain versions of the JVM and having the JAI Tools extension present, an unhandled AccessControlException thrown in the ImageIO class static initializer prevents ImageIO object instantiation & usage.

The exception stack is as follows:

java.lang.ExceptionInInitializerError
        at ImageIOBug.main(ImageIOBug.java:22)
Caused by: java.security.AccessControlException: access denied (java.util.PropertyPermission com.sun.media.imageio.disableCodecLib read)
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
        at java.security.AccessController.checkPermission(AccessController.java:427)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
        at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1285)
        at java.lang.System.getProperty(System.java:628)
        at java.lang.Boolean.getBoolean(Boolean.java:221)
        at com.sun.media.imageioimpl.common.PackageUtil.isCodecLibAvailable(PackageUtil.java:70)
        at com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi.onRegistration(CLibJPEGImageWriterSpi.java:74)
        at javax.imageio.spi.SubRegistry.registerServiceProvider(ServiceRegistry.java:698)
        at javax.imageio.spi.ServiceRegistry.registerServiceProvider(ServiceRegistry.java:285)
        at javax.imageio.spi.IIORegistry$1.run(IIORegistry.java:223)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.imageio.spi.IIORegistry.registerInstalledProviders(IIORegistry.java:230)
        at javax.imageio.spi.IIORegistry.registerStandardSpis(IIORegistry.java:165)
        at javax.imageio.spi.IIORegistry.<init>(IIORegistry.java:119)
        at javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:141)
        at javax.imageio.ImageIO.<clinit>(ImageIO.java:46)

This is reproducable using the following code on Solaris 10 with JVM 1.5.0_11 and
JAI Tools V1.1.2.

java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode, sharing)

% jar xf jai_core.jar javax/media/jai/buildVersion
% cat javax/media/jai/buildVersion
jai-1_1_2 Thu Jul 10 18:57:36 PDT 2003

ImageIOBug.java
===============

import java.security.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;

public class ImageIOBug {

  public static void main(String[] args) {
    
    if(args.length != 1) {
      System.err.println("Usage: java ImageIOBug <true|false - Use security mgr>");
      System.exit(22);
    }
    try {
      System.err.println("java.ext.dirs" + " = " + System.getProperty("java.ext.dirs"));
      if(args[0].equalsIgnoreCase("true")) {
        System.setSecurityManager(new RMISecurityManager());
      }
      System.err.println(Thread.currentThread().getContextClassLoader().getClass().getName());
      for(Iterator i = ImageIO.getImageReadersByMIMEType("image/jpeg"); i.hasNext();) {
        ImageReader imr = (ImageReader) i.next();
        System.out.println(imr.getClass().getName());
      }
    }
    catch(Throwable t) {
      t.printStackTrace();
    }

  }

};

% java -cp . ImageIOBug true
java.ext.dirs = /RickZ/JAVA/jdk1.5.0_11/jre/lib/ext
sun.misc.Launcher$AppClassLoader
java.lang.ExceptionInInitializerError
        at ImageIOBug.main(ImageIOBug.java:21)
...

Using the 1.5.0_12 version of the JVM on the same machine works.

% /usr/bin/java -version
java version "1.5.0_12"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_12-b04)
Java HotSpot(TM) Client VM (build 1.5.0_12-b04, mixed mode, sharing)

% /usr/bin/java -cp . ImageIOBug true
java.ext.dirs = /usr/jdk/instances/jdk1.5.0/jre/lib/ext
sun.misc.Launcher$AppClassLoader
com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader
com.sun.imageio.plugins.jpeg.JPEGImageReader

Running both with -Djava.security.debug=access yields

1.5.0_11
========
access: access denied (java.util.PropertyPermission com.sun.media.imageio.disableCodecLib read)

1.5.0_12
========
access: access allowed (java.util.PropertyPermission com.sun.media.imageio.disableCodecLib read)

Various JVM's have exhibited this problem. Below is a list of those that have seen the
problem with my application.

SunOS sparc 5.10 1.4.2_10-b03
SunOS sparc 5.10 1.5.0_08-b03
SunOS sparc 5.10 1.5.0_11-b03
SunOS sparc 5.10 1.5.0_12-b04
SunOS sparc 5.10 1.5.0_14-b03
SunOS x86   5.10 1.5.0_07-b03
SunOS x86   5.11 1.5.0_08-b03
SunOS x86   5.11 1.5.0_10-b03
SunOS x86   5.11 1.5.0_11-b03
SunOS x86   5.11 1.5.0_13-rev-b07

Reviewing the JAI source, it appears that based on the 1.1.2 release that there is
a try/catch block in the JAI code to catch the SecurityException as shown below.
This appears to be not working. 

The following cvs revision tags for jai-imageio-core show:

Doesn't catch security exception.
root-1_1
jai-imageio-1_1-alpha

Revision tag jai-imageio-1_1-dr-b01 & later, including
jai-imageio-1_1-fcs, contains the code below.

    public static final boolean isCodecLibAvailable() {
        // Retrieve value of system property here to allow this to be
        // modified dynamically.
        Boolean result = (Boolean)
            AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        String property = null;
                        try {
                            property =
                                System.getProperty("com.sun.media.imageio.disableCodecLib");
                        } catch(SecurityException se) {
                            // Do nothing: leave 'property' null.
                        }
                        return (property != null &&
                                property.equalsIgnoreCase("true")) ?
                            Boolean.TRUE : Boolean.FALSE;
                    }
                });

Regardless of whether there is a problem catching the exception in the above code,
uncaught exceptions loading an extension should not be able to cripple the ImageIO
object instantation.

Applications deployed using Java Web Start have no control over the JVM installations on the
target machine, and in my case Jini proxies which provide image services fail because of this
bug.

The ImageIO static initializer should handle errors trying to load extensions.

Comments
EVALUATION This problem seems to be already resolved on the jws side: I have verified it using jdk5u26, jdk6u22, and jdk7b114, all work fine with installed jai imageio plugins. I think this problem was resolved in jdk6u10 as a part of fix for CR 6633196, and forward-ported into jdk7 as a part of work for CR 6797688. So this fix in imageio is not needed anymore, and I am going to close the CR and withdraw the webrev.
22-10-2010

EVALUATION The idea of the fix is exactly same as for classpath plugins: we isolate a plugin registration by try/catch block. For standalone application we re-throw a caught exception to indicate a misconfiguration of the system. For applets and javaws application we silently eat the exception and dump a stack trace to stderr.
02-06-2009

SUGGESTED FIX http://sa.sfbay.sun.com/projects/java2d_data/7/6677403.0
02-06-2009

EVALUATION I tried to reproduce this problem on SunRay servers from the list (see comments) but didn't succeed, i.e. installed plugins form the jre/lib/ext directory always had enough permission to read required properties. Without way to reporoduce this problem, I am unable to figure out what is the root reason of observed behavior and leaning to suspect some kind of misconfiguration. It is possible to add try/catch block to the IIORegistry.registerInstalledProviders method (like it was done for the IIORegistry.registerApplicationClasspathSpis method as part of fix for CR 6342404) and increase our tolerance to misconfiguration of plugins. This will require adding some trace logging support because eating such exceptions silently does not look like good idea. In fact we had considered this in the past and decided not to do this simply because we did not expect installed plugins can be misconfigured. Perhaps we should revisit this. However, adding try/catch will not fix original misconfiguration issue. Therefore I am marking this bug incomplete until I get more info how to reproduce it.
03-06-2008

WORK AROUND If your application does not use any extensions, you can define the property java.ext.dirs to be null with -Djava.ext.dirs or the line <property name="java.ext.dirs"/> in a jnlp file. This will prevent the ExtClassLoader from traversing the lib/ext directory.
19-03-2008