2. “Any application that can be written in JavaScript, will eventually be
written in JavaScript”
- Jeff Atwood (founder, stackoverflow.com)
3.
4. In the Beginning - JavaScript
• Developed by Netscape as a portable version of
Java offering a lightweight interpreted language
• Developed under the name Mocha, officially
released as LiveScript in September 1995,
• Renamed JavaScript in December 1995 as a
marketing ploy to leverage off Java's popularity
• Even reserved Java’s keywords
• Standardized by ECMA International
7. In the Beginning - Rhino
• In 1997 Netscape wanted a browser written fully in
Java and so it needed an implementation of
JavaScript written in Java.
• Code named "Javagator", project was canned but
engine lived on
• Compiles JavaScript code to Java bytecodes in
either Interpreted or generated Java class files.
• Suffers from:
• Slow compile time
• Memory leaks
• Very unsecure!!!
8. Using Rhino - Command line and REPL
• jrunscript -e "print('hello world')“
• jrunscript -l js -f helloWorld.js
• jrunscript
js> print('Hello Worldn');
>>Hello World
9. Using Scripting API - background
• “javax.script” package
• Use any JSR-223 compliant scripting language.
• Java SE 6 & 7 include Scripting API and Mozilla
Rhino as default engine
• Extensive list of available engines: Python, Ruby,
PHP, Groovy …
10. Script API Basics
1) Create a ScriptEngineManager object.
ScriptEngineManager factory = new ScriptEngineManager();
2) Get a ScriptEngine object from the manager.
ScriptEngine engine = factory.getEngineByName("JavaScript");
3) Evaluate script using the ScriptEngine's eval methods.
engine.eval("print('Hello, World')");
14. Implementing Java Interfaces by Scripts
String script =
"function run() { "
+ "println('run called'); "
+ "}";
engine.eval(script);
Runnable r = ((Invocable) engine).getInterface(Runnable.class);
new Thread(r).start();
>>run called
15. Java Interfaces in JavaScript
var r = new java.lang.Runnable() {
run: function() {
print("running...n");
}
};
var th = new java.lang.Thread(r);
th.start();
>>running…
17. Compiling with Rhino
cat test.js
java.lang.System.out.println("hi, mom!");
java org.mozilla.javascript.tools.jsc.Main test.js
ls *.class
test.class
java test
>>hi, mom!
18. Optimization
-1
Interpretive mode is always used. No class files are generated,
0
Basic Compilation. No optimizations are performed. The compiler runs fastest in this
mode, but the generated byte code is less efficient
1-9
All optimizations are performed. Java Class Files generated
• Rhino optimizer not standard with JDK
• Runtime optimization of compilation can be set from -1 to 9
20. InvokeDynamic
Opcode Usage
Invokestatic For static methods
Invokevirtual For non-private instance methods
Invokespecial For private instance
Invokeinterface For the receiver that implements the interface
Bytecode operations that were available before JDK version 7:
22. • JavaScript is dynamic
– Things can change at runtime
• For example, what is the type of:
var x = 500000;
• x *= 500000; And now?
The challenge
23. • Based on an experimental project, the Da
Vinci Machine
• Adds two new concepts to the JVM:
– invokedynamic bytecode instruction
– MethodHandles
• The first bytecode extension since 1999!
Enter JSR 292
30. Why you care
• Server-side JavaScript
• Leverage Existing
JavaScript Libraries
• Cross Platform scripting –
Rhino runs on Android
• Fast performance with
Nashorn
• Leverage some vNode
Libraries with Nashorn
Why Oracle cares
• Atwood’s law
• Node.js
– A real threat to Java’s
server-side growth
• Let developers handle
typing with
invokedynamic
– Jruby, Jython
Summary – JavaScript Why bother?
abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public
java org.mozilla.javascript.tools.jsc.Main [options] file1.js [file2.js...]
where options are:
-extends java-class-name
Specifies that a java class extending the Java class java-class-name should be generated from the incoming JavaScript source file. Each global function in the source file is made a method of the generated class, overriding any methods in the base class by the same name.
-implements java-intf-name
Specifies that a java class implementing the Java interface java-intf-name should be generated from the incoming JavaScript source file. Each global function in the source file is made a method of the generated class, implementing any methods in the interface by the same name.
-debug-g
Specifies that debug information should be generated. May not be combined with optimization at an optLevel greater than zero.
-main-method-class className
Specify the class name used for main method implementation. The class must have a method matching public static void main(Script sc, String[] args).
-nosource
Does not save the source in the class file. Functions and scripts compiled this way cannot be decompiled. This option can be used to avoid distributing source or simply to save space in the resulting class file.
-o outputFile
Writes the class file to outputFile, which should end in .class and must be a writable filename.
-d outputDirectory
Writes the class file to outputDirectory.
-opt optLevel
Optimizes at level optLevel, which must be an integer between -1 and 9. See Optimization for more details. If optLevel is greater than zero, -debug may not be specified.
-package packageName
Specifies the package to generate the class into. The string packageName must be composed of valid identifier characters optionally separated by periods.
-version versionNumber
Specifies the language version to compile with. The string versionNumber must be one of 100, 110, 120, 130, 140, 150, 160, or 170. See JavaScript Language Versions for more information on language versions.
Chrome is ~15 quicker than compiled Java/Rhino, and ~200 times quicker than interpreted Java/Rhino.
The invokeDynamic instruction was added in Java 7 to allow developers writing their own dynamic languages to decide at runtime how to link code.
For static languages like Java and Scala, the compiler decides at compile time which method would be invoked .
Unfortunately, for languages which are more dynamic in nature (and JS is a good example) static resolution may not be possible.
When we say obj.foo() in Java, either the class of obj has a foo() method or it doesn’t.
In a language like JS that will depend on the actual object referenced by obj at runtime - a nightmare scenario for a static compiler.
A compile-time approach to linking in this case just doesn't work. But invokeDynamic does.
InvokeDynamic enables deferring of linkage back to the writers of the language at run-time, so they can guide the JVM as to which method they would like to call, based on their own language semantics. This is a win-win situation. The JVM gets an actual method to link to, optimize and execute against, and the language makers control its resolution.
A simple invocation to a method starts from a given “Call Site”,
A callsite consists of name of the method, the signature (access level, modifiers and return type) and the arguments that are processed by this method
The JVM will process this Call Site information and go through a set of operations:
It is going to look for that method’s code within memory (Lookup), check if the types involved in the operations match (Type Checking), invokes the actual code (Branch) and then caches the location of that method so, if it is going to be needed again soon, the JVM already knows that memory address and speeds up the process (Cache).
The new “Invokedynamic” bytecode operation allows the JVM to customize how the resources for the Call Site are assembled (dynamically) and also perform a different set of operations within the JVM so the field or method can be accessed (invoked). Instead of the regular Call Site, it integrates bytecode (invokedynamic operation with name and signature) with a bootstrap method, this is the component that will connect the Call Site with the “Method Handle”, once the handle finds the correct way of making this invocation occurs, the JVM will optimize the operation and the invokedynamic bytecode will be attached to the “Target Method” to avoid processing all these steps again. In a scenario where a scripting language that is running within the JVM needs to access a specific function, it is going to initiate the process by providing the bootstrap method with the invokedynamic instructions (name of the function followed by arguments and the return type), the JVM will look for the function within a Method Table (list of functions that are not associated to any object or class) based on the arguments that are defined at runtime (Lookup), once it finds the function, it will perform some language-specific type checking (Type Checking) and then it will finish the bootstrap process connecting the Call Site with the Method Handle so it can be executed (Branch), this connection is performed only once but Call Sites can be connected to new Method Handles.
Behind the scene, Nashorn compiles your JavaScript code into Java bytecodes and run them on the JVM itself. On top of that, Nashorn is taking advantage of invokedynamic instruction (from the Da Vinci Machine Project, part of Java 7) to permit "efficient and flexible execution" in a dynamic environment such as JavaScript