0

我正在使用FileWalker从指定文件夹中走动并查找.class文件夹中的所有文件以及任何后续子文件夹,以便我可以使用ClassLoader然后使用反射来加载它们以获取类中声明的字段和方法。

这对于大多数文件来说都很好,.class但我有时会NoClassDefFoundError在尝试加载一个类时得到一个,我认为这与文件的位置有关。我将用一个例子来说明我的问题。

如果我有以下目录结构:

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

我给出了FileWalker的起始目录,D:\Users\Ste\.....\Project Tests\File Reader它很高兴地找到了.class文件并使用ClassLoader.

但是,如果我将子文件夹添加到我的srcbin文件夹中,如下所示:

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

当程序尝试加载TestClass.class它给我这个错误

!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

我已经在很多其他目录上对此进行了测试,并且出现了同样的问题。这似乎是由.class子文件夹中的文件引起的,但我不知道为什么。

这是我遍历文件系统并加载.class找到的文件的代码:

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;
    }

}
4

0 回答 0