Как передать внешний исходный код в поток в Java? - PullRequest
0 голосов
/ 29 июня 2019

Я имею в виду, что мне нужно передать исходный код в качестве входных данных потокам и позволить потоку скомпилировать и запустить исходный код, пока он уже запущен?

как я могу передать исходный код функции map в классе mapperWordCount, пока выполняется код всего проекта, моей программе нужно взять код сканера и преобразователя из сканера, а код должен быть помещен в функцию map, и уменьшить функцию, вы можете посмотреть код

Я имею в виду не основной поток Java-программы.

class mapper extends Thread{

    // some code 

    @Override
    public void run() {
        mapper.map(bucket,reader);
    }
}
class mapperWordCount implement Mapper{
    public void map ( Bucket bucket , Reader reader){
        // code for word count mapper , this code must be entered by scanner as input , and compiled and run while the project is running 
    }
}
class reducer extends Thread{

    // some code 

    @Override
    public void run() {
        Reducer.reduce(bucket,reader);
    }
}
class reducerWordCount implement Reducer {
    public void reduce ( Bucket bucket , MapOfKeysAndLists keyListOfKeysAndValues){
        // code for reducer , this code must be entered by scanner as input , and compiled and run while the project is running 
    }
}

1 Ответ

1 голос
/ 29 июня 2019

Сначала большое предупреждение: вы должны быть уверены в том, откуда исходит код, который вы хотите скомпилировать, поскольку это создает огромный потенциал для, ну, в общем, внедрения кода.

Еще одно предупреждение: если вы компилируете классы, вы не можете использовать одно и то же имя класса снова и снова , поэтому ваш ClassLoader в конечном итоге съест всю вашу оперативную память перед OOME!Одна только эта причина должна заставить вас найти другой способ сделать это! Редактировать : начиная с Java 8, больше нет пространства PermGen (где хранились метаданные класса), но метапространство .Одно из различий заключается в том, что Metaspace собирает мусор, а PermGen нет;так что это должно уменьшить потенциал для OOME.

Если вы просто ищете способ добавить более динамичную конфигурацию в вашу программу, я настоятельно рекомендую вам взглянуть на ScriptEngine , которыйподдерживает ECMAScript (очень близко к JavaScript) "из коробки" (если вы используете Oracle HotSpot JVM по крайней мере).Это избавит вас от лишних затрат на написание собственного ClassLoader и компиляцию кода.

Тем не менее, если вы все еще хотите продолжить в этом направлении, я просто предполагаю, что здесь будет дан старт, но вывероятно, придется скомпилировать файл с помощью JavaCompiler объекта и вставить содержимое результата компиляции в ClassLoader .

Если бы у меня былчтобы протестировать компьютер, я бы попробовал что-то вроде:

Files[] files = ... ; // input for first compilation task
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files));
compiler.getTask(null, fileManager, null, null, null, compilationUnits).call().get(); // Compile the class and wait for it to finish
Class<?> cls = null;
for (JavaFileObject compiledClass : compilationUnits) {
    if (compiledClass.getKind() != Kind.CLASS)
        continue;
    int n;
    byte[] classData;
    try (InputStream is = compiledClass.openInputStream()) {
        classData = new byte[1024]; // DO A PROPER FULL READ HERE!
        n = is.read(classData);
    } // catch Exceptions here
    cls = myClassLoader.defineClass(className, classData, 0, n);
    break;
}
if (cls != null) {
    // Now, cls.newInstance() etc.
}

Помимо того, что это полная попытка в темноте, вам также придется определить свой собственный ClassLoader, как defineClass()*Метод 1036 * защищен.

Кроме того, вы также можете вызвать вызов javac, используя Runtime.exec() и считывая байты байт-кода непосредственно из сгенерированного .class, или даже, возможно, сгенерироватьэто прямо в classpath.

...