javolution.lang.Initializer Maven / Gradle / Ivy
/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2012 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.lang;
import java.util.Vector;
import javolution.context.LogContext;
/**
* An initializer for all classes loaded by any given class loader.
*
* Initialization of classes at startup (or during bundle activation)
* ensures a significantly improved worst case execution time especially
* if the classes has {@link Configurable configuration logic} to be
* executed then.
*
* Javolution activator initialize {@link Realtime} classes when started.
* When running outside OSGi the method
* {@code javolution.osgi.internal.OSGiServices.initializeRealtimeClasses()}
* can be used to that effect..
*
* Class loading can be performed in a lazy manner and therefore some parts
* of the class loading process may be done on first use rather than at
* load time. Javolution bundle activator ensure that all its classes
* are initialized at start up.
* The following code illustrates how this can be done for any bundle.
* [code]
* public class MyActivator implements BundleActivator {
* public void start(BundleContext bc) throws Exception {
* Initializer initializer = new Initializer(MyActivator.class.getClassLoader());
* initializer.loadClass(com.foo.internal.UnreferencedClass.class);
* // Load explicitly classes not directly or indirectly referenced.
* ...
* initializer.initializeLoadedClasses(); // Recursive loading/initialization.
* ... // Continue activation
* }
* }[/code]
*
* This utility use reflection to find the classes loaded and may not be
* supported on all platforms.
*
* @author Jean-Marie Dautelle
* @version 5.1, July 26, 2007
*/
public class Initializer {
/**
* Indicates if the class being initialized should be logged
* (default {@code false}).
*/
public static final Configurable SHOW_INITIALIZED = new Configurable() {
@Override
protected Boolean getDefault() {
return false;
}
};
/** The class loader for this initializer */
private final ClassLoader classLoader;
/**
* Creates an initializer for the specified class loader.
*/
public Initializer(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Returns the classes loaded by the class loader of this initializer or
* null
if not supported by the platform.
*/
@SuppressWarnings("unchecked")
public Class[] loadedClasses() {
Class cls = classLoader.getClass();
while (cls != java.lang.ClassLoader.class) {
cls = cls.getSuperclass();
}
try {
java.lang.reflect.Field fldClasses = cls
.getDeclaredField("classes");
fldClasses.setAccessible(true);
Vector> list = (Vector>) fldClasses
.get(classLoader);
Class[] classes = new Class[list.size()];
for (int i = 0; i < classes.length; i++) {
classes[i] = list.get(i);
}
return classes;
} catch (Throwable e) {
return null;
}
}
/**
* Loads the specified class (does not perform any initialization).
* This method is typically used to load unreferenced classes.
*/
public void loadClass(Class cls) {
try {
classLoader.loadClass(cls.getName());
} catch (ClassNotFoundException e) {
LogContext.debug("Class " + cls + " not found.");
}
}
/**
* Initializes all the loaded classes. If the initialization leads to more
* classes being loaded, these classes are initialized as well
* (recursive process).
*
* @return {@code true} if initialization has been performed successfully;
* {@code false} otherwise.
*/
public boolean initializeLoadedClasses() {
boolean isInitializationSuccessful = true;
int nbrClassesInitialized = 0;
while (true) {
Class[] classes = loadedClasses();
if (classes == null) {
LogContext.debug("Automatic class initialization not supported.");
return false;
}
if (nbrClassesInitialized >= classes.length)
break; // Done.
for (int i = nbrClassesInitialized; i < classes.length; i++) {
Class cls = classes[i];
try {
if (SHOW_INITIALIZED.get())
LogContext.debug("Initialize ", cls.getName());
Class.forName(cls.getName(), true, classLoader);
} catch (Throwable error) {
isInitializationSuccessful = false;
LogContext.warning("Class ", cls.getName(), " cannot be initialized.");
}
}
nbrClassesInitialized = classes.length;
}
LogContext.debug("Initialization of ", nbrClassesInitialized,
" classes loaded by ", classLoader);
return isInitializationSuccessful;
}
}