Kompilowanie skryptów
W przypadku skryptów kompilacja ma dwa znaczenia:
- Kompilacja w znaczeniu JVM oznacza przekształcenie kodu źródłowego w plikach .java czy .groovy w kod bajtowy w plikach .class
- W znaczeniu Java Scripting API oznacza kompilację do obiektu
CompiledScript
. Ten obiekt może być klasą Java (.java), skompilowaną klasą java (.class) albo kodem operacyjnym specyficznym dla języka.
-
Kod skryptu jest parsowany przy każdej ewaluacji. Kompilacja do obiektu
CompiledScript
jest wykonywana podczas pierwszej ewaluacji, a potem skrypt może być uruchamiany wielokrotnie.Aby to było możliwe silnik skryptu musi implementować interfejs
Compilable
– co zapewniają lub nie twórcy skryptu.Silnik języka Groovy daje możliwość kompilacji skryptów.
Klasa E12_CompilableTest
package jsr223groovy; import javax.script.Bindings; import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import java.io.IOException; import java.io.Reader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; public class E12_CompilableTest { public static void main(String[] args) { String fileName = "src/scripts/skrypt3.groovy"; Path path = Paths.get(fileName); if (! Files.exists(path) ) { System.out.println(path.toAbsolutePath() + " nie istnieje."); return; } ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("Groovy"); if (!(engine instanceof Compilable comp)) { System.out.println("Kompilacja skryptu nie jest dostępna."); return; } try { Reader reader = Files.newBufferedReader(path); CompiledScript cScript = comp.compile(reader); Bindings scriptParams = engine.createBindings(); scriptParams.put("a", 125); scriptParams.put("b", 3); //- Instant start1 = Instant.now(); cScript.eval(scriptParams); Instant end1 = Instant.now(); long millis1 = Duration.between(start1, end1).toMillis(); //- scriptParams.put("a", 127); scriptParams.put("b", 7); Instant start2 = Instant.now(); cScript.eval(scriptParams); Instant end2 = Instant.now(); long millis2 = Duration.between(start2, end2).toMillis(); //- System.out.println("Czas wykonania w ms: " + millis1); System.out.println("Czas wykonania w ms: " + millis2); } catch (ScriptException | IOException e) { e.printStackTrace(); } } }
Skrypt skrypt3.groovy
package scripts def dividing(int a, int b){ def a1 = a.intdiv(b) def a2 = a % b def res = [a1, a2] as int[] return res; } result = dividing(a,b) println("dividing($a, $b) = $result")
Po uruchomieniu klasy na konsoli zobaczymy:
dividing(125, 3) = [41, 2] dividing(127, 7) = [18, 1] Czas wykonania w ms: 278 Czas wykonania w ms: 4
Przy pierwszej ewaluacji skrypt został skompilowany. Przy drugim nie było już takiej potrzeby. Różnica w czasie wykonywania jest astronomiczna.
Klasa module-info.java
module jsr223groovy { requires org.apache.groovy; requires java.scripting; requires java.sql; exports jsr223groovy; opens jsr223groovy; }