Programmering

Nashorn: JavaScript er fantastisk i Java 8

Nashorn, udtalt som "nass-horn", er tysk for "næsehorn", og det er et af dyrenavnene på en tysk tankskytten, der blev brugt i 2. verdenskrig. Det er også navnet på erstatningen - introduceret med Java 8 - til den gamle, langsomme Rhino JavaScript-motor. Både Rhino og Nashorn er implementeringer af JavaScript-sproget, der er skrevet til at køre på den virtuelle Java-maskine eller JVM.

Obligatorisk rant: JavaScript kan have Java som en del af navnet, men de to sprog er meget forskellige i ånd og design såvel som i deres implementeringer. Ikke desto mindre er en måde at implementere en JavaScript-tolk på at kompilere JavaScript i Java-byte-koder, hvilket Rhino og Nashorn var designet til at gøre.

Du tænker sandsynligvis på JavaScript i form af scripting-browsere, og du vil for det meste have ret. Det bruges også til servere. For eksempel bruges Node.js til at opbygge hurtige, lette servere baseret på V8 JavaScript-motoren fra Google Chrome. JavaScript-motorer i webbrowsere har adgang til HTML-dokumentobjektmodellen (DOM) og kan manipulere HTML-elementer gennem DOM. Da forskellige webbrowsere har forskellige DOM'er og JavaScript-motorer, forsøger rammer som jQuery at skjule implementeringsoplysningerne fra programmøren.

Nashorn og Rhino før det understøtter eksplicit ikke browseren DOM. Implementeret på JVM kaldes de typisk til slutbruger-scripting i Java-applikationer. Nashorn og Rhino kan integreres i Java-programmer og bruges som kommandolinjeskaller. Selvfølgelig er den ekstra magi, der er nødvendig, når du scripter Java fra JavaScript, at bygge bro over data og skrive uoverensstemmelser mellem de to sprog.

Problemer med næsehorn

Rhinoudvikling startede i Netscape i 1997 for et ulykkeligt "Javagator" -projekt og blev frigivet til Mozilla.org i 1998. Det blev derefter licenseret til Sun og andre. Ærligt talt kan 1998 lige så godt være jura-perioden, som Internetudvikling går - 16 år senere har Rhino tydeligt vist sin alder. Ifølge Jim Laskey fra Oracle, hovedudvikleren af ​​Nashorn:

Jeg er sikker på, at alt dette er sandt, men som en trængt udvikler og udviklingschef finder jeg den sidste sætning meget morsom. Når alt kommer til alt er store omskrivninger aldrig sjove. Det er altid sjovt at starte fra bunden.

Mål for Nashorn

Laskey beskrev sine mål for Nashorn som følger:

  • Nashorn vil være baseret på ECMAScript-262 Edition 5.1 sprogspecifikation og skal bestå ECMAScript-262 compliance test.
  • Nashorn vil støtte javax.script (JSR 223) API.
  • Support ydes til påberåbelse af Java-kode fra JavaScript og for Java til at påberåbe JavaScript-kode. Dette inkluderer direkte kortlægning til JavaBeans.
  • Nashorn vil definere et nyt kommandolinjeværktøj, jjs, til evaluering af JavaScript-kode i "shebang" -skripter, her dokumenter og redigere strenge.
  • Ydelse og hukommelsesforbrug af Nashorn-applikationer skal være betydeligt bedre end Rhino.
  • Nashorn vil ikke udsætte yderligere sikkerhedsrisici.
  • Medfølgende biblioteker skal fungere korrekt under lokalisering.
  • Fejlmeddelelser og dokumentation vil blive internationaliseret.

Laskey begrænsede også eksplicit projektets omfang med nogle "ikke-mål":

  • Nashorn understøtter kun ECMAScript-262 Edition 5.1. Det understøtter ikke nogen funktioner i Edition 6 eller andre ikke-standardfunktioner, der leveres af andre JavaScript-implementeringer.
  • Nashorn inkluderer ikke en browser-plug-in API.
  • Nashorn inkluderer ikke understøttelse af DOM / CSS eller nogen relaterede biblioteker (såsom jQuery, Prototype eller Dojo).
  • Nashorn inkluderer ikke support til direkte fejlretning.

Så hvad betyder det at være baseret på ECMAScript-262 Edition 5.1? Forskellen her er, at Rhino var baseret på den ældre, mindre kapable udgave 3. javax.script (JSR 223) API er til at ringe tilbage til JavaScript fra Java.

Manglen på debugging-understøttelse i Nashorn er et skridt tilbage fra Rhino, som har sin egen JavaScript-debugger. Du finder dog løsninger på denne bevidste udeladelse i mindst to populære IDE'er.

Nashorn kommandolinjeværktøjer: Installation af jjs og jrunscript

Efter at have læst om Nashorns kommandolinjeværktøj, jjs, Jeg var ivrig efter at prøve skallen på min iMac, men efter installation af Java 8 var den ikke tilgængelig for bash-skallen. Det viser sig, at dokumentationen og implementeringen ikke var helt synkroniseret.

Jeg vidste, at installationen havde været vellykket:

 > java -version java version "1.8.0" Java (TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot (TM) 64-Bit Server VM (build 25.0-b70, mixed mode) 

men kører jjs vendt tilbage -bash: jjs: kommandoen blev ikke fundet. En lille pik rundt bragte mig til / usr / bin / vejviser:

 > hvilken java / usr / bin / java 

Der fandt jeg noget kaldet jrunscript, som viste sig at være en variant af jjs der kører et ekstra opstarts script. Det skulle have tilfredsstillet mig, men jeg var forvirret over, hvorfor det blev dokumenteret jjs værktøj blev ikke installeret i / usr / bin / med resten af ​​Java 8 runtime. En lille undersøgelse fik mig til at se på JavaVirtualMachines installation til Java 8. På en Mac skal du kigge efter jjs i /Bibliotek/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/ eller /Bibliotek/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/bin/.

Du kan definere et alias for jjs i sidstnævnte bibliotek og tilføj det til din shell-konfiguration, hvis du har brug for det til scripting på en Mac eller Linux. På en pc kan du tilføje det rigtige jre / bin / bibliotek til din STI. I sin video fra lanceringen af ​​Java 8 foreslår Jim Laskey at kopiere jjs til / usr / bin / katalog, men da jeg gjorde det, fandt jeg det jjs kunne ikke finde JRE korrekt ved kørsel.

Kører JavaScript-scripts

Hvorfor de to kommandolinjeværktøjer til at køre JavaScript-scripts? Jeg er ikke helt klar over, hvad udviklingsteamet tænkte, men jjs har kapaciteter, der jrunscript ikke, og jrunscript har en initialiseringsfil. Nedenfor er et par enkle eksempler på jjs og jrunscript brug.

 $ jrunscript nashorn> alarm ("hej,"); scriptfejl: ReferenceError: "alarm" er ikke defineret i på linje nummer 1 

Dette virker ikke fordi alert() er en browser / DOM-funktion. D'oh! Jeg kunne dog have svoret, at det fungerede i næsehorn.

 nashorn> print ("Hej"); Hej, 

Dette fungerer, fordi print () er en central JavaScript-funktion.

 nashorn> var a = 1; nashorn> var b = "1"; nashorn> print (a + b); 11 nashorn> print (a + a); 2 nashorn> afslut (); $ 

Med andre ord har vi et grundlæggende REPL-miljø (read-execute-print-loop-command-line) til JavaScript her. Hvis du er overrasket over svaret på a + b, overvej dette:

 nashorn> print (typeof (a + b)); snor 

Det er en charmerende bivirkning af løs skrivning og overbelastning af "+" -operatøren i JavaScript. Det er korrekt adfærd i henhold til JavaScript-specifikationen, ikke en fejl.

Nashorn understøtter tegnet "#" som en førende linjekommentarmarkør, så jjs og jrunscript kan bruges i eksekverbare "shebang" -skripter skrevet i JavaScript. På en Mac eller Linux skal du markere JavaScript-filen som eksekverbar med chmod-værktøjet for at gøre den kørbar.

Du finder en scripting-tilstand i jjs at jrunscript synes at mangle. I scripting-tilstand sendes udtryk inden i back-flåter til den ydre skal til evaluering:

 $ jjs -scripting jjs> print ('ls'); Applikationer Applikationer (Paralleller) Creative Cloud Files Desktop ... arbejde jjs>

Scripting-tilstand muliggør også en udvidelse til "heredocs", som grundlæggende er multiline strenge i et format, der er kendt for Perl og Ruby programmerere.

Forresten fungerer piletasterne på Mac-tastaturet ikke ordentligt til linieredigering i jjs skal. Men der er et hack for det: Du kan brygge installer rlwrap og brug det som en del af dit alias til jjs i din .bashrc eller .zshrc fil.

Opkald til JavaScript fra Java

For at ringe til Nashorn JavaScript fra et Java 8-program skal du grundlæggende oprette et nyt ScriptEngineManager eksempel og brug det ScriptEngineManager at indlæse Nashorn-scriptmotoren ved navn. (Se dette Stack Overflow-spørgsmål for et detaljeret resumé af indlæsning og fejlretning af Nashorn.)

Endelig kan du sende Nashorn-motoren en fil eller en streng til evaluering:

 import javax.script.Invocable; importere javax.script.ScriptEngine; importere javax.script.ScriptEngineManager; importere javax.script.ScriptException; ... prøv {ScriptEngineManager fabrik = ny ScriptEngineManager (); ScriptEngine engine = factory.getEngineByName ("nashorn"); engine.eval ("load (\" "+" src "+" / "+" javascript_sample "+" / "+" test1.js "+" \ ");"); } fange (Undtagelse ex) {// ...} ... prøv {ScriptEngineManager fabrik = ny ScriptEngineManager (); ScriptEngine engine = factory.getEngineByName ("nashorn"); engine.eval ("funktion hi () {\ nvar a = 'PROSPER'.toLowerCase (); \ nmiddle (); \ nprint (' Live lang og '+ a)} \ n funktion midt () {\ n var b = 1; for (var i = 0, max = 5; i

Bemærk, at scripts altid kan genereres ScriptException fejl, så du skal fange dem.

Opkald til Java fra JavaScript

At ringe til Java fra Nashorn er omtrent så let som det kan være, da Java 8-klassebibliotekerne er indbygget i Nashorn:

 udskrive (java.lang.System.currentTimeMillis ()); var fil = ny java.io.File ("sample.js"); udskrive (file.getAbsolutePath ()); udskrive (file.absolutePath); 

Bemærk, at Nashorn ikke importerer java pakke som standard, fordi henvisninger til Snor eller Objekt konflikt med de tilsvarende typer i JavaScript. Derfor er en Java-streng java.lang.Streng, ikke Snor.

Nashorn og JavaFX

Hvis du påberåber dig jjs med -fx skifte, giver det dig mulighed for at bruge visuelle JavaFX-klasser i dine Nashorn-applikationer. For eksempel viser følgende eksempel fra Oracle-dokumentationen en JavaFX-knap:

 var Button = javafx.scene.control.Button; var StackPane = javafx.scene.layout.StackPane; var Scene = javafx.scene.Scene; funktionsstart (primaryStage) {primaryStage.title = "Hej verden!"; var-knap = ny knap (); button.text = "Sig 'Hello World'"; button.onAction = funktion () print ("Hello World!"); var root = ny StackPane (); root.children.add (knap); primaryStage.scene = ny scene (rod, 300, 250); primaryStage.show (); } 

Fejlretning af Nashorn

Jeg nævnte tidligere, at Nashorn ikke inkluderer en egen debugger. Heldigvis understøtter både NetBeans 8 og IntelliJ IDEA 13.1 debugging af Nashorn JavaScript. Stack Overflow-spørgsmålet, jeg nævnte tidligere, indeholder et nyttigt NetBeans 8-projekt, som du kan bruge som en prøve. Du finder ud af, at simpelthen brug af fejlretningselementet fra pop op-menuen på JavaScript-filer giver dig mulighed for at debugge Nashorn-koden.

I IntelliJ IDEA 13 kan du indstille breakpoints i Java- og Nashorn JavaScript-filer ved hjælp af den samme genvejstast (Com / Ctrl-F8). Når du rammer et JavaScript-brudpunkt, får du alle de sædvanlige fejlretningsoplysninger.

Nashorn blev designet til at være en bedre, hurtigere erstatning for den gamle Rhino-motor, og efter de fleste mål lykkes det. Det har nogle mindre vorter, som jeg håber vil blive rettet i fremtidige opdateringer, men indtil videre er der rimelige hacks, der giver dig mulighed for at bruge Nashorn effektivt i dine projekter.