Hi all,
I've been cleaning up code that I work on to be Java 9 compatible, but have ran into a blocker due to limitations of the Naming API. I could work around the blocker with an --add-opens, but I'd rather find a proper solution. *** Background Currently the javax.naming.spi.NamingManager allows for setting a JVM-wide InitialContextFactoryBuilder (ICFB) once and only once by using the static NamingManager.setInitialContextFactoryBuilder() method [1]. The javadoc clearly states: > Once installed, the builder cannot be replaced. If the set ICFB method is called after a ICFB is set, it will throw an IllegalStateException. This seems to be an overly-aggressive restriction of the API. Currently my product has code that reflects into the NamingManager class in order to clear out the ICFB field using reflection. To be Java 9 compliant, we would like to remove this usage of deep reflection, but there are no clear alternatives for doing so. *** Use case We have a JNDI server that may be started/stopped by other java code in the same JVM. If users stop the JNDI server we clear out the ICFB (using reflection) when the JNDI server OSGi bundle deactivates, so that if a user decides to start the JNDI server again in the same JVM, they may do so and we simply set the ICFB when the JNDI server bundle activates. *** Proposed Solution: I could add a layer of indirection by creating an ICFB wrapper that supports re-setting what ICFB it wraps. However, this would cause the ICFB wrapper and all other classes loaded using that bundle's classloader to be leaked (since it can't be fully deactivated and garbage collected). To sort of work around this classloader leak, we would need to load the ICFB wrapper using its own classloader. Although the wrapper classloader would still be leaked, it would have minimal impact because only the one wrapper class would be leaked. I am not sure why the "no resetting" restriction is on the NamingManager API in the first place. Is anyone aware why the API has this restriction? In any case, the solution outlined above seems rather messy (as it only solves the problem by mitigating a classloader leak), so I would like to propose the following addition to the NamingManager API: /** * Clears the InitialContextFactoryBuilder that was previously installed, if any, so that a different one may be set at a later time. * @throws SecurityException - the builder cannot be cleared for security reasons. * @see SecurityManager.checkSetFactory() */ public static void clearInitialContextFactoryBuilder() Additionally, I think it would make sense to permit clearing the NamingManager's ObjectFactoryBuilder using a similar mechanism. Although I don't have any immediate need or use case for this API, I can imagine others may need the same. [1] http://download.java.net/java/jdk9/docs/api/javax/naming/spi/NamingManager.html#setInitialContextFactoryBuilder-javax.naming.spi.InitialContextFactoryBuilder- - Andy
