[英]How do I pass external source code to a Thread in java?
我的意思是我需要將源代碼作為輸入傳遞給線程,並讓線程編譯並運行已運行的源代碼?
我如何將源代碼傳遞給mapperWordCount類中的map函數,而整個項目的代碼正在運行時,我的程序需要從掃描儀中獲取mapper和reducer代碼,並且必須將這些代碼放置在map函數中,並將reduce函數放入,您可以看一下代碼
用線程我不是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
}
}
首先要大警告:您必須確定要編譯的代碼來自哪里,因為這為代碼注入創造了巨大的潛力。
另一個警告:如果編譯類, 則不能一再使用相同的類名,因此ClassLoader最終將在OOME之前吞噬掉所有RAM! 僅憑這個原因就應該使您找到另一種方式! 編輯 :從Java 8開始,不再有PermGen空間 (用於存儲類元數據的空間 ),而是Metaspace 。 區別之一是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()
方法受到保護。
另外,您也可以使用Runtime.exec()
生成對javac
的調用,並直接從生成的.class
讀取字節碼字節,甚至可以將其直接生成到類路徑中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.