2014-11-06 4 views
1

나는 즉시 생성하는 클래스를 컴파일하기 위해 JavaCompiler을 사용했습니다. 컴파일 태스크가 성공합니다. 그런 다음 Class.forName("MyClass")을 사용하여 컴파일 된 클래스를로드하려고합니다. ClassNotFoundException로 실패합니다. 이 작업과 관련하여 알려진 문제점이 있습니까? 사용하여 컴파일 한 후 클래스를로드JavaCompiler 컴파일 된 클래스를 찾을 수 없습니다.

package com.amir.method; 

import java.io.*; 
import java.lang.reflect.Method; 
import java.net.URI; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.Set; 

import javax.tools.*; 

public class MethodGenerator { 

    private final static MethodGenerator INSTANCE = new MethodGenerator(); 

    private MethodGenerator() { 
    } 

    public static MethodGenerator get() { 
     return INSTANCE; 
    } 


    public static void main(String[] args) { 

     final Class<?> clz = MethodGenerator.get().compile("Foo", "doIt"); //<- args ignored for now 

    } 

    public Class compile(final String className, 
         final String methodName) { 
     try { 
      return doCompile(className, methodName); 
     } catch(final Exception e) { 
      throw new RuntimeException(this.toString(), e); 
     } 

    } 

    private Class doCompile(final String className, 
          final String methodName) throws IOException, ClassNotFoundException { 

     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 

     StringWriter writer = new StringWriter(); 
     PrintWriter out = new PrintWriter(writer); 
     out.println("public class HelloWorld {"); 
     out.println(" public static void main(String args[]) {"); 
     out.println(" System.out.println(\"This is in another java file\");"); 
     out.println(" }"); 
     out.println("}"); 
     out.close(); 

     final JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString()); 
     final Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file); 
     final String classPath = System.getProperty("java.class.path") + File.pathSeparator; 
     final String bootClassPath = System.getProperty("sun.boot.class.path") + File.pathSeparator; 
     final List<String> options = new ArrayList<String>(); 
     options.add("-classpath"); 
     final StringBuilder builder = new StringBuilder(); 
     builder.append(classPath); 
     builder.append(bootClassPath); 
     final URLClassLoader urlClassLoader = (URLClassLoader) ClassLoaderResolver.getClassLoader(); 
     for (final URL url : urlClassLoader.getURLs()) { 
      builder.append(url.getFile()).append(File.pathSeparator); 
     } 
     final int lastIndexOfColon = builder.lastIndexOf(File.pathSeparator); 
     builder.replace(lastIndexOfColon, lastIndexOfColon + 1, ""); 
     options.add(builder.toString()); 

     final JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, options, null, compilationUnits); 

     boolean success = task.call(); 

     if(success) { 
      final Class<?> cls = Class.forName("HelloWorld", true, urlClassLoader); 
      return cls; 
     } 

     return null; 

    } 

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

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

} 
+0

해당 클래스를 내보내거나 가져 오는 경우 매니페스트를 확인 했습니까? 어떻게하면 프로젝트를 구축 할 수 있습니다. 매니페스트 파일을 다시 생성하십시오. – StackFlowed

+0

Manifest? 나는 비행 중에 수업을 편성하고있다. 매니페스트 파일이 무엇을하는지 이해할 수 있습니까? –

+0

클래스를 컴파일해도 클래스 로더에 자동으로 추가되지 않습니다. 너 스스로 그렇게해야 해. – Paul

답변

0

시도, Thread.currentThread().getContextClassLoader().loadClass("com.ur.class");이 도울 수 있다면이 ... 확인을 찾을 수

..

// Create a new custom class loader, pointing to the directory that contains the compiled 
// classes, this should point to the top of the package structure! 
URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()}); 
// Load the class from the classloader by name.... 
Class<?> loadedClass = classLoader.loadClass("com.ur.class"); 
// Create a new instance... 
Object obj = loadedClass.newInstance(); 
// Santity check 
if (obj instanceof com.ur.class) { 
    // code here ... 
} 

자세한 내용은이를 참조 해주십시오 : How do you dynamically compile and load external java classes?

+0

정확히 문자열 인수는 무엇입니까? 댓글 섹션에서 "com.amir.method.HelloWorld"를 사용해야한다고 제안되었지만 작동하지 않는 것 같습니다 ... –

+0

@AmirAfghani 클래스가 속한 패키지는 무엇입니까? –

+0

@VinceEmigh - 생성 된 코드에서 알 수 있듯이 특정 패키지에 없습니다. 내 소스에는 패키지 문이 없습니다. –

관련 문제