Date post: | 14-Apr-2017 |
Category: |
Internet |
Upload: | dmitry-alexandrov |
View: | 196 times |
Download: | 1 times |
Java(Script) на JVM Дмитрий Александров Старший эксперт-программист в T-Systems Rus Bulgarian JUG co-lead [email protected] @bercut2000
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 1
Поговорим о JavaScript…
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 2
WAT
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 4
By Gary Bernhardt: h-p://www.youtube.com/watch?v=20BySC_6HyY
План на сегодня
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 5
Was ist JavaScript? • Разработан Бренданом Ейхом за 15 дней в далеком 1995 году
• Диалект ECMAScript (да, это не синонимы)
• Мультипарадигменный: прототипный, слаботипизированный, функциональный, императивный… скриптовый
• Ducktyped
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 6
Was ist Nashorn? • Читается как Насхорн (ˈnaːsˌhɔʁn ).. Не наШорн!
• Рантайм для ECMAScript 5.1 (6.0) на JVM
• GPL
• Часть OpenJDK
• Релиз – Март 2014
• Просто напишите jjs в консоли.. И вы в игре!
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 7
… Зачем?
Закон Атвуда: любое приложение, которое может быть написано на JavaScript, рано или поздно оно будет написано на JavaScript
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 8
Зачем: • Поддержка Oracle динамических языков
• Ныне часть JRE
• 100% поддержка ECMAScript 5.1
• Частичная поддержка ECMAScript 6
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 9
Почему не Rhino? • Весь код компилируется в bytecode. Нет интерпретации.. Даже в консоли!
• Самый большой потребитель InvokeDynamic в мире!
• JSR-223 javax.script.* единое публичное API
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 10
Часть первая..
Java -> JavaScript
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 11
Самое простое import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptExcepOon; public class EvalScript { public sta.c void main(String[] args) throws ExcepOon { // create a script engine manager ScriptEngineManager factory = new ScriptEngineManager(); // create a Nashorn script engine ScriptEngine engine = factory.getEngineByName("nashorn"); // evaluate JavaScript statement try { engine.eval("print('Hello, World!');"); } catch (final ScriptExcepOon se) { se.printStackTrace(); } } }
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 12
Чуть сложнее: Multiple invoke import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class Eval_Invocable { public sta.c void main(String[] args) throws ExcepOon { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("funcOon f(x){return x < 2 ? 1 : f(x-‐1)*x} "); engine.eval("funcOon sum(x,y){return x+y}"); Invocable i = (Invocable) engine; System.out.println(i.invokeFuncOon("f",5)); System.out.println(i.invokeFuncOon("f",10)); System.out.println(i.invokeFuncOon("sum",5,10)); System.out.println(i.invokeFuncOon("sum",10,15)); } }
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 13
Имплементируем интерфейс
public class Eval_InvocableInterface { public sta.c void main(String... args) throws ExcepOon{ ScriptEngine engine = new
ScriptEngineManager().getEngineByName("nashorn"); engine.eval("funcOon sum(x,y){return x+y}"); Invocable i = (Invocable) engine; Adder adder= i.getInterface(Adder.class); System.out.println(adder.sum(1,3)); } }
public interface Adder { int sum(int a, int b); }
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 14
Передаем переменные public class Eval_Bind { public sta.c void main(String... args) throws ExcepOon {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
Bindings b = engine.createBindings(); b.put("file", new File("/")); engine.eval("list = file.listFiles()", b); System.out.println(Arrays.toString((File[]) b.get("list"))); } }
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 15
Часть Вторая..
JavaScript -> Java
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 16
Попроще: var Omer = new java.uOl.Timer(); Omer.schedule( new java.uOl.TimerTask({ run: func.on(){ print("Tick") } }) ,0,1000) java.lang.Thread.sleep(5000) Omer.cancel();
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 17
Или даже так: var Omer2= new java.uOl.Timer(); Omer2.schedule(func.on(){print("Tack")},0,1000) java.lang.Thread.sleep(5000) Omer2.cancel();
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 18
Конструируем Java(Script) объект • var linkedList = new java.uOl.LinkedList()
• var LinkedList = java.uOl.LinkedList var list = new LinkedList()
• var LinkedList = Java.type(“java.uOl.LinkedList”) var list = new LinkedList()
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 19
Типы var ints = new (Java.type(“int[]”))(6) ints[0]=1 ints[1]=1.6 ints[2]=null ints[3]=“45” ints[4]=“str” Ints[5]=undefined print(ints) print(java.uOl.Arrays.toString(ints)) На выходе будет: [I@43re2sd [1, 1, 0, 45, 0, 0]
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 20
Типы 2 Var dbls = new (Java.type(“double[]”))(6) dbls [0]=1 dbls [1]=1.6 dbls [2]=null dbls [3]=“45” dbls [4]=“str” dbls [5]=undefined print(dbls ) print(java.uOl.Arrays.toString(dbls )) Output will be: [D@43re2sd [1.0, 1.6, 0.0, 45.0, NaN, NaN]
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 21
Конвертирование типов • Сначала пытается конвертировать JavaScript методами, и далее Java методами
• Все JS native объекты имплементируют java.util.Map
• .. И они НЕ имплементируют java.util.List
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 22
И еще о конвертировании
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 23
Представим себе: sta.c void about(Object object) { System.out.println(object.getClass()); }
И еще о конвертировании MyJavaClass.about(123); // class java.lang.Integer MyJavaClass.about(49.99); // class java.lang.Double MyJavaClass.about(true); // class java.lang.Boolean MyJavaClass.about("hi there") // class java.lang.String
MyJavaClass.about(new Number(23)); // class jdk.nashorn.internal.objects.Na.veNumber MyJavaClass.about(new Date()); // class jdk.nashorn.internal.objects.Na.veDate MyJavaClass.about(new RegExp()); // class jdk.nashorn.internal.objects.Na.veRegExp MyJavaClass.about({foo: 'bar'}); // class jdk.nashorn.internal.scripts.JO4
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 24
Конвертирование массивов • Сами не конвертируются!
• Существует специализированные методы: – var javaArray = Java.toJavaArray( jsArray,type) – var jsArray = Java.toJavaScriptArray( javaArray)
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 25
Доступ static var ps = java.io.File.pathSeparator print(ps) var File = Java.type("java.io.File") var p = File.separator print(p) var MapEntry = java.uOl.AbstractMap.SimpleEntry print(MapEntry) var m = new MapEntry(1,"b"); print(m)
На выходе: : / [JavaClass java.uOl.AbstractMap$SimpleEntry] 1=b
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 26
Кстати, а ведь это Java 8!
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 27
Кстати, а ведь это Java 8!
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 28
… так вот JavaScript: var stack = new java.uOl.LinkedList(); [1, 2, 3, 4,54,87,42,32,65,4,5,8,43].forEach(func.on(item) { stack.push(item); }); print(stack.getClass()); var sorted = stack .stream() .filter(func.on(i){return i%2==0}) .sorted() .toArray(); print(java.uOl.Arrays.toString(sorted)); На выходе: [Ljava.lang.Object;@6591f517 [2, 4, 4, 8, 32, 42, 54]
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 29
.. и Default методы Java: public interface DefTest { default void sayHello(String name){ System.out.println("Hello "+name); } } public class DefTestImpl implements DefTest { //nothing here } JavaScript: >jjs -‐cp . jjs> var DT = Java.type("DefTestImpl") jjs> DT [JavaClass DefTestImpl] jjs> var dt = new DT() jjs> dt.sayHello("World") Hello World
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 30
Часть предпредпоследняя..
JavaScript(ing)
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 31
Scripting расширения • Возможность указывать classpath элементы для JVM
• JavaScript Strict Mode
• Scripting mode!!!!
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 32
JavaScript в консоли JavaScript: var lines = 'ls -‐lsa'.split("\n"); for each (var line in lines) { print("|> " + line); } На выходе: buzz:Nashorn miOa$ jjs -‐scripOng scripOng.js |> total 112 |> 0 drwxr-‐xr-‐x 16 miOa staff 544 21 апр 21:39 . |> 0 drwxr-‐xr-‐x 3 miOa staff 102 19 апр 14:26 .. |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 113 21 апр 21:32 Adder.class |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 603 21 апр 21:32 DefTest.class |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 273 21 апр 21:39 DefTestImpl.class |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 1001 21 апр 21:32 EvalScript.class |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 1379 21 апр 21:32 Eval_Bind.class |> 8 -‐rw-‐r-‐-‐r-‐-‐ 1 miOa staff 1402 21 апр 21:32 Eval_Invocable.class
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 33
JavaScript в консоли JavaScript: #!/usr/bin/env jjs -‐scripOng print( "Arguments (${$ARG.length})"); for each (arg in $ARG) { print("-‐ ${arg}") } Output: $ chmod +x executable.js $ ./executable.js Arguments (0) $ ./executable.js -‐-‐ hello world ! Arguments (3) -‐ hello -‐ world -‐ !
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 34
Часть промежуточная..
Internals
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 35
Как оно работает • Dynalink: Имплементация метаобъектного протокола мультиязычного связывающего фреймворка, основанного на invokedynamic. Позволяет JVM классам созданными одним языком вызывать методы и свойства классов созданными другим языковым рантаймом в одной инстанции JVM
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 36
Как оно работает • Dynalink:
– Позволяет динамически вызывать операции на объектах создавая MethodHandle или
– В случае генерации байткода, позволяет вызывать методы без знания конкретной модели
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 37
Часть предпоследняя..
Энтерпрайз!
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 38
Как оно работает • HTML5 и CSS3 + быстрые JS движки превратили браузер в мощную платформу
• Восход “Thin Server Architecture” (TSA) & “Single Page Architecture”
• ..но они все общались на разных языках до появления node.js
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 39
Node.js event loop
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 40
…И как это происходит в Avatar.js
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 41
Node модули работающие с Avatar.js • abbrev • ansi • async • block-‐stream • chmodr • chownr • coffee-‐script • colors • commander • connect • debug • engine.io • express • �sream[1] • glob[1] • graceful-‐fs • inherits • ini
• init-‐package-‐json • grunt • grunt-‐bower-‐task • jade • lodash • mime • mkdirp • mocha • moment[2] • mongodb[3] • mongoose[3], [4] • mustache • node-‐unit • node-‐uuid • once • opener • opOmist • osenv
• passport • q • read • redis • request • retry • rimraf • ronn • semver • slide • socket.io • tar • uglify-‐js • uid-‐number • underscore • which • winston [1]: with minor issues related to symbolic link handling [2]: some issues with Ancient Greek lang [3]: Replace all const occurrences with var [4]: Buffer Schema data type is not supported
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 44
Приложение Avatar EE • … или Архив
• Простая папка содержащая avatar.properties и WEB-INF папку
• Содержит папку Views и/или Service
• «Встроенная системная» папкаа
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 46
Сервисы Avatar • Сервис Avatar наследует REST, WebSocket или
SSE абстракцию
• Относительно ленивый. Инстансцируется и вызывается при первом вызове. Как Servlet.
• Одновременно доступны библиотеки node.js и все библиотеки Java
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 47
Avatar клиент • View – Декларативное UI – Bundle widgets ( jQuery-ui)
• Model – WS, REST, SSE, local – Autowire with services
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 48
Avatar EE • Data providers
– JPA provider
• JavaScript API интерфейс для Java Messaging Service (JMS) • На будущее: “native” API для другие EE технологий:
– Context and Dependency Injection (CDI) – Enterprise Java Beans (EJB) – ..etc
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 50
Avatar • Поддерживаемые фреймворки – Nodyn
• Vert.x + dyn.js + Netty
– Trieme • Apigee
• Reactive – RxJS – React.js
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 53
Часть последняя..
Состояние на сегодня
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 54
Дела на сегодня • Начиная с 8u20 поддержка cache для уже скомпилированных скриптов
• Начиная с 8u40 – Optimistic typing (JEP196)* – Code Persistence (JEP194)
• --class-cache-size=100 default 50 • --persistent-code-cache=true|false default false
– Class Filter (JEP202) – Partial ECMAScript 6 support const/var (JEP203)
• --language=es5|es6 default is es5
• --lazy-compilation=true|false
• * NashornScriptEngineManager factory = new NashornScriptEngineManager(); ScriptEngine engine = factory.getEngineByName(”—opOmisOc-‐types=true"); Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 55
let & var // let let a=2; function f(x){ // a=2 if (x){ let a=42; } // a все еще 2 }
// var var a=2; function f(x){ // a = undefined if (x){ let a=42; } // либо 42 либо undefined }
Часть после последней..
Состояние на завтра
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 58
Дела на завтра • 8u60
– Оптимизация – Улучшение работы Optimistic typing
• Java 9 – Полная поддержка ECMAScript 6 – Parser API (JEP 236) – Java Flight Recorder
• JS Profiler • Nashorn tag
Но не все так просто
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 60
И причина тому
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 61
И все-таки.. V8 быстрее
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 62
Но у Java самая большая экосистема .. в мире
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 63
Домашнее задание:
• Попробуйте написать multithreaded приложение на JavaScript :)
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 64
Домашнее задание 2:
• https://blogs.oracle.com/nashorn/entry/using_nashorn_with_intellij
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 65
Так к чему все это?
Октябрь 16–18 2015 | Санкт-Петербург #jokerconf dmitryalexandrov.net | @bercut2000 66