JavaFX z Arią - powrót do strony głównej

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