在代码中编译,没有得到我想要的行为. [英] Compiling within code, not getting behavior I'd like.

查看:118
本文介绍了在代码中编译,没有得到我想要的行为.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一些代码-我想编译字符串'temp',然后执行它,然后更改字符串,重新编译并执行.问题是当前它只是首先执行第一部分代码.

So I've got some code - I'd like to compile the string 'temp' then execute it, then change the string, recompile and execute. Problem is that currently it's just executing the first bit of code first.

我希望:

This is in another java file
How about now?

我得到:

This is in another java file
This is in another java file

完整代码如下,任何帮助表示赞赏.

Full code follows, any help appreciated.

import java.io.IOException;
import java.util.Arrays;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;

public class Another2 {

    public static void main(String args[]) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

        //First run
        String temp = "public class HelloWorld {\n" + "  public static void main(String args[]) {\n"
                + "    System.out.println(\"First Compiled Class\");\n" + "  }\n" + "}";

        JavaFileObject file = new JavaSourceFromString("HelloWorld", temp);
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
        task.call();
        try {
            Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class })
                    .invoke(null, new Object[] { null });
        } catch (Exception e) {
            // handled it
        }

        //second run
        temp = "public class HelloWorld {\n" + "  public static void main(String args[]) {\n"
                + "    System.out.println(\"How About Now?\");\n" + "  }\n" + "}";
        file = new JavaSourceFromString("HelloWorld", temp);
        Iterable<? extends JavaFileObject> compilationUnits2 = Arrays.asList(file);
        task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits2);
        task.call();
        try {
            Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class })
                    .invoke(null, new Object[] { null });
        } catch (Exception e) {
            // handled it
        }
    }

}

推荐答案

事实证明,我正在寻找的代码是:

It turns out that the code I was looking for was:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;

public class AnotherClassLoaderRunner {

    private static final String nameOfDemoClass = "ByeWorld";

    public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException,
            IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        // Start compilation and loading of first class.
        String sourceCode = "public class " + nameOfDemoClass + " {\n" + "  public static void main(String args[]) {\n"
                + "    System.out.println(\"First of our Compiled Class\");\n" + "  }\n" + "}";
        AnotherClassLoader classLoader = new AnotherClassLoader(AnotherClassLoaderRunner.class.getClassLoader(), nameOfDemoClass);
        Class<?> myclass = classLoader.loadClass(nameOfDemoClass,sourceCode);
        Method mymethod = myclass.getDeclaredMethod("main", new Class[] { String[].class });
        mymethod.invoke(null, new Object[] { null });

        // Start compilation and loading of second class.
        sourceCode = sourceCode.replace("First of our Compiled Cla", "Second of our Compiled Cla");
        classLoader = new AnotherClassLoader(AnotherClassLoaderRunner.class.getClassLoader(), nameOfDemoClass);
        myclass = classLoader.loadClass(nameOfDemoClass,sourceCode);
        mymethod = myclass.getDeclaredMethod("main", new Class[] { String[].class });
        mymethod.invoke(null, new Object[] { null });
    }
}

class AnotherClassLoader extends ClassLoader {

    private static final String pathToClassDirectory = "file:/Users/*********/Documents/workspace/Dynamic/src/";
    private String targetName;

    public AnotherClassLoader(ClassLoader parent, String target) {
        super(parent);
        targetName = target;
    }

    public Class<?> loadClass(String name, String compileme) throws ClassNotFoundException {
        if (!targetName.equals(name)) {
            return super.loadClass(name);
        }
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        JavaFileObject file = new JavaSourceFromString(name, compileme);
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        CompilationTask task = compiler.getTask(null, null, new DiagnosticCollector<JavaFileObject>(), null, null,
                compilationUnits);
        task.call();
        // THE CLASSFILE FOR THE SYSTEM EXSITS AT THIS POINT, thought how it
        // chooses the directory escapes me.
        try {
            String url = pathToClassDirectory + targetName + ".class";
            URL myUrl = new URL(url);
            URLConnection connection = myUrl.openConnection();
            InputStream input = connection.getInputStream();
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int data = input.read();
            while (data != -1) {
                buffer.write(data);
                data = input.read();
            }
            input.close();
            byte[] classData = buffer.toByteArray();

            return defineClass(targetName, classData, 0, classData.length);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        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;
    }
}

这篇关于在代码中编译,没有得到我想要的行为.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆