Eval Java-Quelle von Java

Vor kurzem habe ich eine Java-Anwendung entwickelt, die Java-Quellcode in meinem Unternehmen analysiert. In einigen Fällen wollte ich jedoch einen Teil des zu analysierenden Quellcodes bewerten. Also habe ich den Java-Quellcode ausgewertet und leicht untersucht, wie ich zu den Ergebnissen komme.

Den für das Experiment verwendeten Quellcode finden Sie unter tanzaku / eval \ -java \ -code. Der Master enthält den JDK10-Testcode und der Zweig eval_jdk8 enthält den JDK8-Testcode.

Verwendung der Java Compiler API

Sie können eine Instanz von Class mit der Methode abrufen, wie auf der folgenden Site gezeigt, sodass Sie sie auswerten können, indem Sie die Methode mit Reflektion ausführen. Java Compiler Class Memo \ (Hishidamas JavaCompiler Memo )

Wenn Sie keine detaillierten Anpassungen vornehmen möchten, kann es zweckmäßig sein, eine Bibliothek wie die folgende zu verwenden. OpenHFT/Java-Runtime-Compiler: Java Runtime Compiler

Wie als Groovy-Skript zu bewerten

Es kann einfach durch Aufrufen von "ScriptEngine # eval" wie unten gezeigt ausgewertet werden. (groovy-all muss dem Klassenpfad hinzugefügt werden)

package experiments.eval.evaluator;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class GroovyEvaluator {
	private static ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("groovy");

	public String eval(final String sourceCode) throws ScriptException {
		return scriptEngine.eval(sourceCode).toString();
	}
}

Beachten Sie jedoch, dass der Java-Quellcode möglicherweise kein gültiges Groovy-Skript ist. Zum Beispiel sollte ein Ausdruck wie "new String [] {" A "}" in groovy ungültig sein und wie "[" A "] als String []" sein.

Wie von JShell zu bewerten

Sie kann mithilfe der in Java 9 hinzugefügten JShell-API bewertet werden. JShell (Java SE 9 & JDK 9 )

package experiments.eval.evaluator;

import java.util.Arrays;
import java.util.stream.Stream;

import jdk.jshell.JShell;
import jdk.jshell.SnippetEvent;

public class JShellEvaluator {
	private Stream<String> splitStatements(final String sourceCode) {
		return Arrays.stream(sourceCode.split(";")).map(stmt -> stmt + ";");
	}
	
	public String eval(final String sourceCode) {
		try (final JShell jshell = JShell.create()) {
			//Es scheint, dass mehrere Anweisungen nicht gleichzeitig ausgewertet werden können. Bewerten Sie sie daher separat.
			return splitStatements(sourceCode)
						.flatMap(stmt -> jshell.eval(stmt).stream())
						.reduce((a,b)->b)
						.map(SnippetEvent::value)
						.orElse(null);
		}
	}
}

Vergleich der Bearbeitungszeit

Die Verarbeitungszeit, wenn sie mit jeder Methode bewertet wurde, wurde gemessen. Wir messen die Zeit, die benötigt wird, um einen kleinen Prozess 100 Mal zu bewerten. Die 100 Operationen unterscheiden sich geringfügig, sodass sie nicht zwischengespeichert werden. Weitere Informationen finden Sie im Quellcode.

Methode JDK ver Verarbeitungszeit[sec]
Java Compiler API Oracle JDK 8 14.732
Java Compiler API Oracle JDK 10 42.743
groovy Oracle JDK 8 3.578
groovy Oracle JDK 10 4.914
JShell API Oracle JDK 10 147.294

Fazit

Der Quellcode ist prägnant und scheint in der Geschwindigkeit nicht minderwertig zu sein. Daher scheint es gut, ihn mit Groovy zu bewerten. In jedem Fall ist es jedoch definitiv ein sehr schwerer Prozess, so dass es schwierig zu sein scheint, ihn häufig zu verwenden. Wenn sich die Version des Compilers ändert, ändert sich natürlich die Leistung. Seien Sie daher beim Upgrade vorsichtig.

Recommended Posts

Eval Java-Quelle von Java
[Java] Fluss vom Quellcode zur Ausführung
Rufen Sie Java von JRuby aus auf
Kommentare in der Java-Quelle
Java (geteilte Quelldatei)
Lesen Sie die Java HashMap-Quelle
Greifen Sie über Java auf API.AI zu
Von Java zu Ruby !!
Migration von Cobol nach JAVA
Java ab Anfänger überschreiben
Neue Funktionen von Java7 bis Java8
Stellen Sie eine Verbindung von Java zu PostgreSQL her
Java, Instanz für Anfänger
Java ab Anfänger, Vererbung
Java-Leben von vorne anfangen
[Java] Tipps zum Schreiben der Quelle
Verwenden von Docker von Java Gradle
Von ineffektivem Java zu effektivem Java
JavaScript von Java aus gesehen
Führen Sie Nicht-Java-Anweisungen von Java aus
Rufen Sie Kotlins versiegelte Klasse von Java aus an
Java, abstrakte Klasse für Anfänger
Code Java von Emacs mit Eclim
Deep Learning Java von Grund auf 6.4 Regularisierung
Land von IP-Adresse abrufen (Java)
Führen Sie node.js von Android Java aus (Verarbeitung)
Führen Sie eine Batchdatei von Java aus
[Java] Entfernen Sie Leerzeichen in Zeichenfolgen
Akka praktische Vorbereitungsprozedur aus Java
Greifen Sie über eine Java-Anwendung auf Teradata zu
Verwenden Sie Chrome Headless von Selenium / Java
Java soll ab heute dabei sein
Java
Von Java zu VB.NET-Writing Kontrastmemo-
Java, Überlastungskonstruktor ab Anfänger
Installieren Sie Apache 2.4.46 von der Quelle unter CentOS 7
Java-Quellcode zum Lesen der Klasse java.lang.Math
Arbeiten Sie mit Google-Tabellen aus Java
Java, Schnittstelle für Anfänger
Java
Der Weg von JavaScript nach Java
Wiedereinführung von Java8, das seit Android Studio 2.4 verfügbar ist
Rufen Sie die Java-API von TensorFlow von Scala aus auf
[Java] Konvertierung von Array zu Liste
Beispielcode mit Minio aus Java
Grundstruktur des Java-Quellcodes
Generieren Sie den Quellcode aus der JAR-Datei mit der JD-GUI des Java Decompiler-Projekts
Was ist CHECKSTYLE: OFF in der Java-Quelle? Checkstyle zu wissen von
Lernen Sie Deep Learning von Grund auf in Java.
Java für Anfänger, Variablen und Typen
Bedeutung der aus der Java Collection gelernten Schnittstelle
Datenverarbeitung mit der Stream-API von Java 8
Installieren Sie samba4 aus dem Quellcode unter CentOS8
Rufen Sie die Java-Bibliothek von C mit JNI auf
API-Integration von Java mit Jersey Client
Verwenden Sie den PostgreSQL-Datentyp (jsonb) aus Java
Rufen Sie Java-Methoden aus JavaScript auf, das in Java ausgeführt wird
OCR in Java (Zeichenerkennung aus Bildern)
Abrufen von Anruferinformationen aus dem Stack-Trace (Java)
Rufen Sie Java von C ++ auf Android NDK auf