Java java.lang.NoClassDefFoundError whilie loading jars in Module Loader - java

Ich have wrote a little module system, where modules are packaged into jars.
The application has to load these modules at start.
For loading these jars and extract the classes which implements the IModule interface or extends the Module class, i have written an ModuleLoader, by inspiring an tutorial.
The class Module is also implementing the IModule interface.
Now, if i start the application, there is thrown an exception.
IModuleLoader moduleLoader = new DefaultModuleLoader();
List<IModule> moduleList = moduleLoader.loadModulesFromDir(moduleDir);
Exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/corundumstudio/socketio/AuthorizationListener
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at com.jukusoft.jbackendengine.backendengine.module.impl.DefaultModuleLoader.extractClassesFromJAR(DefaultModuleLoader.java:137)
at com.jukusoft.jbackendengine.backendengine.module.impl.DefaultModuleLoader.extractClassesFromJARs(DefaultModuleLoader.java:120)
at com.jukusoft.jbackendengine.backendengine.module.impl.DefaultModuleLoader.loadModulesFromDir(DefaultModuleLoader.java:43)
at com.jukusoft.jbackendengine.backendengine.module.impl.DefaultModuleManager.loadModulesFromDir(DefaultModuleManager.java:91)
at com.jukusoft.jbackendengine.backendengine.module.impl.DefaultModuleManager.loadAndStart(DefaultModuleManager.java:100)
at com.jukusoft.jbackendengine.backendengine.builder.DefaultBackendEngineBuilder.buildBackendEngine(DefaultBackendEngineBuilder.java:26)
at com.jukusoft.jbackendengine.backendengine.builder.DefaultBackendEngineBuilder.buildBackendEngine(DefaultBackendEngineBuilder.java:16)
at com.jukusoft.jbackendengine.backendengine.factory.BackendEngineFactory.createNewDefaultBackendEngine(BackendEngineFactory.java:22)
at com.jukusoft.jbackendengine.backendengine.ServerEngineMain.main(ServerEngineMain.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassNotFoundException: com.corundumstudio.socketio.AuthorizationListener
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 25 more
Here is the code of class ModuleLoader:
package com.jukusoft.jbackendengine.backendengine.module.impl;
import com.jukusoft.jbackendengine.backendengine.module.IModule;
import com.jukusoft.jbackendengine.backendengine.module.IModuleLoader;
import com.jukusoft.jbackendengine.backendengine.module.ModuleUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Created by Justin on 03.07.2015.
*/
public class DefaultModuleLoader implements IModuleLoader {
#Override
public List<IModule> loadModulesFromDir(File modulesDir) throws IOException {
FilenameFilter filenameFilter = new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar") || name.endsWith(".jam");
}
};
if (!modulesDir.exists()) {
System.out.println("directory modules doesnt exists, creating directory modules.");
modulesDir.mkdirs();
}
File[] files = modulesDir.listFiles(filenameFilter);
System.out.println("" + files.length + " .jar files in directory " + modulesDir.getAbsolutePath() + " found.");
ClassLoader classLoader = new URLClassLoader(fileArrayToURLs(files));
List<Class<IModule>> moduleClasses = extractClassesFromJARs(files, classLoader);
System.out.println("" + moduleClasses.size() + " modules found.");
return createModuleObjects(moduleClasses);
}
#Override
public List<IModule> loadModulesFromFile(File moduleFile) throws IOException {
ClassLoader classLoader = new URLClassLoader(fileToURL(moduleFile));
List<Class<IModule>> moduleClasses = extractClassesFromJAR(moduleFile, classLoader);
return createModuleObjects(moduleClasses);
}
private URL[] fileArrayToURLs (File[] files) throws MalformedURLException {
URL[] urlsArray = new URL[files.length];
for (int i = 0; i < files.length; i++) {
urlsArray[i] = files[i].toURI().toURL();
}
return urlsArray;
}
private URL[] fileToURL (File file) throws MalformedURLException {
URL[] urlsArray = new URL[1];
urlsArray[0] = file.toURI().toURL();
return urlsArray;
}
public boolean isModuleClass (Class<?> cls) {
//System.out.println("isModuleClass() " + cls.getName() + ".");
/*try {
for (Class<?> cls1 : cls.getInterfaces()) {
System.out.println("Found interface " + cls1.getName() + " in class " + cls.getName() + ".");
if ((cls1.equals(IModule.class) || cls1.equals(Module.class)) && ModuleUtils.containsModuleInfo(cls)) {
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}*/
return IModule.class.isAssignableFrom(cls) || Module.class.isAssignableFrom(cls);
}
public IModule createModuleObject (Class<IModule> moduleClass) throws IllegalAccessException, InstantiationException {
return moduleClass.newInstance();
}
private List<IModule> createModuleObjects(List<Class<IModule>> classList) {
List<IModule> modules = new ArrayList<IModule>(classList.size());
for (Class<IModule> module : classList) {
try {
modules.add(module.newInstance());
} catch (InstantiationException e) {
System.err.println("Cannot create new instance of class " + module.getName() + ".");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.err.println("IllegalAccess for module: " + module.getName() + ".");
e.printStackTrace();
}
}
return modules;
}
private List<Class<IModule>> extractClassesFromJARs(File[] jars, ClassLoader cl) throws IOException {
List<Class<IModule>> classList = new ArrayList<Class<IModule>>();
for (File jar : jars) {
classList.addAll(extractClassesFromJAR(jar, cl));
}
return classList;
}
#SuppressWarnings("unchecked")
private List<Class<IModule>> extractClassesFromJAR(File jarFile, ClassLoader classLoader) throws IOException {
List<Class<IModule>> classList = new ArrayList<Class<IModule>>();
JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile));
JarEntry ent = null;
while ((ent = jarInputStream.getNextJarEntry()) != null) {
if (ent.getName().toLowerCase().endsWith(".class")) {
try {
Class<?> cls = classLoader.loadClass(ent.getName().substring(0, ent.getName().length() - 6).replace('/', '.'));
if (isModuleClass(cls)) {
classList.add((Class<IModule>) cls);
}
} catch (ClassNotFoundException e) {
System.err.println("Cannot load class " + ent.getName() + ".");
//e.printStackTrace();
}
}
}
jarInputStream.close();
return classList;
}
}

the difference between ClassNotFoundException and NoClassDefFoundError are that the first happens because the named class can't be found on the classpath, the second (which is what you have) occurs when a class can be found but that some other error happens when the class is loaded. With this in mind perhaps there's a static piece of code or initialised member variable that's causing an exception. I have a vague recollection that a class I had once caused this error because I declared and initialised a variable to a resource that at runtime was null i.e. InputStream in = blah.class.getResourceAsStream(..blah...) so when my class that had in as a member was loaded it threw an NPE.
Helps if I actually read the whole stack trace before answering, yes the def error is caused by the ClassNotFoundException which makes things easier it just means that Authorization class isn't accessible on the classpath

Is
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
</dependency>
present in your maven pom.xml?
If yes, try to add corresponding netty-socketio***.jar to classpath where your run your program.

Related

NoClassDefFoundError. Why??? How can I fix it?

I wrote my classloader:
package ru.sberbank.school.homework8;
import ru.sberbank.school.homework8.plugin.Plugin;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class PluginManager extends ClassLoader {
private final String pluginRootDirectory;
public PluginManager(String pluginRootDirectory) {
this.pluginRootDirectory = pluginRootDirectory;
}
public Plugin load(String pluginName, String pluginClassName) {
String name = pluginName + "." + pluginClassName;
try {
Class clazz;
try {
clazz = super.findSystemClass(name);
} catch (ClassNotFoundException e) {
String fileName = pluginRootDirectory + "\\" + pluginName + "\\" + pluginClassName + ".class";
try (FileInputStream fin = new FileInputStream(fileName)) {
byte[] buffer = new byte[(int) (new File(fileName).length())];
fin.read(buffer);
clazz = defineClass(name, buffer, 0, buffer.length);
}
}
return (Plugin)clazz.newInstance();
} catch (IOException | InstantiationException | IllegalAccessException ignored) {
return null;
}
}
}
When I run it:
package ru.sberbank.school.homework8;
import ru.sberbank.school.homework8.plugin.Plugin;
public class PluginManagerTest {
public static void main(String[] args) {
String pluginRootDirectory = "D:\\sbt\\target\\classes\\ru\\sberbank\\school\\homework8";
PluginManager pluginManager = new PluginManager(pluginRootDirectory);
Plugin plugin = pluginManager.load("plugin", "PluginImpl");
if (plugin != null) {
plugin.doUseful();
}
}
}
Exception in thread "main" java.lang.NoClassDefFoundError:
plugin/PluginImpl (wrong name:
ru/sberbank/school/homework8/plugin/PluginImpl) at
java.lang.ClassLoader.defineClass1(Native Method)
I get NoClassDefFoundError. Why??? How can I fix it???
Help me, please!
package ru.sberbank.school.homework8.plugin;
public class PluginImpl implements Plugin {
#Override
public void doUseful() {
System.out.println("My plugin!");
}
}
You get this error because you don't provide the correct FQN of your class, indeed in your load method, you try to find the class corresponding to pluginName + "." + pluginClassName that will be in your case plugin.PluginImpl but the package name of your class PluginImpl is actually ru.sberbank.school.homework8.plugin such that the real FQN of your class is ru.sberbank.school.homework8.plugin.PluginImpl.
To fix this problem, you need to replace:
Plugin plugin = pluginManager.load("plugin", "PluginImpl");
With:
Plugin plugin = pluginManager.load("ru.sberbank.school.homework8.plugin", "PluginImpl");
Or you could modify your method load to add a prefix assuming that you will always retrieve your plugins from the same root package:
public Plugin load(String pluginName, String pluginClassName) {
String name = "ru.sberbank.school.homework8." + pluginName + "." + pluginClassName;

Dynamic Class Loading : Exception in thread "main" java.lang.ClassFormatError

I was trying to perform dynamic class loading from a jar file, unfortunately there was an error:
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1347093252 in class file com/life/Life
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at gloria.MyClassLoader.loadClass(MyClassLoader.java:38)
at gloria.Gloria.main(Gloria.java:9)
Java Result: 1
Here's my code:
MainClass.java
public class MainClass {
public static void main(String[] args) {
try{
ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
Class myObjectClass = classLoader.loadClass("com.life.Life");
//create new class loader so classes can be reloaded.
classLoader = new MyClassLoader(parentClassLoader);
myObjectClass = classLoader.loadClass("com.life.Life");
Life life = (Life) myObjectClass.newInstance();
System.out.println("Message: " + life.getMessage());
}catch(Exception e){
e.printStackTrace();
}
}
}
MyClassLoader.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class MyClassLoader extends ClassLoader{
public MyClassLoader(ClassLoader parent) {
super(parent);
}
#Override
public Class loadClass(String name) throws ClassNotFoundException {
if(!"com.life.Life".equals(name))
return super.loadClass(name);
try {
String url = "http://192.168.1.229:8081/downloads/Life.jar";
URL myUrl = new URL(url);
URLConnection connection = myUrl.openConnection();
InputStream input = connection.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int data = input.read();
while(data != -1){
buffer.write(data);
data = input.read();
}
input.close();
byte[] classData = buffer.toByteArray();
return defineClass("com.life.Life", classData, 0, classData.length);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Life.java
public interface Life {
public String getMessage();
}
What Im doing right here is to instantiate an object that from a jar file and load it in runtime. What's wrong with my code? Any idea?
0xCAFEBABE is the usual first 4 bytes of a Java file.
Your value 1347093252 is 0x504B0304 in hex, which is the magic value for a ZIP file.
As jar is also a zip file. This means that your jar can be corrupt. Try re-building the jar.
You are trying to use a JAR/ZIP file as a CLASS file; a JAR file contains JAR files, but isn't one.
BTW, why won't something like new UrlClassLoader("jar:http://http://192.168.1.229:8081/downloads/!/") work? This will also transparently handle loading classes that Life needs and are located in that JAR.

Custom ClassLoader with resource loading

I'm writing a plugin loader -- it loads jars that are not on the classpath. I wrote a simple custom ClassLoader that takes a JarFile in its constructor and looks in the JarFile for the named class. This loader simply overrides the findClass() method of ClassLoader, and works fine.
Then I determined that I also needed to be able to get resources from the plugin jar. So I overrode findResource(). This had the unexpected result of causing the base plugin class to not be able to find other classes in the jar: I get NoClassDefFoundErrors!
In other words, if I have plugin.jar that contains MyPlugin and MyPluginComponent:
if I do not override findResource(), then I can load the jar, create an instance of MyPlugin, and that in turn can create a MyPluginComponent. However I cannot find resources that are bundled in the jar.
if I do override findResource(), then I can load the jar, create an instance of MyPlugin, but if MyPlugin attempts to create a MyPluginComponent, I get a NoClassDefFoundError.
This suggests that somehow the implementation of findResource() is unable to find class files -- but it's not even getting called (per my logging), so I don't see how that could be the case. How does this interaction work out, and how do I fix it?
I tried to write a small self-contained example, and ran into difficulty manually generating a jar file that wouldn't produce "incompatible magic number" errors. Hopefully whatever I'm doing wrong will be evident from the class loader alone. Sorry for the inconvenience, and thank you for your time.
import com.google.common.io.CharStreams;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.lang.ClassLoader;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Custom class loader for loading plugin classes. Adapted from
* http://kalanir.blogspot.com/2010/01/how-to-write-custom-class-loader-to.html
*/
public static class PluginLoader extends ClassLoader {
private JarFile jarFile_;
public PluginLoader(JarFile jarFile) {
super(Thread.currentThread().getContextClassLoader());
jarFile_ = jarFile;
}
#Override
public Class findClass(String className) {
try {
// Replace "." with "/" for seeking through the jar.
String classPath = className.replace(".", "/") + ".class";
System.out.println("Searching for " + className + " under " + classPath);
JarEntry entry = jarFile_.getJarEntry(classPath);
if (entry == null) {
return null;
}
InputStream stream = jarFile_.getInputStream(entry);
String contents = CharStreams.toString(
new InputStreamReader(stream));
stream.close();
byte[] bytes = contents.getBytes();
Class result = defineClass(className, bytes, 0, bytes.length);
return result;
}
catch (IOException e) {
System.out.println(e + "Unable to load jar file " + jarFile_.getName());
}
catch (ClassFormatError e) {
System.out.println(e + "Unable to read class data for class " + className + " from jar " + jarFile_.getName());
}
return null;
}
#Override
protected URL findResource(String name) {
System.out.println("Asked to find resource at " + name);
try {
String base = new File(jarFile_.getName()).toURI().toURL().toString();
URL result = new URL(String.format("jar:%s!/%s", base, name));
System.out.println("Result is " + result);
return result;
}
catch (IOException e) {
System.out.println(e + "Unable to construct URL to find " + name);
return null;
}
}
#Override
public InputStream getResourceAsStream(String name) {
System.out.println("Getting resource at " +name);
JarEntry entry = jarFile_.getJarEntry(name);
if (entry == null) {
System.out.println("Couldn't find resource " + name);
return null;
}
try {
return jarFile_.getInputStream(entry);
}
catch (IOException e) {
System.out.println(e + "Unable to load resource " + name + " from jar file " + jarFile_.getName());
return null;
}
}
}
If your requirement is to just read extra JAR files extending URLClassLoader might be a better option.
public class PluginLoader extends URLClassLoader {
public PluginLoader(String jar) throws MalformedURLException {
super(new URL[] { new File(jar).toURI().toURL() });
}
}

ClassNotFoundException with dynamically generated and compiled source code [duplicate]

This question already has an answer here:
loading class at runtime in java ClassNotFoundException
(1 answer)
Closed 7 years ago.
The following code works correctly but in some cases when Class.forName method accesses the file it throws ClassNotFoundException because the file is not completely written, I solve the problem in those cases by increasing the sleep time.
But I want a way that forces the thread sleeps until file becomes completely written in stead of the static sleep(5000) ?
public void run(String className, String code) {
String pkgname = "pkg" + (int) (Math.random() * 10000);
String sb = "";
sb += "package " + pkgname + ";\n";
sb += code;
File javaFile = new File(serverPath + pkgname + "/" + className + ".java");
if (javaFile.getParentFile()
.exists() || javaFile.getParentFile().mkdirs()) {
try {
FileWriter writer = new FileWriter(javaFile);
writer.write(sb);
writer.flush();
writer.close();
try {
Thread.sleep(5000);// here is the problem
} catch (InterruptedException ex) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, ex);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, javaFile.getPath());
try {
String[] params = new String[0];
Method method = Class.forName(pkgname + "." + className).getMethod("main", String[].class);
method.invoke(null, (Object) params);
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException | ClassNotFoundException exp) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, exp);
}
}}
Again: my problem is not the logic of the code or of Compiling and executing the file dynamically but it is only related to the sleeping time.
Exception when I decreased sleep to 2000
Jun 27, 2015 3:06:28 AM compile.InlineCompiler run
SEVERE: null
java.lang.ClassNotFoundException: pkg5958.test
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:259)
at compile.InlineCompiler.run(InlineCompiler.java:49)
Writing the file is not the problem:
java.lang.ClassNotFoundException: pkg5958.test means that some a class named test in a package named pkg5989 that the runtime is trying to reference is not on the classpath. This has nothing to do with Thread.sleep().
The directory you are generating the .class file into is not on your classpath.
I could not reproduce your problem, did not think I could.
This works and there is not a single call to Thread.sleep()!
Q31083880.java
import javax.annotation.Nonnull;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
public class Q31083880
{
public static int compile(#Nonnull final File file)
{
final JavaCompiler c = ToolProvider.getSystemJavaCompiler();
return c.run(null, null, null, file.getAbsolutePath());
}
public static void invoke(#Nonnull final String name)
{
try
{
final URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
final Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
final File f = new File(System.getProperty("user.home"));
method.invoke(cl, f.toURI().toURL());
final Method m;
try
{
m = Class.forName(name).getMethod("main", String[].class);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
final String[] args = new String[0];
m.invoke(null, new Object[]{args});
}
catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | MalformedURLException e)
{
throw new RuntimeException(e);
}
}
public static void main(final String[] args)
{
final File f = new File(System.getProperty("user.home"), "Test.java");
try
{
final FileWriter fw = new FileWriter(f);
try
{
final String source = "public class Test { public static void main(String[] args) { System.out.println(\"Testing\"); } }";
fw.write(source);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
try { fw.close(); } catch (final IOException e) { System.err.println(e.getMessage()); }
}
System.out.println(compile(f));
invoke("Test");
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
This compiles to System.getProperty("user.home"); as an example.
It is an exercise to the reader to change this behavior, which should be easy.

CustomerClassLoader: NoClassDefFoundError

I have been playing around with a CustomerClassLoader as i am trying to load a .class file into JUnitCore.runClasses(...); but i am getting the following error
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: SimpleTest (wrong name: JUnit/SimpleTest)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
at Java.CustomClassLoader.access$000(CustomClassLoader.java:16)
at Java.CustomClassLoader$1.run(CustomClassLoader.java:45)
at java.security.AccessController.doPrivileged(Native Method)
at Java.CustomClassLoader.findClass(CustomClassLoader.java:33)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
.....
I don't know what it wrong as I am passing in the correct class name and path for the class. here is the code that i am using
CustomClassLoader
import java.io.FileInputStream;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
public class CustomClassLoader extends ClassLoader {
String repoLocation = "C:/TempBINfolder/bin/JUnit/";
public CustomClassLoader() { }
public CustomClassLoader(ClassLoader parent) {
super(parent);
}
#Override
protected Class<?> findClass(final String name)
throws ClassNotFoundException {
AccessControlContext acc = AccessController.getContext();
try {
return (Class)AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
FileInputStream fi = null;
try {
String path = name.replace('.', '/');
fi = new FileInputStream(repoLocation + path
+ ".class");
byte[] classBytes = new byte[fi.available()];
fi.read(classBytes);
return defineClass(name, classBytes, 0,
classBytes.length);
}catch(Exception e )
{
throw new ClassNotFoundException(name);
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
return super.findClass(name);
}
}
}
And this is how i am calling it
ClassLoader cls= new CustomClassLoader(ClassLoader.getSystemClassLoader());
Class stringClass = null;
try {
stringClass = cls.loadClass("SimpleTest");
} catch (ClassNotFoundException ex) {
Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
}
try {
stringClass.newInstance();
} catch (InstantiationException ex) {
Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(CompilerForm.class.getName()).log(Level.SEVERE, null, ex);
}
JUnitCore.runClasses(stringClass);
Does anyone know why i am getting this error?
Change
stringClass = cls.loadClass("SimpleTest");
to
stringClass = cls.loadClass("JUnit.SimpleTest");
(i.e Add the fully qualified package name of the class file)
and
String repoLocation = "C:/TempBINfolder/bin/JUnit/";
to
String repoLocation = "C:/TempBINfolder/bin/";
You must be declaring your SimpleTest class to be in JUnit package, but you are trying to load is as simply SimpleTest (no package). Try eiteher:
remove the package declaration
remove Junit from location: String repoLocation = "C:/TempBINfolder/bin/";
Class name should be fully qualified junit.samples.SimpleTest
stringClass = cls.loadClass("SimpleTest");
should be
stringClass = cls.loadClass("junit.sample.SimpleTest");
Sometimes this happens to me, and usually it's solved by a clean and build. If that doesn't work, I usually restart my IDE.

Categories

Resources