You need to specify the name of the Class, not of the jar file in loadClass(). For this to succeed, you need to have the jar in the runtime classpath of your application (as specified by the CLASSPATH environment variable or the -cp commandline switch)
If you need to load the jar dynamically, you have to use a new ClassLoader (like Riven already posted) instance to load it yourself:
// you could specify all jars in a plugins folder here
ClassLoader pluginClassLoader = new URLClassLoader(new URL[]{ jarFile.toURI().toURL() });
telemetryComponents.add((Component) pluginClassLoader.loadClass(pluginClassname).newInstance());
The problem here might be to know, how the plugin class is named. They either have to be specified (a jars manifest is the common place to do so) or you have to scan a jar for all Classes implementing your Component interface.
Scanning the manifest for specified Components
ArrayList<Component> telemetryComponents = new ArrayList<Component>();
JarFile pluginJar = new JarFile(pluginFile);
ClassLoader pluginClassLoader = new URLClassLoader(new URL[] { pluginFile.toURI().toURL() });
Manifest manifest = pluginJar.getManifest();
// get the ; separated list of component classes from the manifest main section
String componentList = manifest.getMainAttributes().getValue("Component-Classes");
if (componentList != null)
{
String[] components = componentList.split("[; ]+");
for (int i = 0; i < components.length; i++)
{
// you might need to handle some Exceptions here
telemetryComponents.add((Component) pluginClassLoader.loadClass(components[i]).newInstance());
}
}
You need to have a Manifest in that jar like
Manifest-Version: 1.0
Created-By: YOU
Component-Classes: org.yourorg.TelemetryComponent1;org.yourorg.TelemetryComponent2
Scanning the jar for classes implementing the Component interface
ArrayList<Component> telemetryComponents = new ArrayList<Component>();
JarFile pluginJar = new JarFile(pluginFile);
ClassLoader pluginClassLoader = new URLClassLoader(new URL[] { pluginFile.toURI().toURL() });
// Iterate over the jar entries to find Component classes
for (Enumeration entries = pluginJar.entries(); entries.hasMoreElements();)
{
JarEntry entry = (JarEntry) entries.nextElement();
String candidateName = entry.getName();
// only look at (non-inner) classes
if(candidateName.endsWith(".class") && candidateName.indexOf('$') == -1)
{
// produce a class name by replacing / and removing the suffix
candidateName = candidateName.replace('/', '.').substring(0,candidateName.length()-6);
// you might need to handle some Exceptions here
Class candidate = pluginClassLoader.loadClass(candidateName);
// if the loaded class is a Component, add an instance to the list
if(Component.class.isAssignableFrom(candidate))
{
telemetryComponents.add((Component) candidate.newInstance());
}
}
}
The latter has the advantage, that you only need to implement the right interface (no Manifest editing), but also has the disadvantage of loading all classes right away, which circumvents the lazy classloading normally implemented by classloaders.