SharedSecrets in OpenJDK

I have always been impressed by the effort OpenJDK folks go to maintain API compatibility. I recently came across a nifty little trick that is used in the OpenJDK codebase to help achieve this goal. Behold the SharedSecrets class! The name of the class is a little misleading since it doesn’t have anything to do with the cryptographic concepts of shared secrets. The javadocs do a (slightly) better job describing its purpose:

/** A repository of "shared secrets", which are a mechanism for
    calling implementation-private methods in another package without
    using reflection. A package-private class implements a public
    interface and provides the ability to call package-private methods
    within that package; the object implementing that interface is
    provided through a third package to which access is restricted.
    This framework avoids the primary disadvantage of using reflection
    for this purpose, namely the loss of compile-time checking. */

In other words, it is used to make private methods public, without using reflection! AND it works under a security manager! At first, I thought this was too good to be true but it turns out that the concept behind it is pretty simple. Here’s how it works. Suppose we have a class with a fixed public api and we wish to add a new method to it that we would like to be able to use internally within the project but not provide as an api:

public class FixedPublicApi {
  private static doFoo() { /* do something */ }
}

We could choose to add the doFoo method to another class (in fact, it will primarily be accessed through another class) and make it public, but let’s assume that the only way to avoid duplicating lots of code is to keep doFoo in FixedPublicApi. First we create an interface that exposes the method we want to be invoked:

public interface FooHandler {
  public void doFoo();
}

Then we modify the SharedSecrets class (or it’s equivalent in our codebase), to set the implementation for FooHandler

public class SharedSecrets {
  private static FooHandler fooHandler;
  public static void setFoo(FooHandler handler) {
    fooHandler = handler;
  }
  public static void foo() {
    fooHandler.doFoo();
  }
}

Finally we modify the FixedPublicApi class to install a handler:

public class FixedPublicApi {
  static {
     SharedSecrets.setFoo(new FooHandler() {
       public void doFoo() {
         FixedPublicApi.doFoo();
       }
     }
  }

  private static doFoo() { /* do something */ }
}

And that’s it! Now we can use SharedSecrets to call the private method:

  SharedSecrets.doFoo();

Hats off to whoever came up with this great technique.

OpenJDK and Awesome

I have been playing around with awesome and ran into some issues with Java programs (apparently others users are running into those problems too). I hacked together a patch against OpenJDK7 that seems to solve all my issues:

diff --git a/src/solaris/classes/sun/awt/X11/XWM.java b/src/solaris/classes/sun/awt/X11/XWM.java
--- a/src/solaris/classes/sun/awt/X11/XWM.java
+++ b/src/solaris/classes/sun/awt/X11/XWM.java
@@ -102,7 +102,8 @@
         METACITY_WM = 11,
         COMPIZ_WM = 12,
         LG3D_WM = 13,
-        CWM_WM = 14;
+        CWM_WM = 14,
+        AWESOME_WM = 15;
     public String toString() {
         switch  (WMID) {
           case NO_WM:
@@ -131,6 +132,8 @@
               return "LookingGlass";
           case CWM_WM:
               return "CWM";
+          case AWESOME_WM:
+              return "awesomewm";
           case UNDETERMINED_WM:
           default:
               return "Undetermined WM";
@@ -573,8 +576,12 @@
 //                            getIntProperty(XToolkit.getDefaultRootWindow(), XAtom.XA_CARDINAL)) == 0);
     }
 
+    static boolean isAwesomeWM() {
+        return isNetWMName("awesome");
+    }
+
     static boolean isNonReparentingWM() {
-        return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM);
+        return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM || XWM.getWMID() == XWM.AWESOME_WM);
     }
 
     /*
@@ -754,6 +761,8 @@
                 awt_wmgr = CWM_WM;
             } else if (doIsIceWM && isIceWM()) {
                 awt_wmgr = XWM.ICE_WM;
+            } else if (isAwesomeWM()) {
+                awt_wmgr = XWM.AWESOME_WM;
             }
             /*
              * We don't check for legacy WM when we already know that WM


Given the effort it’s taking to push a fix for mutter (the default gnome3 window manager), I wouldnt hold my breath waiting for this code to make it upstream.

IcedTea6 1.11.1 Released!

A new release of IcedTea6 1.11 branch is now available: 1.11.1

The update contains the following security fixes:

– S7082299, CVE-2011-3571: Fix in AtomicReferenceArray
– S7088367, CVE-2011-3563: Fix issues in java sound
– S7110683, CVE-2012-0502: Issues with some KeyboardFocusManager method
– S7110687, CVE-2012-0503: Issues with TimeZone class
– S7110700, CVE-2012-0505: Enhance exception throwing mechanism in
ObjectStreamClass
– S7110704, CVE-2012-0506: Issues with some method in corba
– S7112642, CVE-2012-0497: Incorrect checking for graphics rendering
object
– S7118283, CVE-2012-0501: Better input parameter checking in zip file
processing
– S7126960, CVE-2011-5035: (httpserver) Add property to limit number
of request headers to the HTTP Server

This release also contains the following additional fix:
– PR865: Patching fails with patches/ecj/jaxws-getdtdtype.patch

The tarball can be downloaded from:
http://icedtea.classpath.org/download/source/icedtea6-1.11.1.tar.gz

SHA256SUM:
bafb0e21e1edf5ee22871b13dbc0a8a0d3efd894551fb91d5f59783069b6912c

A signature (produced using my public key) is available at:
http://icedtea.classpath.org/download/source/icedtea6-1.11.1.tar.gz.sig

The following people helped with this release:

* Andrew Haley
* Andrew John Hughes
* Chris Phillips
* Danesh Dadachanji
* Deepak Bhole
* Jiri Vanek
* Omair Majid
* Roman Kennke

A huge thanks to everyone who helped test this release and reported bugs!

To get started:
$ tar xf icedtea6-1.11.1.tar.gz
$ cd icedtea6-1.11.1

Full build requirements and instructions are in INSTALL:
$ ./configure [–enable-zero –enable-pulse-java –enable-systemtap …]
$ make

IcedTea6 1.11 Branched

I have just branched IcedTea6 1.11. Please start subjecting this branch to the most vicious tests you have.

I am planning to release IcedTea6 1.11 on Wednesday 2012-01-18, unless major problems are discovered. As always, a list of new features in this release can be found in the NEWS file.

Only bugfixes are likely to be accepted for the branch. Please try to minimize changes and hold off any build-system related changes unless they are absolutely necessary.

Please note that all commits to this branch need to be posted for discussion and have to be approved for committing.

What IcedTea-Web 1.1 means for you

A number of changes occurred between IcedTea-Web 1.0 and IcedTea-Web 1.1. If you are a packager or a developer here are some things you need to know.

Are you a packager?
IcedTea-Web 1.1 can be installed into a regular prefix (/usr/ or /usr/local/ or anything else). Unlike IcedTea-Web 1.0, you do not need to install IcedTea-Web into a JDK or JRE directory. IcedTea-Web uses a JDK to build itself (specified using --with-jdk-home). IcedTea-Web will use the JDK it was compiled against to run. The launchers (javaws and itweb-settings) are now shell scripts and can be customized as needed.

Are you a developer using applets or java web start?
IcedTea-Web 1.1 provides netscape.javascript.* and javax.jnlp.* classes that applets and web start applications use. However, unlike icedtea-web < 1.1 (or older releases of icedtea6) the jars that provide these classes will not be automatically be picked up by the JDK. netscape.javascript.* classes are included in IcedTea-Web’s plugin.jar. javax.jnlp.* classes are included in IcedTea-Web’s netx.jar. Please add these classes to your classpath when building.