我的意思是我需要将源代码作为输入传递给线程,并让线程在已经运行的情况下编译并运行源代码?
如何在mapperWordCount类中将源代码传递给map函数,而在整个项目的代码运行时,我的程序需要从扫描仪中获取mapper和reducer代码,并且必须将这些代码放置在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
}
}
答案 0 :(得分:1)
首先要大加警告:必须确保要编译的代码来自哪里,因为这会产生巨大的潜力,代码注入。
另一个警告:如果编译类,您将不能一遍又一遍地重复使用相同的类名,因此您的ClassLoader最终将在OOME之前吞噬掉所有RAM!仅凭这个原因就应该使您找到另一种方式! Edit :自Java 8起,不再有 PermGen空间(用于存储类元数据),而只有 Metaspace 。区别之一是Metaspace是垃圾收集的,而PermGen不是。因此应该减少发生OOME的可能性。
如果您只是想为程序添加更多动态配置,我强烈建议您看看ScriptEngine,它支持ECMAScript(非常接近JavaScript)。框(如果至少使用Oracle的HotSpot JVM)。它将节省您编写自己的ClassLoader和编译代码的开销。
也就是说,如果您仍然希望朝这个方向继续前进,我只是想在这里进行一些尝试,但是您可能必须通过JavaCompiler对象编译文件并注入内容compilation result变成ClassLoader。
如果我有一台要测试的计算机,我会尝试以下操作:
std::option
除了可以在黑暗中进行全面尝试之外,还必须定义自己的ClassLoader,因为defineClass()
方法受到保护。
或者,您也可以使用Runtime.exec()
产生对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.
}
的调用,并直接从生成的javac
中读取字节码字节,甚至可以直接将其生成到类路径中。