Avoid useless Plugin Initialization and/or Class Loading
Here’s a tip for initializing your plugins or any other singleton-like repository only when needed.
Consider a code like this:
if (isConfigurable()) {
Bundle bundleCopy = bundle;
Preferences[] preferencesCopy = new Preferences[1];
preferencesCopy[0] = new org.eclipse.core.internal.
preferences.legacy.PreferenceForwarder(
this, bundleCopy.getSymbolicName());
return preferencesCopy;
}
return null;
Do you see what’s wrong there?
The problem is that if your #isConfigurable is always FALSE then your code still:
- loads PreferencesForwarder class
- initializes all PreferencesForwarder’s static variables
- forces Preferences plugin to load
Always, if possible and makes sense, isolate your class loading into a simple Runnable inner class if there is some static init or plugin activation trigger involved!
Then the code would become:
if (isConfigurable()) {
final Bundle bundleCopy = bundle;
final Preferences[] preferencesCopy = new Preferences[1];
Runnable innerCall = new Runnable() {
public void run() {
preferencesCopy[0] = new org.eclipse.core.internal.
preferences.legacy.PreferenceForwarder(
this, bundleCopy.getSymbolicName());
}
};
innerCall.run();
}
return null;
When you think of it - this pattern is somewhat similar to the singleton pattern implementation - the one of the very few thread-safe and fast singleton patterns that is bugfree and truly lazy!
Quoting wonderful singleton impl from wikipedia:
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
(OK, to be fully honest, since java1.5 you can also trust volatile flags but - trust noone, use the old stuff:P)
For the reference, the PreferencesForwarder example was taken from the org.eclipse.core.runtime.Plugin#getPluginPreferences class and modified a bit.
UPDATE: This post is not fully correct! Never assume something to be true even if it comes from a trustworthy source like eclipse core runtime source. Please see the comments for explanation!
3 Comments »
RSS feed for comments on this post.






In what circumstances do you think that PreferenceForwarder will load from the first example
if (isConfigurable()) {
Bundle bundleCopy = bundle;
Preferences[] preferencesCopy = new Preferences[1];
preferencesCopy[0] = new org.eclipse.core.internal.
preferences.legacy.PreferenceForwarder(
this, bundleCopy.getSymbolicName());
return preferencesCopy;
}
return null;
My understanding is that classloading on most JVMs is so lazy that it will only happen if the condition is evaluated to true. A few tests on different JVMs (Sun 1.4.2, 5, 6 and IBM 1.4.2, 6) with -verbose:class confirmed this behavior for me.
It is not a big deal, but I am a little concerned with adding complexity (although not that much) for no reason.
Comment by Mark Hibberd — December 19, 2007 @ Wednesday, December 19, 9:03 pm
Mark: Haha! How embarrassing, you were right :)
Plugin source code has a comment regarding this and it was clearly misleading:
// Performance: isolate PreferenceForwarder into
// an inner class so that it mere presence
// won’t force the PreferenceForwarder class
// to be loaded (which triggers Preferences
// plugin activation).
True, of course it makes sense that class load happens only when it’s actually needed.
Now I don’t see any reason why this Runnable is in #getPluginPreferences after all.
Comment by Ahti — December 20, 2007 @ Thursday, December 20, 11:43 am
Sometimes respective source code like eclipse runtime is so trustworthy that one stops thinking if it’s really correct :P
Comment by Ahti — December 20, 2007 @ Thursday, December 20, 11:47 am