
Vom Übersetzer: GraalVM ist eine neue, interessante Technologie, aber auf Habré gibt es nicht viele Artikel, die Beispiele für Graal-Fähigkeiten zeigen könnten. Der folgende Artikel enthält nicht nur eine Auflistung der Möglichkeiten von GraalVM, sondern auch eine kleine Meisterklasse, die der von Chris Seaton und Oleg Shelaev bei Oracle CodeOne 2018 durchgeführten ähnelt. Nach dem Autor fordere ich Sie dringend auf, zu versuchen, Beispiele aus dem Artikel zu erstellen interessant.
Es gibt viele verschiedene Dinge in GraalVM , und wenn Sie diesen Namen schon einmal gehört oder sogar Berichte gesehen haben, gibt es noch viele Dinge, von denen Sie wahrscheinlich noch nichts wissen, die GraalVM jedoch tun kann. In diesem Artikel werden wir uns die verschiedenen Funktionen von GraalVM ansehen und zeigen, was Sie damit tun können.
- Java schnelle Ausführung
- Verringern Sie die Startzeit und die Speichernutzung für Java
- Kombinieren von JavaScript, Java, Ruby und R.
- Ausführung von Programmen in plattformspezifischen Sprachen
- Gemeinsame Tools für alle Programmiersprachen
- JVM Application Supplement
- Plattformabhängige Anwendungen
- Java-Code als plattformspezifische Bibliothek
- Unterstützung für mehrere Programmiersprachen in der Datenbank
- Programmiersprachen für GraalVM erstellen
Sie können alles, was in diesem Artikel gezeigt wird, mit GraalVM 1.0.0 RC1 tun, das über den Link auf der GraalVM-Website verfügbar ist . Ich habe die MacOS Enterprise Edition verwendet, aber der hier geschriebene Code funktioniert unter Linux und GraalVM Community Edition.
Führen Sie beim Lesen des Artikels die darin beschriebenen Programme aus! Der Code kann von GitHub heruntergeladen werden.
Installation
Nach dem Herunterladen von http://graalvm.org/downloads habe ich den Pfad zu den ausführbaren Dateien von GraalVM in $PATH
hinzugefügt. Standardmäßig wird die Ausführung von Java und JavaScript unterstützt.
$ git clone https://github.com/chrisseaton/graalvm-ten-things.git $ cd foo $ tar -zxf graalvm-ee-1.0.0-rc1-macos-amd64.tar.gz # or graalvm-ee-1.0.0-rc1-linux-amd64.tar.gz on Linux $ export PATH=graalvm-1.0.0-rc1/Contents/Home/bin:$PATH # or PATH=graalvm-1.0.0-rc1/bin:$PATH on Linux
GraalVM verfügt über eine integrierte JavaScript-Unterstützung und enthält einen Paketmanager namens gu
, mit dem die Unterstützung für andere Sprachen als Java und JavaScript installiert werden kann. Ich habe zusätzlich Ruby, Python und R installiert, sie werden von GitHub heruntergeladen.
$ gu install -c org.graalvm.ruby $ gu install -c org.graalvm.python $ gu install -c org.graalvm.R
Wenn Sie nun den Befehl java
oder js
ausführen, werden GraalVM-Versionen dieser Engines angezeigt.
$ java -version java version "1.8.0_161" Java(TM) SE Runtime Environment (build 1.8.0_161-b12) GraalVM 1.0.0-rc1 (build 25.71-b01-internal-jvmci-0.42, mixed mode) $ js --version Graal JavaScript 1.0 (GraalVM 1.0.0-rc1)
1. Schnelle Java-Ausführung
"Graal" in GraalVM ist der Name des Compilers. Er allein ist geschaffen, um alle zu regieren ! Dies bedeutet, dass dies eine Compiler-Implementierung ist, die in Form einer Bibliothek geschrieben wurde, die für viele verschiedene Dinge verwendet werden kann. Zum Beispiel verwenden wir Graal, um sowohl vorab als auch just-in-time zu kompilieren, um Code zu kompilieren, der in verschiedenen Programmiersprachen geschrieben wurde, auch für verschiedene Prozessorarchitekturen.
Die erste und einfachste Möglichkeit, Graal zu verwenden, besteht darin, es als Java JIT-Compiler zu verwenden.
Als Beispiel verwenden wir ein Programm, das 10 der häufigsten Wörter in einem Dokument erzeugt. Das Programm nutzt die Funktionen der modernen Java-Sprache wie Streams und Sammlungen.
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class TopTen { public static void main(String[] args) { Arrays.stream(args) .flatMap(TopTen::fileLines) .flatMap(line -> Arrays.stream(line.split("\\b"))) .map(word -> word.replaceAll("[^a-zA-Z]", "")) .filter(word -> word.length() > 0) .map(word -> word.toLowerCase()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet().stream() .sorted((a, b) -> -a.getValue().compareTo(b.getValue())) .limit(10) .forEach(e -> System.out.format("%s = %d%n", e.getKey(), e.getValue())); } private static Stream<String> fileLines(String path) { try { return Files.lines(Paths.get(path)); } catch (IOException e) { throw new RuntimeException(e); } } }
GraalVM enthält den javac
Compiler, aber es gibt keinen Unterschied für diese Demo, ob sie oder der Standard-Compiler verwendet werden soll. Daher können Sie den Standard- javac
Compiler verwenden, wenn Sie möchten.
$ javac TopTen.java
Wenn wir den java
Befehl ausführen, der in GraalVM enthalten ist, wird der Grait JIT-Compiler automatisch verwendet - es sind keine zusätzlichen Schritte erforderlich. Ich werde den Befehl time
verwenden, um echte Daten über die Zeit zu erhalten, die für die Ausführung des Programms von Anfang bis Ende aufgewendet wurde, anstatt ein komplexes Mikrobenchmark bereitzustellen. Es wird auch eine große Menge an Eingaben verwendet, damit hier oder da keine Andeutungen über die gespeicherten paar Sekunden gemacht werden. Die Größe der Datei large.txt
beträgt 150 MB.
$ make large.txt $ time java TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m17.367s user 0m32.355s sys 0m1.456s
Graal ist in Java geschrieben, nicht in C ++, wie die meisten anderen JIT-Compiler für Java. Wir glauben, dass dies uns ermöglicht, es schneller als vorhandene Compiler zu verbessern und neue leistungsstarke Optimierungen (wie zum Beispiel die partielle Escape-Analyse) hinzuzufügen, die im Standard-JIT-Compiler für HotSpot nicht verfügbar sind.
Und dies kann Ihre Java-Programme viel schneller machen.
Zu Vergleichszwecken verwende ich zum Ausführen von Programmen ohne den Grait JIT-Compiler das -XX:-UseJVMCICompiler
. JVMCI ist die Schnittstelle zwischen Graal und der JVM. Sie können das Beispiel auch auf einer Standard-JVM ausführen und die Ergebnisse vergleichen.
$ time java -XX:-UseJVMCICompiler TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m23.511s user 0m24.293s sys 0m0.579s
Dieser Test zeigt, dass Graal unser Java-Programm in etwa drei Viertel der Zeit ausführt, die für die Ausführung mit dem Standard-HotSpot-Compiler erforderlich ist. Wo wir glauben, dass die Verbesserung der Produktivität um Prozenteinheiten eine bedeutende Leistung ist, sind 25% eine große Sache.
Twitter ist heute das einzige Unternehmen, das Graal auf "Battle" -Servern einsetzt , und sie sagen, dass dies für sie gerechtfertigt ist, um echtes Geld zu sparen. Twitter verwendet Graal, um in Scala geschriebene Anwendungen auszuführen - Graal arbeitet auf der JVM-Ebene des Bytecodes, d. H. gilt für jede JVM-Sprache.
Dies ist der erste Anwendungsfall für GraalVM. Ersetzen Sie einfach den JIT-Compiler durch eine bessere Version für Ihre vorhandenen Java-Anwendungen.
2. Verringern Sie die Startzeit und die Speichernutzung für Java
Die Stärken der Java-Plattform zeigen sich insbesondere bei der Arbeit mit lang laufenden Prozessen und Spitzenlasten. Im Gegensatz dazu leiden kurzlebige Prozesse unter langen Startzeiten und einer relativ hohen Speichernutzung.
Wenn wir beispielsweise die Anwendung aus dem vorherigen Abschnitt ausführen und ihr eine viel geringere Menge an Eingabedaten zuführen - etwa 1 KB anstelle von 150 MB -, scheint es unangemessen lange und ziemlich viel Speicher zu dauern - etwa 60 MB, um eine so kleine Datei zu verarbeiten . Wir verwenden die Option -l
, um die zusätzlich zur Ausführungszeit verwendete Speichermenge zu drucken.
$ make small.txt $ /usr/bin/time -l java TopTen small.txt # -v on Linux instead of -l sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.32 real 0.49 user 0.05 sys 59846656 maximum resident set size
GraalVM bietet uns ein Tool, das dieses Problem löst. Wir haben gesagt, dass Graal eine Compiler-Bibliothek ist und auf viele verschiedene Arten verwendet werden kann. Eine davon ist das vorzeitige Kompilieren in ein plattformabhängiges ausführbares Image, anstatt Just-in-Time zur Laufzeit zu kompilieren. Dies ähnelt der Funktionsweise eines regulären Compilers wie gcc
.
$ native-image --no-server TopTen classlist: 1,513.82 ms (cap): 2,333.95 ms setup: 3,584.09 ms (typeflow): 4,642.13 ms (objects): 3,073.58 ms (features): 156.34 ms analysis: 8,059.94 ms universe: 353.02 ms (parse): 1,277.02 ms (inline): 1,412.08 ms (compile): 10,337.76 ms compile: 13,776.23 ms image: 2,526.63 ms write: 1,525.03 ms [total]: 31,439.47 ms
Dieser Befehl erstellt eine plattformspezifische topten
namens topten
. Diese Datei startet die JVM nicht, ist nicht mit der JVM verknüpft und enthält in keiner Weise die JVM. Der Befehl native-image
kompiliert Ihren Java-Code und die von Ihnen verwendeten Java-Bibliotheken wirklich zu vollständigem Maschinencode. Für Laufzeitkomponenten wie den Garbage Collector starten wir unsere eigene neue VM namens SubstrateVM, die wie Graal auch in Java geschrieben ist.
Wenn Sie sich die Abhängigkeiten topten
, die topten
verwendet, werden Sie topten
, dass dies nur Standardsystembibliotheken sind. Wir können nur diese eine Datei auf ein System übertragen, auf dem die JVM noch nie installiert wurde, und sie dort ausführen, um zu überprüfen, ob die JVM oder andere Dateien nicht verwendet werden. Topten
auch ziemlich klein - der ausführbare Code nimmt weniger als 6 MB ein.
$ otool -L topten # ldd topten on Linux topten: .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h topten 5.7M topten
Wenn wir diese ausführbare Datei ausführen, werden wir feststellen, dass sie etwa eine Größenordnung schneller startet und etwa eine Größenordnung weniger Speicher benötigt als dasselbe Programm, das unter der JVM ausgeführt wird. Der Start ist so schnell, dass Sie nicht bemerken, wie lange es gedauert hat. Wenn Sie die Befehlszeile verwenden, spüren Sie nicht die Pause, die normalerweise auftritt, wenn Sie ein kleines, kurzlebiges Programm unter der JVM ausführen
$ /usr/bin/time -l ./topten small.txt sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.02 real 0.00 user 0.00 sys 4702208 maximum resident set size
Das native-image
Dienstprogramm weist einige Einschränkungen auf . Zum Zeitpunkt der Kompilierung sollten also alle Klassen vorhanden sein. Außerdem gibt es Einschränkungen für die Verwendung der Reflection-API. Es gibt jedoch einige zusätzliche Vorteile gegenüber der grundlegenden Kompilierung, z. B. die Ausführung statischer Initialisierer zur Kompilierungszeit. Dadurch wird der Arbeitsaufwand bei jedem Herunterladen der Anwendung verringert.
Dies ist die zweite Anwendung von GraalVM - die Verteilung und Ausführung vorhandener Java-Programme mit schnellem Start und geringerem Speicherverbrauch. Diese Methode behebt Konfigurationsprobleme wie das Finden des richtigen JAR zur Laufzeit und ermöglicht das Erstellen kleinerer Docker-Images.
3. Kombinieren von JavaScript, Java, Ruby und R.
Neben Java enthält GraalVM neue Implementierungen von JavaScript-, Ruby-, R- und Python-Engines. Sie werden mit einem neuen Framework namens Truffle geschrieben . Dieses Framework ermöglicht es, Sprachinterpreter zu erstellen, die sowohl einfach als auch leistungsstark sind. Wenn Sie einen Sprachinterpreter mit Truffle schreiben, wird Graal automatisch verwendet, um die JIT-Kompilierung für Ihre Sprache bereitzustellen. Somit ist Graal nicht nur ein JIT-Compiler und AOT-Compiler für Java, sondern kann auch ein JIT-Compiler für JavaScript, Ruby, R und Python sein.
Die Unterstützung von Sprachen von Drittanbietern in GraalVM soll ein transparenter Ersatz für vorhandene Engines für die Ausführung verschiedener Sprachen sein. Zum Beispiel können wir das "Farb" -Modul für Node.js installieren:
$ npm install --global color ... + color@3.0.0 added 6 packages in 14.156s
Schreiben Sie dann mit diesem Modul ein Programm, um RGB-HTML-Farben in HSL zu konvertieren:
var Color = require('color'); process.argv.slice(2).forEach(function (val) { print(Color(val).hsl().string()); });
Und führen Sie es wie gewohnt aus:
$ node color.js '#42aaf4' hsl(204.89999999999998, 89%, 60.8%)
Die Ausführungs-Engines verschiedener Sprachen in GraalVM arbeiten zusammen. Es gibt eine API, mit der Sie Code aus einer Sprache in einem Programm ausführen können, das in einer anderen Sprache geschrieben ist. Auf diese Weise können Sie mehrsprachige Programme schreiben - Programme, die in mehr als einer Programmiersprache geschrieben sind.
Dies kann erforderlich sein, wenn Sie den größten Teil Ihres Programms in einer Sprache schreiben, aber eine Bibliothek verwenden möchten, die in einer anderen Programmiersprache geschrieben ist. Angenommen, wir müssen eine Anwendung schreiben, um einen Farbnamen von CSS in seine numerische Darstellung in Node.js zu konvertieren. Wir möchten jedoch eine Ruby-Farbbibliothek verwenden, anstatt die Konvertierung selbst zu schreiben.
var express = require('express'); var app = express(); color_rgb = Polyglot.eval('ruby', ` require 'color' Color::RGB `); app.get('/css/:name', function (req, res) { color = color_rgb.by_name(req.params.name).html() res.send('<h1 style="color: ' + color + '" >' + color + '</h1>'); }); app.listen(8080, function () { console.log('serving at http://localhost:8080') });
In diesem Code haben wir geschrieben, dass wir Ruby-Code als Zeichenfolge ausführen müssen, aber beachten Sie, dass wir hier nicht viel getan haben - wir haben nur die Bibliotheken verbunden und dann das Ruby-Objekt zurückgegeben. In Ruby würden wir es folgendermaßen verwenden: Color::RGB.by_name (name).html
. Wenn Sie sich ansehen, wie color_rgb
später in JavaScript verwendet wird, werden Sie color_rgb
, dass wir tatsächlich dieselben Methoden aus JavaScript aufrufen, obwohl dies Ruby-Objekte und -Methoden sind. Wir übergeben sie als JavaScript-Zeichenfolgen und kombinieren das Ergebnis, bei dem es sich um eine Ruby-Zeichenfolge handelt, mit einer JavaScript-Zeichenfolge.
Installieren Sie beide Abhängigkeiten - Ruby und JavaScript.
$ gem install color Fetching: color-1.8.gem (100%) Successfully installed color-1.8 1 gem installed $ npm install express + express@4.16.2 updated 1 package in 10.393s
Dann müssen Sie den node
mit einigen zusätzlichen Optionen --polyglot
: --polyglot
, um zu sagen, dass wir Zugriff auf andere Sprachen und --jvm
, da das ausführbare node
standardmäßig nichts anderes als JavaScript enthält.
$ node --polyglot --jvm color-server.js serving at http://localhost:8080
Gehen Sie dann wie gewohnt in Ihrem Browser zur URL http: // localhost: 8080 / css / orange (oder einer anderen Farbe).

Lassen Sie uns versuchen, ein ernsthafteres Beispiel zu erstellen, das mehr Sprachen und Module verwendet.
JavaScript unterstützt keine sehr großen Ganzzahlen. Ich habe mehrere Module wie Big-Integer gefunden , aber sie sind alle ineffizient, weil Speichern Sie die Komponenten einer Zahl als JavaScript-Gleitkommazahlen. Die BigInteger
Klasse in Java ist effizienter. Verwenden Sie sie, um einige arithmetische Operationen mit großen Ganzzahlen auszuführen.
JavaScript bietet auch keine integrierte Unterstützung für das Zeichnen von Diagrammen, während R Diagramme hervorragend zeichnet. Verwenden wir das svg
Modul von R, um ein Streudiagramm einer trigonometrischen Funktion im 3D-Raum zu zeichnen.
In beiden Fällen verwenden wir die API, um die Mehrsprachigkeit von GraalVM (im Folgenden als Polyglot-API bezeichnet) zu unterstützen, und können die Ergebnisse der Ausführung von Programmen in anderen Sprachen einfach in JavaScript einfügen.
const express = require('express') const app = express() const BigInteger = Java.type('java.math.BigInteger') app.get('/', function (req, res) { var text = 'Hello World from Graal.js!<br> '
Öffnen Sie http: // localhost: 3000 / in Ihrem Browser, um das Ergebnis anzuzeigen:

Dies ist das dritte, was wir mit GraalVM tun können - Programme ausführen, die in mehreren Sprachen geschrieben sind, und Module aus diesen Sprachen zusammen in einem Programm verwenden. Wir präsentieren dies als eine Möglichkeit, Laufzeitumgebungen und Bibliotheken zu vereinheitlichen. Sie können die Programmiersprache verwenden, die Ihrer Meinung nach am besten zur Lösung der aktuellen Aufgabe und jeder gewünschten Bibliothek geeignet ist, unabhängig davon, in welcher Programmiersprache sie geschrieben ist.
Eine andere Sprache, die GraalVM unterstützt, ist C. GraalVM kann C-Code auf dieselbe Weise ausführen wie in JavaScript und Ruby geschriebene Programme.
Was GraalVM tatsächlich unterstützt, ist die Ausführung des Codes, der sich aus der Ausführung der LLVM-Dienstprogramme ergibt, d. H. Bitcode, keine direkte Unterstützung für C. Dies bedeutet, dass Sie die vorhandenen Tools für die C-Sprache und andere, die LLVM unterstützen, wie C ++, Fortran und möglicherweise in Zukunft weitere Sprachen verwenden können. Zur Vereinfachung der Demonstration führe ich eine spezielle Version von gzip aus , die in einer einzigen Datei zusammengestellt ist ( Stephen McCamant unterstützt diese Version). Dies ist lediglich ein gzip
Quellcode und eine autoconf
Konfiguration, die der Einfachheit halber in einer Datei zusammengefasst sind. Ich musste ein paar Dinge patchen, damit es unter macOS und mit clang funktioniert, aber ich habe nichts spezielles getan, um GraalVM zu unterstützen.
Wir kompilieren gzip mit dem Standard- clang
(LLVM-Compiler für C) und möchten, dass es uns zu einem LLVM-Bitcode und nicht zu einem plattformspezifischen Build macht, da GraalVM ihn nicht startet. Ich benutze clang
4.0.1.
$ clang -c -emit-llvm gzip.c
Führen Sie dann das Ergebnis direkt mit dem Befehl lli (LLVM-Bitcode-Interpreter) von GraalVM aus. Versuchen wir, die Datei mit meinem gzip-Systemarchivator zu komprimieren und sie dann mit gzip zu entpacken, das unter GraalVM ausgeführt wird.
$ cat small.txt Lorem ipsum dolor sit amet... $ gzip small.txt $ lli gzip.bc -d small.txt.gz $ cat small.txt Lorem ipsum dolor sit amet...
Die Ruby- und Python-Implementierungen in GraalVM verwenden dieselbe Technik, um in C geschriebene Erweiterungen für diese Sprachen auszuführen. Dies bedeutet, dass Sie diese Erweiterungen innerhalb der VM ausführen können. Dadurch können wir eine hohe Ausführungsgeschwindigkeit beibehalten, selbst wenn wir veraltete plattformspezifische Erweiterungsschnittstellen verwenden.
Dies ist die vierte Möglichkeit, GraalVM zu verwenden - Programme auszuführen, die in plattformspezifischen Sprachen wie C oder C ++ geschrieben sind, sowie Erweiterungen für Sprachen wie Python oder Ruby zu starten, die keine JVM-Implementierungen dieser Sprachen wie JRuby durchführen können.
5. Allgemeine Tools für alle Programmiersprachen
Wenn Sie in Java programmieren, verwenden Sie wahrscheinlich sehr hochwertige Tools wie IDEs, Debugger und Profiler. Nicht alle Sprachen verfügen über dieses Toolkit. Sie können jedoch eines erwerben, wenn Sie Sprachen verwenden, die von GraalVM unterstützt werden.
Die Unterstützung für alle Sprachen in GraalVM (derzeit außer Java) wird mithilfe eines gemeinsamen Frameworks implementiert - Truffle. Auf diese Weise können wir die Funktionalität, beispielsweise einen Debugger, einmal erstellen und für alle Sprachen verwenden.
Um dies zu versuchen, werden wir das einfachste Programm schreiben - FizzBuzz , da es visuell ist (es druckt etwas auf dem Bildschirm) und klare Zweige hat, die nur in einigen Iterationen verwendet werden. Somit ist es für uns einfacher, Haltepunkte zu setzen. Beginnen wir mit einer JavaScript-Implementierung.
function fizzbuzz(n) { if ((n % 3 == 0) && (n % 5 == 0)) { return 'FizzBuzz'; } else if (n % 3 == 0) { return 'Fizz'; } else if (n % 5 == 0) { return 'Buzz'; } else { return n; } } for (var n = 1; n <= 20; n++) { print(fizzbuzz(n)); }
Wir starten das Programm wie gewohnt mit dem Dienstprogramm js unter GraalVM.
$ js fizzbuzz.js 1 2 Fizz 4 Buzz Fizz
Wir können das Programm auch mit dem Flag --inspect
. Dadurch erhalten wir einen Link, den Sie in Chrome öffnen und das Programm im Debugger stoppen können.
$ js --inspect fizzbuzz.js Debugger listening on port 9229. To start debugging, open the following URL in Chrome: chrome-devtools://devtools/bundled/inspector.html?ws=127.0.0.1:9229/6c478d4e-1350b196b409
Sie können einen Haltepunkt im FizzBuzz- Code festlegen und dann die Ausführung fortsetzen. Wenn das Programm die Ausführung unterbricht, wird der Wert der Variablen n
im Debugger angezeigt, und wir können die Programmausführung fortsetzen oder die Debugger-Schnittstelle untersuchen.

Der Debugger in Chrome wird normalerweise für JavaScript verwendet, aber für GraalVM in JavaScript unterscheidet sich nichts von anderen Sprachen. Das Flag --inspect
ebenfalls verfügbar und funktioniert in den Python-, Ruby- und R-Implementierungen. Ich zeige Ihnen nicht die Quelle jedes Programms, aber sie werden auf dieselbe Weise ausgeführt, und Sie erhalten für jede Version denselben Debugger in Chrome.
$ graalpython --jvm --inspect fizzbuzz.py

$ ruby --inspect fizzbuzz.rb

$ Rscript --inspect fizzbuzz.r

Ein weiteres Tool, mit dem Sie möglicherweise aus Java vertraut sind, ist VisualVM. Es bietet eine Benutzeroberfläche, über die Sie einer laufenden JVM auf Ihrem lokalen Computer oder über ein Netzwerk beitreten können, um verschiedene Aspekte der Programmausführung zu überprüfen, z. B. die Speichernutzung oder die Thread-Ausführung.
GraalVM enthält VisualVM als Standarddienstprogramm für jvisualvm
.
$ jvisualvm &> /dev/null &
Wenn wir VisualVM ausführen, während das TopTen
Java-Programm ausgeführt wird, können wir die Speichernutzung beobachten oder beispielsweise eine Momentaufnahme des Speicherinhalts erstellen und sehen, welche Arten von Objekten wir auf dem Heap verwenden.
$ java TopTen large.txt

Ich habe dieses Programm in Ruby geschrieben, um zur Laufzeit Müll im Speicher zu generieren.
require 'erb' x = 42 template = ERB.new <<-EOF The value of x is: <%= x %> EOF loop do puts template.result(binding) end
Wenn Sie die Standard-Ruby-Implementierung auf JVM - JRuby ausführen, werden Sie von VisualVM enttäuscht sein, da anstelle von Objekten in Ihrer Sprache nur interne Java-Objekte angezeigt werden.
Wenn Sie die Version von Ruby für GraalVM verwenden, erkennt VisualVM Ruby-Objekte. Wir müssen die Option --jvm
, um VisualVM als zu verwenden native Versionen von Ruby werden nicht unterstützt.
$ ruby --jvm render.rb
, , Java , , , Summary, Ruby Heap Ruby .

Truffle — - Nexus . Truffle , , API Truffle' , , Truffle, .
, GraalVM — , . Truffle GraalVM , VisualVM.
6. JVM
, , , Java . API org.graalvm.polyglot
, .
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; public class ExtendJava { public static void main(String[] args) { String language = "js"; try (Context context = Context.newBuilder().allowNativeAccess(true).build()) { for (String arg: args) { if (arg.startsWith("-")) { language = arg.substring(1); } else { Value v = context.eval(language, arg); System.out.println(v); } } } } }
javac
java
GraalVM, org.graalvm.*
classpath
, .. .
$ javac ExtendJava.java $ java ExtendJava '14 + 2' 16 $ java ExtendJava -js 'Math.sqrt(14)' 3.7416573867739413 $ java ExtendJava -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128] $ java ExtendJava -ruby '[4, 2, 3].sort' [2, 3, 4]
, — , node
ruby
, GraalVM.
GraalVM — Java . Polyglot API “” Java , .
GraalVM , , — , , GraalVM, - . , JavaScript , V8, Python — CPython , .. . GraalVM — Polyglot .
GraalVM, , JavaScript. Polyglot , , :
$ graalvm-1.0.0-rc1/Contents/Home/jre/lib/svm/bin/rebuild-images libpolyglot
C, , , GraalVM, . ExtendJava
, , .
#include <stdlib.h> #include <stdio.h> #include <polyglot_api.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } poly_context context = NULL; if (poly_create_context(thread, NULL, 0, &context) != poly_ok) { fprintf(stderr, "initialization error\n"); return 1; } char* language = "js"; for (int n = 1; n < argc; n++) { if (argv[n][0] == '-') { language = &argv[n][1]; } else { poly_value result = NULL; if (poly_context_eval(thread, context, language, "unicalc", argv[n], &result) != poly_ok) { fprintf(stderr, "eval error\n"); return 1; } char buffer[1024]; size_t length; if (poly_value_to_string_utf8(thread, result, buffer, sizeof(buffer), &length) != poly_ok) { fprintf(stderr, "to string error\n"); return 1; } buffer[length] = '\0'; printf("%s\n", buffer); poly_destroy_handle(thread, result); } } return 0; }
, polyglot GraalVM. , , JVM.
$ clang -Igraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -rpath graalvm-1.0.0-rc1/Contents/Home / -Lgraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -lpolyglot extendc.c -o extendc $ otool -L extendc extendc: .../libpolyglot.dylib ... .../libSystem.B.dylib ...
$ ./extendc '14 + 2' 16 $ ./extendc -js 'Math.sqrt(14)' 3.7416573867739413 $ ./extendc -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128]
, GraalVM — - , , GraalVM.
Java , , , , - , . Java - , JVM , .
GraalVM Java , , - , . , , Java JVM.
, Apache SIS , ( ) . SIS 0.8, http://sis.apache.org/ jar.
import org.apache.sis.distance.DistanceUtils; public class Distance { public static void main(String[] args) { final double aLat = Double.parseDouble(args[0]); final double aLong = Double.parseDouble(args[1]); final double bLat = Double.parseDouble(args[2]); final double bLong = Double.parseDouble(args[3]); System.out.printf("%.2f km%n", DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong)); } public static double distance(IsolateThread thread, double aLat, double aLong, double bLat, double bLong) { return DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong); } }
, -
$ javac -cp sis.jar -parameters Distance.java $ java -cp sis.jar:. Distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
, topten
.
$ native-image --no-server -cp sis.jar:. Distance ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
, . , @CEntryPoint
... import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.CEntryPoint; public class Distance { ... @CEntryPoint(name = "distance") public static double distance(IsolateThread thread, double a_lat, double a_long, double b_lat, double b_long) { return DistanceUtils.getHaversineDistance(a_lat, a_long, b_lat, b_long); } ... }
javac
, GraalVM API classpath
. C .
$ native-image --no-server -cp sis.jar:. -H:Kind=SHARED_LIBRARY \ -H:Name=libdistance $ otool -L libdistance.dylib # .so on Linux libdistance.dylib: .../libdistance.dylib ... .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h libdistance.dylib 4.8M libdistance.dylib
, . , : VM , , .
#include <stdlib.h> #include <stdio.h> #include <libdistance.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } double a_lat = strtod(argv[1], NULL); double a_long = strtod(argv[2], NULL); double b_lat = strtod(argv[3], NULL); double b_long = strtod(argv[4], NULL); printf("%.2f km\n", distance(thread, a_lat, a_long, b_lat, b_long)); return 0; }
, ( LD_LIBRARY_PARTH=.
Linux)
$ clang -I. -L. -ldistance distance.c -o distance $ otool -L distance distance: .../libdistance.dylib ... .../libSystem.B.dylib ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
GraalVM — java - , JVM
9.
Polyglot — Oracle. Oracle Database Multilingual Engine (MLE), GraalVM SQL.
, front-end, JavaScript email , JavaScript validator
. - , SQL PL/SQL. , .
MLE Docker :
https://oracle.imtqy.com/oracle-db-mle/releases/0.2.7/docker/
Docker Daemon.
$ docker load --input mle-docker-0.2.7.tar.gz
, Docker, , ( ), Bash .
$ docker run mle-docker-0.2.7 $ docker ps $ docker exec -ti <container_id> bash -li
sqlplus
( SQL ), Bash, , , .
$ sqlplus scott/tiger@localhost:1521/ORCLCDB
, sqlplus
. , Bash Docker, dbjs
, . sqlplus
.
$ npm install validator $ npm install @types/validator $ dbjs deploy -u scott -p tiger -c localhost:1521/ORCLCDB validator $ sqlplus scott/tiger@localhost:1521/ORCLCDB
validator
SQL .
SQL> select validator.isEmail('hello.world@oracle.com') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD@ORACLE.COM') ------------------------------------------- 1 SQL> select validator.isEmail('hello.world') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD') -------------------------------- 0
, GraalVM — , GraalVM, Oracle. , front-end back-end, , , .
10. GraalVM
Oracle Labs JavaScript, R, Ruby, Python C , Truffle, GraalVM.
Truffle — java , (AST). AST — , , , , , . , , Truffle Graal JIT , AST .
Truffle, GraalVM , , DSL. Truffle Graal , , Truffle — GraalVM. , , , , . , , . Oracle labs Ruby , , .
, , , SimpleLanguage — Truffle, JavaScript. , , , , , if .
, Truffle Oracle Labs, SmallTalk , Newspeak Lisp . Lisp , .
Fazit
GraalVM — , , . , , , , .
GraalVM, http://www.graalvm.org/ . , , .
, , . , GraalVM @ChrisGSeaton @shelajev .
: Oleg Šelajev , Olya Gupalo Doug Simon