简体   繁体   中英

How do I pass external source code to a Thread in java?

I mean i need to pass the source code as input to a threads and let the thread compile and run the source code while it's already running ?

how could i pass a source code to map function in the mapperWordCount class , while the code of whole project is running , my program needs to take mapper and reducer code from scanner , and the code must be placed inside the map function , and reduce function, you can take a look for the code

by thread i mean not the main thread of java program .

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 
    }
}

A big warning first: you must be sure of where the code you want to compile comes from, as that creates a huge potential for, well, code injection .

Another warning: if you compile classes, you can't reuse the same class name over and over so your ClassLoader will eventually eat up all of your RAM before OOME! That reason alone should make you find another way of doing that! Edit : since Java 8, there is no more PermGen space (where class metadata were stored) but a Metaspace . One of the difference being Metaspace is garbage-collected, when PermGen wasn't; so it should reduce the potential for OOME.

If you're just looking for a way to add a more dynamic configuration to your program, I would strongly suggest you look at ScriptEngine , which supports ECMAScript (very close to JavaScript) out-of-the-box (if you use Oracle's HotSpot JVM at least). It will save you the overhead of writing your own ClassLoader and compiling code.

That said, if you still want to continue in that direction, I'm just guessing here to give to a headstart, but you'll probably have to compile a file through a JavaCompiler object and inject the content of the compilation result into a ClassLoader .

If I had a computer to test, I would try something like:

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.
}

Apart from that being a complete try in the dark, you'll also have to define your own ClassLoader, as the defineClass() method is protected.

Alternatively, you could also spawn a call to javac using Runtime.exec() and reading bytecode bytes directly from the generated .class , or even maybe generate it directly into the classpath.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM