簡體   English   中英

如何將外部源代碼傳遞給Java中的線程?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM