HashMap / doPrivileged problem

Salter, Thomas A Thomas.Salter at unisys.com
Mon Nov 5 20:09:42 UTC 2012


Mike,

Thanks for responding so promptly.  I certainly did not expect my fix to be the best one; I was just happy to find something that worked.  I couldn't think of a solution that didn't involve doPrivileged and HashMap knowing a lot about each other, like adding a HashMap option just for doPrivileged that skips the call from HashMap to doPrivileged. 

Tom


-----Original Message-----
From: Mike Duigou [mailto:mike.duigou at oracle.com] 
Sent: Monday, November 05, 2012 1:46 PM
To: Salter, Thomas A
Cc: core-libs-dev at openjdk.java.net
Subject: Re: HashMap / doPrivileged problem

Hello Thomas;

I am sorry to hear that you ran in to this problem. The class initialization order was something we found to be surprisingly brittle and tricky with this particular change. You've run across a path we didn't anticipate. I have created a bug for this issue : JDK-8002283 (It should be visible on bugs.sun.com soon).

On Nov 5 2012, at 07:02 , Salter, Thomas A wrote:

> I have encountered a problem with initializing the new HashMap code introduced in Java 7u6.  I'm running with 7u9.  The problem only shows up running rmid (sun.rmi.server.Activation).  It seems that the AccessController needs to call HashMap but the new code in HashMap calls AccessController when reading the property, jdk.map.althashing.threshold.
> 
> At the end of this message is the stack trace and the output of -verbose:class showing the failure.
> 
> Here's a synopsis of what I think is happening:
> 1. AccessControllerContext at 98 caused Policy.isset.
> 2. Before calling isSet, the class loader initialize Policy by calling <clinit>
> 3. Clinit found its way into HashMap init.
> 4. HashMap init called HashMap$Holder.<clinit>
> 5. Which called AccessController
> 6. Which eventually called isSet.   Policy was already loaded and its clinit called, so isSet actually got called.
> 7. But Policy.<clinit> had not completed so policy is null, hence NPE.
> 8. The class loader from #2 caught the exception and wrapped it in the ExceptionInitializationError.
> 
> I'm running a modified JDK, with modifications primarily in the area of file and socket IO.  I'm pretty sure we've modified none of the classes in the stack trace below.  The best I can tell, our changes eliminated the loading of WinNTFileSystem and changed the CharSet classes that are called.  Apparently that code contains an incidental call to HashMap that gets it initialized before doPrivileged gets called from some other class.
> 
> I've found an inelegant workaround.  In java.lang.System I added a "new HashMap()" immediately following the call to set VM.booted to true.

I will see if there's an alternative way to accomplish this. There are several other classes that would need the same treatment for full safety and it seems unreasonable to just create throw-away instances to make sure they are initialized.

>  This causes the HashMap$Holder class to be initialized before doPrivileged can call it.  The key to the fix is that HashMap needs to be called after isBooted has been set so that it will invoke its Holder class.  Since the Holder class invokes doPrivileged, the HashMap needs to have been initialized before anyone calls doPrivileged.

Understood.

Thanks, 

Mike



More information about the core-libs-dev mailing list