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.
Related
I am trying to use the java.nio-API for traversing a .zip-file, but I get a ProviderNotFoundException when I try to call FileSystems.newFileSystem.
I have also tried changing the zip:file: to jar:file:, but I get the same kind of exception except that the message says Provider "jar" not found.
I have also tried using FileSystems.newFileSystem(Path, null) directly without creating an URI first.
Output:
Reading zip-file: /home/pyknic/Downloads/Walking.zip
Exception in thread "main" java.nio.file.ProviderNotFoundException: Provider "zip" not found
at java.base/java.nio.file.FileSystems.newFileSystem(FileSystems.java:364)
at java.base/java.nio.file.FileSystems.newFileSystem(FileSystems.java:293)
at com.github.pyknic.zipfs.Main.main(Main.java:19)
Main.java
package com.github.pyknic.zipfs;
import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.util.stream.StreamSupport;
import static java.lang.String.format;
import static java.util.Collections.singletonMap;
public class Main {
public static void main(String... args) {
final Path zipFile = Paths.get(args[0]);
System.out.println("Reading zip-file: " + zipFile);
final URI uri = URI.create("zip:file:" + zipFile.toUri().getPath().replace(" ", "%20"));
try (final FileSystem fs = FileSystems.newFileSystem(uri, singletonMap("create", "true"))) {
final long entriesRead = StreamSupport.stream(fs.getRootDirectories().spliterator(), false)
.flatMap(root -> {
try {
return Files.walk(root);
} catch (final IOException ex) {
throw new RuntimeException(format(
"Error traversing zip file system '%s', root: '%s'.",
zipFile, root), ex);
}
}).mapToLong(file -> {
try {
Files.lines(file).forEachOrdered(System.out::println);
return 1;
} catch (final IOException ex) {
throw new RuntimeException(format(
"Error modifying DAE-file '%s' in zip file system '%s'.",
file, zipFile), ex);
}
}).sum();
System.out.format("A total of %,d entries read.%n", entriesRead);
} catch (final IOException ex) {
throw new RuntimeException(format(
"Error reading zip-file '%s'.", zipFile
), ex);
}
}
}
How do I get access to the file system of a zip-file with the Java Nio-APIs?
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;
EDIT: This does not seem to be possible, see https://bugs.openjdk.java.net/browse/JDK-8039910.
I have a helper class that provides a Stream<Path>. This code just wraps Files.walk and sorts the output:
public Stream<Path> getPaths(Path path) {
return Files.walk(path, FOLLOW_LINKS).sorted();
}
As symlinks are followed, in case of loops in the filesystem (e.g. a symlink x -> .) the code used in Files.walk throws an UncheckedIOException wrapping an instance of FileSystemLoopException.
In my code I would like to catch such exceptions and, for example, just log a helpful message. The resulting stream could/should just stop providing entries as soon as this happens.
I tried adding .map(this::catchException) and .peek(this::catchException) to my code, but the exception is not caught in this stage.
Path checkException(Path path) {
try {
logger.info("path.toString() {}", path.toString());
return path;
} catch (UncheckedIOException exception) {
logger.error("YEAH");
return null;
}
}
How, if at all, can I catch an UncheckedIOException in my code giving out a Stream<Path>, so that consumers of the path do not encounter this exception?
As an example, the following code should never encounter the exception:
List<Path> paths = getPaths().collect(toList());
Right now, the exception is triggered by code invoking collect (and I could catch the exception there):
java.io.UncheckedIOException: java.nio.file.FileSystemLoopException: /tmp/junit5844257414812733938/selfloop
at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:88)
at java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:104)
at java.util.Iterator.forEachRemaining(Iterator.java:115)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at ...
EDIT: I provided a simple JUnit test class. In this question I ask you to fix the test by just modifying the code in provideStream.
package somewhere;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.fail;
public class StreamTest {
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#Test
public void test() throws Exception {
Path rootPath = Paths.get(temporaryFolder.getRoot().getPath());
createSelfloop();
Stream<Path> stream = provideStream(rootPath);
assertThat(stream.collect(Collectors.toList()), is(not(nullValue())));
}
private Stream<Path> provideStream(Path rootPath) throws IOException {
return Files.walk(rootPath, FOLLOW_LINKS).sorted();
}
private void createSelfloop() throws IOException {
String root = temporaryFolder.getRoot().getPath();
try {
Path symlink = Paths.get(root, "selfloop");
Path target = Paths.get(root);
Files.createSymbolicLink(symlink, target);
} catch (UnsupportedOperationException x) {
// Some file systems do not support symbolic links
fail();
}
}
}
You can make your own walking stream factory:
public class FileTree {
public static Stream<Path> walk(Path p) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(FileTree::walk)
.onClose(()->{ try { ds.close(); } catch(IOException ex) {} }));
} catch(IOException ex) {}
return s;
}
// in case you don’t want to ignore exceprions silently
public static Stream<Path> walk(Path p, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
// and with depth limit
public static Stream<Path> walk(
Path p, int maxDepth, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(maxDepth>0 && Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, maxDepth-1, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
}
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.
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.