Hi SecurityManager Experts out there ;-)
I have written a small plugin framework that loads plugins with separate isolated classloaders. For a successfull undeploy of a plugin it is important to make sure that no reference to classes loaded by the plugin classloader are held by the application.
There is a feature in Java called shutdown hook that enables client code to register a thread that is executed when the JVM was requested to shut down. This implies that potentially there will be references held by the JVM to a class loaded by the plugin classloader.
My first attempt was to install a SecurityManager that denies adding a shutdown hook. This totally works and denies all attempts to add shutdown hooks. The interesting thing is, that I realized, that it is not the plugin itself that wants to add a shutdown hook. The plugin just triggers the AWT/Swing internals (precise: SunFontManager
) by loading a font. The SunFontManager
in turn adds the shutdown hook to do some of it's internal handling when the JVM exits. I do not want to deny that the plugin loads a font (because it has to) and I do not want do deny the Java internals to add their stuff.
For me it seems that I would have to grant more permissions to the code (if the sun.*|java.*|javax.*
package is in the stack trace..uuuhmm...ugly) than it would have normally. But this breaks the conventions of the security framework which assumes that client code cannot have more privileges than code that is calling it.
How can I distinguish that it is not the plugin code but the Java internals that wants to do something? Or is there any other way to make sure not to corrupt the internals by denying something?
Example of what happens
To make things clearer, here is what actually happens in my application. I have a custom SecurityManager installed that should deny addShutdownHook
performed directly by plugins, but should not deny those calls if performed as a side-effect by Java internal classes.
Context: Calls: ---------------------------------------------- AppClassloader Application | PluginClassloader PluginObject.init() | AppClassloader Font.create() | AccessController.doPrivileged(...) { Runtime.addShutdownHook(...) }
The SecurityManager was installed using System.setSecurityManager()
and does this:
@Override
public void checkPermission(java.security.Permission perm) {
if (perm.getName().equals("shutdownHooks")) {
if (threadContextClassLoaderIsPluginClassLoader()) {
throw new SecurityException("Installing shutdown hooks is not allowed.");
}
}
}
Although the addShutdownHook
is called inside a doPrivileged
-block my SecurityManager
is called. Am I missing something? Should I check for the privileged context myself?