无法找到动态加载的类

时间:2017-10-12 12:35:54

标签: java classloader

我正在尝试使用Class.forName()加载类,但它给了我异常java.lang.ClassNotFoundException: Test

实际上Test是在eclipse工作目录here is the image中创建的,但它是在bin文件夹之外创建的。 如果我尝试使用命令提示符运行它正常工作。

代码下面的

public class CompileString {

public static void main(String arges[]) throws Exception{

    JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
     String program = " class Test{" + "   public static void main (String [] args){"
                + "      System.out.println (\"Hello, World\");"
                + "      System.out.println (args.length);" + "   }" + "}"
                +"interface demo{}"         
                ;

     Iterable<? extends JavaFileObject> fileObjects;
        fileObjects = getJavaSourceFromString(program);

        Boolean result=compiler.getTask(null, null, null, null, null, fileObjects).call();
        System.out.println(result);


        Class<?> clazz=null;
        try {
            clazz = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
              System.out.println(clazz);
            e.printStackTrace();

        }
        Method m = clazz.getMethod("main", new Class[] { String[].class });
        Object[] _args = new Object[] { new String[0] };
        m.invoke(null, _args);
      }

      static Iterable<JavaSourceFromString> getJavaSourceFromString(String code) {
        final JavaSourceFromString jsfs;
        jsfs = new JavaSourceFromString("demo", code);
        return new Iterable<JavaSourceFromString>() {
          public Iterator<JavaSourceFromString> iterator() {
            return new Iterator<JavaSourceFromString>() {
              boolean isNext = true;

              public boolean hasNext() {
                return isNext;
              }

              public JavaSourceFromString next() {
                if (!isNext)
                  throw new NoSuchElementException();
                isNext = false;
                return jsfs;
              }

              public void remove() {
                throw new UnsupportedOperationException();
              }
            };
          }
        };
      } 

}

另一类:

class JavaSourceFromString extends SimpleJavaFileObject {
  final String code;

  JavaSourceFromString(String name, String code) {
    super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
    this.code = code;
  }

  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
    return code;
  }
}

它给了我运行时异常

  

java.lang.ClassNotFoundException:Test

所有正常工作的编译器JavaCompiler compiler=ToolProvider.getSystemJavaCompiler()都会true,但为什么我找不到Test.class

1 个答案:

答案 0 :(得分:1)

为什么此代码不起作用

Eclipse在与程序运行的目录不同的目录中生成类文件,而当您从命令行运行它时,您使用相同的值。

如何修复

解决此问题的最简单方法是使用URLClassLoader加载类,以便指定用于查找类文件的目录。

示例代码(使用Java 9中的List.of)

import java.io.File;
import java.io.IOException;
import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URLClassLoader;
import java.util.*;
import java.util.logging.Logger;
import javax.tools.*;

public final class CompileString {

    static class JavaSourceFromString extends SimpleJavaFileObject {
        private final String code;

        JavaSourceFromString(final String name, final String code) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(final boolean ignoreEncodingErrors) {
            return code;
        }
    }

    private CompileString() {}

    private static final Logger LOG = Logger.getLogger(CompileString.class.getCanonicalName());

    private static final JavaCompiler COMPILER = ToolProvider.getSystemJavaCompiler();
    public static void main(final String...args) {

        final String program =
            "public class Test{" +
            "   public static void main (String [] args) {" +
            "      System.out.println (\"Hello, World\");" +
            "      System.out.println (args.length);" +
            "   }" +
            "}";

        final List <JavaSourceFromString> fileObjects = List.of(new JavaSourceFromString("Test", program));

        final boolean result = COMPILER.getTask(null, null, null, null, null, fileObjects).call();
        LOG.info("Compilation result was: " + result);

        final URL url;
        try {
            url = new File("./").toURI().toURL();
        } catch (final MalformedURLException ex) {
            throw new AssertionError("Bad URL? (Really shouldn't happen)", ex);
        }

        try (URLClassLoader loader = new URLClassLoader(new URL[] {url})) {
            final Class<?> clazz = loader.loadClass("Test");
            final Method main = clazz.getMethod("main", String[].class);
            final Object[] invocationArguments = {new String[] {}};
            main.invoke(null, invocationArguments);
        } catch (final ClassNotFoundException ex) {
            throw new AssertionError("Bad class name", ex);
        } catch (final IOException ex) {
            throw new AssertionError("IO Error", ex);
        } catch (final NoSuchMethodException ex) {
            throw new AssertionError("Missing main method", ex);
        } catch (final IllegalAccessException ex) {
            throw new AssertionError("Class or main method not public", ex);
        } catch (final InvocationTargetException ex) {
            throw new AssertionError("Exception thrown by main method", ex);
        }
    }

}