Вопрос

I have a Ruby script that I'd like to run at the startup of my Java program.

When you tell the ScriptEngine to evaluate the code for the first time, it takes a while. I'm under the impression that the reason it takes this long is because it first needs to compile the code, right?

I found that you can compile Ruby code, and then evaluate it later. The evaluation itself is fast - the compilation part is the slow one. Here I am compiling:

    jruby = new ScriptEngineManager().getEngineByName("jruby");

    Compilable compilingEngine = (Compilable)jruby;

    String code = "print 'HELLO!'";

    CompiledScript script;
    script = compilingEngine.compile(code);

This snippet is what takes a while. Later when you evaluate it, it is fine.

So of course, I was wondering if it would be possible to "save" this compiled code into a file, so in the future I can "load" it and just execute it without compiling again.

Это было полезно?

Решение

As others have said, this is not possible with CompiledScript. However, with JRuby you have another option. You can use the command line tool jrubyc to compile a Ruby script to Java bytecode like so:

jrubyc <scriptname.rb>

This will produce a class file named scriptname.class. You can run this class from the command line as if it were a normal class with a main(String[] argv) method (note: the jruby runtime needs to be in the classpath) and you can of course load it into your application at runtime.

You can find more details on the output of jrubyc here: https://github.com/jruby/jruby/wiki/JRubyCompiler#methods-in-output-class-file

Другие советы

According to this, no.

"Unfortunately, compiled scripts are not, by default, serializable, so they can't be pre-compiled as part of a deployment process, so compilation should be applied at runtime when you know it makes sense."

I think some really easy cache will solve your problem:

class CompiledScriptCache {

    static {
         CompiledScriptCache INSTANCE = new CompiledScritCache();
    }

    publich static CompiledScriptCache get(){
        retrun INSTANCE;
    };

    List<CompiledScript> scripts = new ArrayList<>();

    public CompiledScript get(int id){
        return scripts.get(id);
    }

    public int add(String code){

        ScriptEngine jruby = new ScriptEngineManager().getEngineByName("jruby");

        Compilable compilingEngine = (Compilable)jruby;

        CompiledScript script;
        script = compilingEngine.compile(code);
        scripts.add(script);
        return scripts.size()-1;

    }


}

update

I thought this question was about avoiding to comile the source more than once.

Only other approach I could imagine is to create Java-Classes and make a cross-compile:

https://github.com/jruby/jruby/wiki/GeneratingJavaClasses

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top