0

I'm using a FileWalker to being walking from a specified folder and find all the .class files in the folder and any subsequent sub folders so I can load them using a ClassLoader then use reflection to obtain the declared fields and methods in the class.

This works totally fine for most .class files but I sometimes get a NoClassDefFoundError when trying to load a class and I think it is to do with the location of the file. I'l use an example to illustrate my problem.

If I have the below directory structure:

D:\Users\Ste\Documents\Eclipse Workspace\Project Tests\File Reader
│
├───+bin
│       ReadFile.class
│
└───+src
        ReadFile.java

I give the FileWalker the starting dir of D:\Users\Ste\.....\Project Tests\File Reader and it happily finds the .class file and loads it using a ClassLoader.

However if I add a sub folder to my src and bin folders like so:

D:\Users\Ste\Documents\Eclipse Workspace\Project Tests\File Reader
    │
    ├───+bin
    │   │   ReadFile.class
    │   │
    │   └───+Test
    │           TestClass.class
    │
    └───+src
        │   ReadFile.java
        │
        └───+Test
                TestClass.java

When the program tries to load TestClass.class it gives me this error

!SESSION 2013-02-28 19:54:14.495 -----------------------------------------------
eclipse.buildId=unknown
java.version=1.7.0_13
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_GB
Framework arguments:  -product ste.wootten.honoursproject.product -clearPersistedState
Command-line arguments:  -product ste.wootten.honoursproject.product -data D:\Users\Ste\Documents\Uni Year 3\Project\Implementation/../runtime-honoursproject.product -dev file:D:/Users/Ste/Documents/Uni Year 3/Project/Implementation/.metadata/.plugins/org.eclipse.pde.core/honoursproject.product/dev.properties -os win32 -ws win32 -arch x86_64 -consoleLog -clearPersistedState

!ENTRY org.eclipse.e4.ui.workbench 4 0 2013-02-28 19:54:27.243
!MESSAGE Unable to create class 'ste.wootten.honoursproject.mainpart.CreateMainUI' from bundle '65'
!STACK 0
org.eclipse.e4.core.di.InjectionException: java.lang.NoClassDefFoundError: TestClass (wrong name: Test/TestClass)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:63)
    at org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(InjectorImpl.java:859)
    at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:111)
    at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:319)
    at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:240)
    at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:161)
    at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:102)
    at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:71)
    at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:53)
    at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:141)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:896)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:630)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682)
    at org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.showTab(StackRenderer.java:1114)
    at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:67)
    at org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run(UIEventHandler.java:41)
    at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:180)
    at org.eclipse.swt.widgets.Display.syncExec(Display.java:4687)
    at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:187)
    at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
    at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197)
    at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197)
    at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
    at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135)
    at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
    at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
    at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:81)
    at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
    at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)
    at org.eclipse.e4.ui.model.application.ui.impl.ElementContainerImpl.setSelectedElement(ElementContainerImpl.java:171)
    at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:103)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:646)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682)
    at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:59)
    at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveRenderer.processContents(PerspectiveRenderer.java:59)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:642)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682)
    at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.showTab(PerspectiveStackRenderer.java:103)
    at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:67)
    at org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run(UIEventHandler.java:41)
    at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:180)
    at org.eclipse.swt.widgets.Display.syncExec(Display.java:4687)
    at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:187)
    at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
    at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197)
    at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197)
    at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
    at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135)
    at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
    at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
    at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:81)
    at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
    at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)
    at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:135)
    at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:1)
    at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:103)
    at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.postProcess(PerspectiveStackRenderer.java:77)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:646)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682)
    at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:59)
    at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.processContents(WBWRenderer.java:639)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:642)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:732)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:703)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:697)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:682)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:964)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:923)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
    at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:150)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
Caused by: java.lang.NoClassDefFoundError: TestClass (wrong name: Test/TestClass)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at ste.wootten.honoursproject.mainpart.reflection.ReflectOnClasses.visitFile(ReflectOnClasses.java:136)
    at ste.wootten.honoursproject.mainpart.reflection.ReflectOnClasses.visitFile(ReflectOnClasses.java:1)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:135)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69)
    at java.nio.file.Files.walkFileTree(Files.java:2591)
    at java.nio.file.Files.walkFileTree(Files.java:2624)
    at ste.wootten.honoursproject.mainpart.reflection.ReflectOnClasses.startFileWalk(ReflectOnClasses.java:39)
    at ste.wootten.honoursproject.mainpart.CreateMainUI.selectDirectoryAndBeginFileWalk(CreateMainUI.java:258)
    at ste.wootten.honoursproject.mainpart.CreateMainUI.createInterface(CreateMainUI.java:159)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
    ... 104 more

I have tested this out on lot's of other directories and the same problem occurs. It seems to be caused by a .class file being in sub folders but I'm not sure why.

Here is my code to walk a file system and load the .class files found:

package ste.wootten.honoursproject.mainpart.reflection;

import ste.wootten.honoursproject.mainpart.CreateMainUI;


public class ReflectOnClasses extends SimpleFileVisitor<Path> {

    //Starts the file walk from a starting directory
    public static void startFileWalk(String directory){

        //The startingDir is the directory the user selects on the MainUI Part
        Path startingDir = FileSystems.getDefault().getPath(directory, "");

        //Create an instance of my FileVisitor
        ReflectOnClasses reflectOnClasses = new ReflectOnClasses();

        try {
            //Walk the files from my startingDir using reflectOnClasses
            Files.walkFileTree(startingDir, reflectOnClasses);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("An Error Occured");
            e.printStackTrace();
        }
    }

    //Visit files and do something with them
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {

        //If we find a .class file get it and reflect upon it
        if(file.toString().endsWith(".class")){

            //String holding the files parents directory
            String filesParentDir = file.getParent().toString();

            //Create a File object on the root of the directory containing the class file (it's parent directory)
            File parentDir = new File(filesParentDir);

            try{

                //Convert parentDir to URL
                URL url = parentDir.toURL();
                URL[] urls = new URL[]{url};

                //Create a new class loader with the directory
                ClassLoader cl = new URLClassLoader(urls);

                //Get the name of the file with .class removed from the end so we can load it
                String classToLoad = file.getFileName().toString().replace(".class", "");

                //Load in the class
                Class cls = cl.loadClass(classToLoad);


                //Pass the name of the class to addClassToVariableTree in CreatUI so it can be added as a TreeItem
                CreateMainUI.addClassToVariableTree(classToLoad);
                //Do the same for addClassToMethodTree
                CreateMainUI.addClassToMethodTree(classToLoad);

                //Array of the declared fields in the class
                Field[] fieldsInClass = cls.getDeclaredFields();

                //For each field in fieldsInClass we add it as a TreeItem using addVariableToClassTreeItem
                for( Field field: fieldsInClass){
                    CreateMainUI.addVariableToClassNameTreeItem(field.getGenericType().toString(), field.getName());
                }

                //Array of all methods in the class
                Method[] methodsInClass = cls.getDeclaredMethods();

                //For each method we pass through the string representation of it, the class it belongs too and it's name. It will be formatted in CreateUI
                for (Method method : methodsInClass) {
                    CreateMainUI.addMethodToClassNameTreeItem(method.toString(), classToLoad, method.getName());
                }


            } catch (MalformedURLException e) {
                System.out.println("URL BAD");
            } catch (ClassNotFoundException e){
                System.out.println("Class couldnt be found");
            }

        }

        return CONTINUE;

    }

    //Print out each directory visited
    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        //System.out.format("Directory: %s%n", dir);
        return CONTINUE;
    }

    //If there is some error accessing the file, let the user know.
    //If you don't override this method an error occurs, an IOException is thrown
    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.err.println(exc);
        return CONTINUE;
    }

}
SteWoo
  • 458
  • 1
  • 8
  • 21
  • 1
    I'm not familiar with the Path API you're using, but it looks like you're trying to load the class without the package name. For example, it looks like you're trying to load test/TestClass.class with the name "TestClass" instead of "test.TestClass". – Eric Galluzzo Feb 28 '13 at 21:01
  • I see, that makes sense. How would I go about obtaining the package name of the .class file I have? There doesn't seem to be any getPackageInfo() method available to get the package name. I have seen an example [here](http://stackoverflow.com/questions/10993418/package-getpackage-in-java-returning-null) to get Package information but from what I can see that invovles either knowing the name of the package already or having the class loaded. – SteWoo Feb 28 '13 at 22:00
  • It should be a simple matter of converting the path name into a package name. For example, if you're loading from a classpath root directory of `/home/stewoo/classes`, then the class file `/home/stewoo/classes/test/TestClass.class` would have fully qualified name `test.TestClass`. Obtaining this fully qualfied name is often just a matter of calling `String.replace(File.separatorChar, '.')`. – Eric Galluzzo Mar 01 '13 at 15:19
  • I managed to create the package name by recursively getting the parent file of the current file or folder and adding it to a string. It's a little bit of a work around but I can at least get the package name now. But now I've ran into a ClassNotFoundException...Oh the joys of programming – SteWoo Mar 01 '13 at 17:21
  • Ha! I feel your pain. :) It's been ages since I implemented a `ClassLoader`, but I seem to remember it was no fun. – Eric Galluzzo Mar 01 '13 at 17:48

0 Answers0