문제

현재의 행동 과정을 중단하라는 경고에도 불구하고, 나는 현재 내 문제를 해결하는 더 좋은 방법을 보지 못하고 있습니다. 나 ~ 해야 하다 생성하다 런타임시 Java 코드를 한 다음 컴파일하고로드하고 참조하십시오..

문제는 이미 시스템 클래스 로더 (IS IS ISS)에 의해 이미로드 된 생성 된 코드 가져 오기 코드, 즉 ClassPath의 항아리 중 하나에 존재한다는 것입니다. (나는 Java 6의 Tomcat 6 웹 컨테이너 안으로 들어갑니다.) 왜 그것이 문제인지 스스로에게 물어볼 수 있습니다 - 잘 물론 모르지만 사실은 컴파일 오류가 발생한다는 것입니다.

/w:/.../parser/v0.5/assignelparser.java:6 : package com.xxx.yyy.zzz.configuration은 존재하지 않습니다

인터넷에서 몇 가지 예제에 따라 다음 수업을 정의했습니다.

class MemoryClassLoader extends ChainedAction {

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

    private LoaderImpl impl;

    private class LoaderImpl extends ClassLoader {

        // The compiler tool
        private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        // Compiler options
        private final Iterable<String> options = Arrays.asList("-verbose");

        // DiagnosticCollector, for collecting compilation problems
        private final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

        // Our FileManager
        private final MemoryFileManager manager = new MemoryFileManager(this.compiler);

        public LoaderImpl(File sourceDirectory) {

            List<Source> list = new ArrayList<Source>();

            File[] files = sourceDirectory.listFiles(new FilenameFilter() {

                @Override
                public boolean accept(File dir, String name) {

                    return name.endsWith(Kind.SOURCE.extension);
                }
            });

            for (File file : files) {
                list.add(new Source(file));
            }

            CompilationTask task = compiler.getTask(null, manager, diagnostics, options, null, list);
            Boolean compilationSuccessful = task.call();

            LOG.info("Compilation has " + ((compilationSuccessful) ? "concluded successfully" : "failed"));

            // report on all errors to screen
            for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                LOG.warn(diagnostic.getMessage(null));
            }
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            synchronized (this.manager) {
                Output output = manager.map.remove(name);
                if (output != null) {
                    byte[] array = output.toByteArray();
                    return defineClass(name, array, 0, array.length);
                }
            }
            return super.findClass(name);
        }
    }

    @Override
    protected void run() {  

        impl = new LoaderImpl(new File(/* Some directory path */));

    }
}



class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {

    final Map<String, Output> map = new HashMap<String, Output>();

    MemoryFileManager(JavaCompiler compiler) {
        super(compiler.getStandardFileManager(null, null, null));
    }

    @Override
    public Output getJavaFileForOutput(Location location, String name, Kind kind, FileObject source) {

        Output output = new Output(name, kind);
        map.put(name, output);

        return output;
    }

}


class Output extends SimpleJavaFileObject {

    private final ByteArrayOutputStream baos = new ByteArrayOutputStream();

    Output(String name, Kind kind) {
        super(URI.create("memo:///" + name.replace('.', '/') + kind.extension), kind);
    }

    byte[] toByteArray() {
        return this.baos.toByteArray();
    }

    @Override
    public ByteArrayOutputStream openOutputStream() {
        return this.baos;
    }
}



class Source extends SimpleJavaFileObject {


    public Source(File file) {
        super(file.toURI(), Kind.SOURCE);
    }


    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {

        StringBuilder sb = new StringBuilder("");
        try {
            File file = new File(uri);
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);

            sb = new StringBuilder((int) file.length());
            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return sb.toString();
    }
}

내부 클래스 로더 클래스를 확장하고 명시 적 슈퍼 생성자를 호출하지 않음으로써 System Class 로더를 모색 클래스 로더로 참조해야합니다.

그렇다면 왜 "런타임"컴파일 오류를 가져 오는 이유는 무엇입니까? 수입 클래스의 코드를 찾지 못하는 이유는 무엇입니까?

도움이 되었습니까?

해결책

그것이 도움이 될 수 있는지 확실하지 않지만 클래스 경로를 명시 적으로 지정하려고 했습니까?

getClassPath()
{
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  URL[] urls = ((URLClassLoader) classLoader).getURLs();
  StringBuilder buf = new StringBuilder(1000);
  buf.append(".");
  String separator = System.getProperty("path.separator");
  for (URL url : urls) {
      buf.append(separator).append(url.getFile());
  }
}

classPath = buf.toString();

그리고

options.add("-classpath");
options.add(getClassPath());

나는 또한 당신이 어디로 통과합니까? LoaderImpl 인스턴스 compiler. 명시 적으로 수행해서는 안됩니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top