In one of my applications I am using the following:
public void calculate (String className)
{
...
Class clazz = Class.forName(className);
...
}
This function is called several times / second. There are about 10 possible class names. And while I do realize there is some internal caching inside this function, I think this caching is only available on native level.
For this reason I am starting to wonder if I should add my own caching.
private static Map<String,Class> classMap;
public void calculate (String className)
{
...
Class clazz = classMap.get(className);
if (clazz == null)
{
clazz = Class.forName(className);
if (classMap == null) classMap = new HashMap<String, Class>(40);
classMap.put(className, clazz);
}
...
}
Will this be a performance gain or does it really make no difference ?
Thank you in advance
forName(String name, boolean initialize, ClassLoader loader) Returns the Class object associated with the class or interface with the given string name, using the given class loader.
The forName() method of java. lang. Class class is used to get the instance of this Class with the specified class name. This class name is specified as the string parameter.
forName() The most common approach to register a driver is to use Java's Class. forName() method, to dynamically load the driver's class file into memory, which automatically registers it. This method is preferable because it allows you to make the driver registration configurable and portable.
Load class with forName() method in Java The class object associated with the class with the given string name can be returned with the method java. lang. Class. forName(String name, boolean initialize, ClassLoader loader), using the class loader that is used to load the class.
I wrote a little script to calculate the execution time of both functions.
This is the Main class that I used.
public class Benchmark
{
public static void main(String... pArgs)
{
// prepare all data as much as possible.
// we don't want to do this while the clock is running.
Class[] classes = {Object.class, Integer.class, String.class, Short.class, Long.class, Double.class,
Float.class, Boolean.class, Character.class, Byte.class};
int cycles = 1000000;
String[] classNames = new String[cycles];
for (int i = 0; i < cycles; i++)
{
classNames[i] = classes[i % classes.length].getName();
}
// THERE ARE 2 IMPLEMENTATIONS - CLASSIC vs CACHING
Implementation impl = new Caching(); // or Classic();
// Start the clocks !
long startTime = System.currentTimeMillis();
for (int i = 0; i < cycles; i++)
{
impl.doStuff(classNames[i]);
}
long endTime = System.currentTimeMillis();
// calculate and display result
long totalTime = endTime - startTime;
System.out.println(totalTime);
}
}
Here is the classic implementation that uses Class.forName
private interface Implementation
{
Class doStuff(String clzName);
}
private static class Classic implements Implementation
{
@Override
public Class doStuff(String clzName)
{
try
{
return Class.forName(clzName);
}
catch (Exception e)
{
return null;
}
}
}
Here is the second implementation that uses a HashMap
to cache the Class
objects.
private static class Caching implements Implementation
{
private Map<String, Class> cache = new HashMap<String, Class>();
@Override
public Class doStuff(String clzName)
{
Class clz = cache.get(clzName);
if (clz != null) return clz;
try
{
clz = Class.forName(clzName);
cache.put(clzName, clz);
}
catch (Exception e)
{
}
return clz;
}
}
The results:
Conclusion:
Will this be a performance gain or does it really make no difference?
I would be astonished if it made a significant difference - and if you're only calling it "several times per second" (rather than, say, a million) it's really not worth optimizing.
You should at least try this in isolation in a benchmark before committing to this more complicated design. I would strongly expect Class.forName
to be caching this anyway, and adding more complexity into your app does no good.
Class.forName()
does two things:
Part #1 is pretty quick. #2 is where the real work starts (where the JVM might hit the hard disk or even the network, depending on the classloader). And if you pass the same parameters in, then all but the first invocations will never get to step #2.
So no: it's probably not worth optimizing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With