Contenu connexe
Similaire à JavaOne 2012 CON3978 Scripting Languages on the JVM (20)
JavaOne 2012 CON3978 Scripting Languages on the JVM
- 1. Paul Thwaite – Java 8 Quality Assurance Engineer
Monday 1 October 2012
How to embed your scripting language
JavaOne 2012 - CON3978
© 2012 IBM Corporation
- 2. Important Disclaimers
THE INFORMATION CONTAINED IN THIS PRESENTATION IS PROVIDED FOR INFORMATIONAL PURPOSES ONLY.
WHILST EFFORTS WERE MADE TO VERIFY THE COMPLETENESS AND ACCURACY OF THE INFORMATION
CONTAINED IN THIS PRESENTATION, IT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED.
ALL PERFORMANCE DATA INCLUDED IN THIS PRESENTATION HAVE BEEN GATHERED IN A CONTROLLED
ENVIRONMENT. YOUR OWN TEST RESULTS MAY VARY BASED ON HARDWARE, SOFTWARE OR INFRASTRUCTURE
DIFFERENCES.
ALL DATA INCLUDED IN THIS PRESENTATION ARE MEANT TO BE USED ONLY AS A GUIDE.
IN ADDITION, THE INFORMATION CONTAINED IN THIS PRESENTATION IS BASED ON IBM’S CURRENT PRODUCT
PLANS AND STRATEGY, WHICH ARE SUBJECT TO CHANGE BY IBM, WITHOUT NOTICE.
IBM AND ITS AFFILIATED COMPANIES SHALL NOT BE RESPONSIBLE FOR ANY DAMAGES ARISING OUT OF THE USE
OF, OR OTHERWISE RELATED TO, THIS PRESENTATION OR ANY OTHER DOCUMENTATION.
NOTHING CONTAINED IN THIS PRESENTATION IS INTENDED TO, OR SHALL HAVE THE EFFECT OF:
- CREATING ANY WARRANT OR REPRESENTATION FROM IBM, ITS AFFILIATED COMPANIES OR ITS OR THEIR
SUPPLIERS AND/OR LICENSORS
2 © 2012 IBM Corporation
- 3. Introduction to the speaker – Paul Thwaite
■ 11 years experience developing and deploying Java SDKs
■ Recent work focus:
– Quality Assurance specialist
• Leading cross-continent teams
• System Test on IBM SDKs
– Quality assurance lead for Java 8
• Focus on testing in OpenJDK
• OpenJDK contributor
■ My contact information:
– paul_thwaite@uk.ibm.com
– linkedin.com/profile/view?id=26327969
3 © 2012 IBM Corporation
- 4. What you will learn from this talk
■ Why me and what I do
■ Why we run scripting languages on the JVM
■ Methods of embedding
■ Models of embedding
■ Comparison of two embedding frameworks
■ Which approach is best
4 © 2012 IBM Corporation
- 5. Why me and what I do
■ Test IBM's Java SDK
– I break Java
■ Focus on system testing in QA
– Multi-threaded load testing
– Third-party applications
■ Increasing use of scripting languages running on the JVM
– We need to ensure they run on the IBM SDK
5 © 2012 IBM Corporation
- 7. How many languages
run on the JVM?
>800 >60
total active
http://en.wikipedia.org/wiki/List_of_JVM_languages
7 © 2012 IBM Corporation
- 9. JavaScript
How many languages
run on the JVM?
Most popular include
9 © 2012 IBM Corporation
- 10. How many languages
run on the JVM?
Why is the JVM so popular?
10 © 2012 IBM Corporation
- 11. Why is the JVM so popular?
The JVM is fast
■ Runtime performance benefits
■ Threading and scaling support
■ JVM profiling tools
■ Access to the impressive array of Java APIs
■ Support for multiple languages
11 © 2012 IBM Corporation
- 12. How many languages
run on the JVM?
Let's examine a few
implementation methods
12 © 2012 IBM Corporation
- 14. Implementation Methods
■ Compiled to bytecodes
– Jython
– Groovy
– Scala
■ Interpreted on the JVM
– JavaScript
– JRuby
14 © 2012 IBM Corporation
- 15. Implementation Methods
■ Compiled to bytecodes
– Jython
– Groovy
– Scala
■ Interpreted on the JVM
– JavaScript
– JRuby
■ Embedded in a Java application on the JVM
– Jython
– Groovy
– Scala
– JavaScript
– JRuby
15 © 2012 IBM Corporation
- 16. Compiled to bytecodes
Compiling a Jython script to bytecodes and running it on the JVM
MyJythonApp.py Jythonc MyJythonApp.class
Compiler
JVM
MyJythonApp
16 © 2012 IBM Corporation
- 17. Interpreted on the JVM
Interpreting a JRuby script on the JVM
JVM
JRuby Java JRuby.rb
Interpreter
The JRuby language provides the interpreter in Java
17 © 2012 IBM Corporation
- 18. Embedding in a Java application
Embedding and running a JRuby script inside a Java application on the JVM
JVM
Ruby.rb JRuby
MyJavaApp.class
Embed Engine
The language provides the embed engine
18 © 2012 IBM Corporation
- 19. Embedding in a Java application – multiple scripts
Embedding and running multiple scripts inside a Java application on the JVM
JVM
Ruby.rb JRuby
JRuby.rb JRuby
Embed Engine
Embed Engine
MyJavaApp.class
Javascript
Ruby.rb JavaScript
JavaScript.js Embed Engine
Embed Engine
The language provides the embed engine
19 © 2012 IBM Corporation
- 21. Scripting on the JVM - Models
Script Java
JVM
Java Script
JVM
Java Script
JVM
21 © 2012 IBM Corporation
- 22. Scripting on the JVM – Script domain knowledge
Language-specifc
■ Java objects are created
and used from inside the Script
script Java
JVM
■ Requires
– Scripting language
knowledge to implement
require 'java'
Java objects
frame = javax.swing.JFrame.new("Window")
– Java knowledge
label = javax.swing.JLabel.new("Hello")
frame.getContentPane.add(label)
frame.setDefaultCloseOperation
■ Limited re-use capabilities
(javax.swing.JFrame::EXIT_ON_CLOSE)
– Not portable code
frame.pack
– Locked in to using the
frame.setVisible(true)
chosen scripting
language
22 © 2012 IBM Corporation
- 23. Scripting on the JVM – Java domain knowledge
Bridge
■ Java runs a script which is
embedded within the Java Java
application Script
■ The APIs used to invoke the
script belong to the scripting JVM
language
import org.jruby.embed.*;
■ Requires ScriptingContainer container = new
– Java knowledge ScriptingContainer();
– Language embed API container.runScriptlet(PathType.RELATIVE,
knowledge
– Bridging knowledge "myscripts/ruby.rb");
■ Re-use existing scripts
– Optional bridge for
legacy scripts
– Investment in using
chosen scripting
language
23 © 2012 IBM Corporation
- 24. Scripting on the JVM – Java and script domain knowledge
■ Options
– Invoke a script from a Java Script
Java application
– Create and use Java
objects inside a script JVM
■ Requires import javax.script.*;
– Java knowledge ScriptEngineManager engineMgr = new ScriptEngineManager();
– Knowledge of the JSR ScriptEngine engine = engineMgr.getEngineByName("jruby");
223 API InputStream is =
– Some knowledge of the this.getClass().getResourceAsStream("/myscripts/ruby.rb");
scripting language may
Reader reader = new InputStreamReader(is);
be required
engine.eval(reader);
■ Re-use existing scripts
– Support for multiple
scripts
24 © 2012 IBM Corporation
- 26. Embedding in a Java application – multiple scripts
Embedding and running multiple scripts inside a Java application on the JVM
JVM
Ruby.rb JRuby
Ruby.rb JRuby
Embed Engine
Embed Engine
MyJavaApp.class
Javascript
Ruby.rb JavaScript
JavaScript.js Embed Engine
Embed Engine
The language provides the embed engine
26 © 2012 IBM Corporation
- 27. What can you do with an embedded language?
Pass variables
to the script Retrieve
variables from
the script
Run a script
Embedding
Call a script's
function and
retrieve its
Configure script return value
environment
Run multiple
scripts on the
same JVM
27 © 2012 IBM Corporation
- 28. Ways to embed a scripting language on the JVM
JSR 223 Language-specific
javax.script Embed
Implementations Implementations
● A common API for embedding ● Implementation provided by the
multiple languages language
● Implementation provided by the ● Similar to JSR223
language ● Extensions available
● Some popular languages provide ● Ability to fine-tune the scripting
a javax.script API environment
● Most popular languages provide
an embed API
28 © 2012 IBM Corporation
- 29. Comparison of embedding frameworks
JSR 223 Language-specific
javax.script Embed
vs
Implementations Implementations
■ Introduction to javax.script
■ Code examples using these languages
– Jruby
– Jython
– Groovy
■ Exception handling may be missed off some examples to save space
29 © 2012 IBM Corporation
- 30. What is javax.script?
JSR 223 Scripting for the Java Platform
■ Allows a developer to embed a scripting language in a Java application
■ Available from Java 6 SE
■ Implementation provided by the scripting language
■ JSR 223 specification defines 6 interfaces
– ScriptEngine
– ScriptEngineFactory
– ScriptContext
– Bindings
– Invocable
– Compilable
■ Setup
– Download the JSR 223 implementation from your language provider's website
– Add the jar(s) to the CLASSPATH
– Add your script directory to the CLASSPATH
■ ScriptEngine is discovered at runtime via the JAR services mechanism
30 © 2012 IBM Corporation
- 31. Example: Query JAR services for installed JSR223 Java Scripting Engines
JSR 223
import javax.script.*;
public class ListScriptEngines {
public static void main(String[] args) {
ScriptEngineManager mgr = new ScriptEngineManager();
List<ScriptEngineFactory> factories = mgr.getEngineFactories();
for (ScriptEngineFactory factory: factories) {
String engName = factory.getEngineName();
String engVersion = factory.getEngineVersion();
System.out.println("Script Engine: " + engName + " V" + engVersion);
}
}
}
Output to stdout:
Script Engine: Groovy Scripting Engine V2.0
Script Engine: jython V2.5.3
Script Engine: JSR 223 JRuby Engine V1.6.7.2
Script Engine: Mozilla Rhino V1.7 release 3 PRERELEASE
31 © 2012 IBM Corporation
- 32. Example: Embedding a Ruby script into a Java application
JSR 223 - JRuby
import javax.script.*;
ScriptEngineManager engineMgr = new ScriptEngineManager();
ScriptEngine engine = engineMgr.getEngineByName("jruby");
InputStream is = this.getClass().getResourceAsStream("/myscripts/ruby.rb");
Reader reader = new InputStreamReader(is);
engine.eval(reader); //throws ScriptException
JRuby Embed API
import org.jruby.embed.*;
ScriptingContainer container = new ScriptingContainer();
container.runScriptlet(PathType.RELATIVE, "myscripts/ruby.rb");
Script: /myscripts/ruby.rb Output to stdout:
stringHello = "Hello, I am a jruby script!" Hello, I am a ruby script!"
puts "#{stringHello.to_s}"
32 © 2012 IBM Corporation
- 33. Example: Passing a variable to a Jython script and retrieving it back again
JSR 223 - Jython
import javax.script.*;
ScriptEngineManager engineMgr = new ScriptEngineManager();
ScriptEngine engine = engineMgr.getEngineByName("jython");
InputStream is = this.getClass().getResourceAsStream("/myscripts/jython_var.py");
Reader reader = new InputStreamReader(is);
try {
engine.put("javaString", "red green blue");
engine.eval(reader);
System.out.println("java> received " + engine.get("javaString"));
} catch (ScriptException e) {}
Jython Embed API
import org.python.util.PythonInterpreter;
PythonInterpreter python = new PythonInterpreter();
python.set ( "javaString", new org.python.core.PyString("red green blue"));
python.execfile ( "myscripts/jython_var.py" );
System.out.println("java> received " + python.get ("javaString"));
Script: /myscripts/jython_var.py Output to stdout:
print "jython> received " + javaString jython> received red green blue
javaString += " yellow indigo white" java> received red green blue
33
yellow indigo white
© 2012 IBM Corporation
- 34. Example: Invoke a Groovy function with a return value
JSR 223 - Groovy
ScriptEngineManager engineMgr = new ScriptEngineManager();
ScriptEngine engine = engineMgr.getEngineByName("groovy");
InputStream is = this.getClass().getResourceAsStream("/myscripts/groovy_func.groovy");
Reader reader = new InputStreamReader(is);
if (engine instanceof Invocable) { //Invocable is an optional interface
Invocable invocableEngine = (Invocable) engine;
engine.eval(reader);
System.out.println("java> What's the Square root of 360?");
double squareRoot = (double) invocableEngine.invokeFunction("squareRoot", 360);
System.out.println("java> " + squareRoot);
}
Groovy Embed API
String[] roots = new String[] { "C:scripts" };
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Class<?> groovyClass = gse.loadScriptByName("groovy_func.groovy");
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
System.out.println("java> What's the square root of 360?");
System.out.println("java> " + groovyObject.invokeMethod("squareRoot", 360).toString());
Script: /myscripts/groovy_func.groovy Output to stdout:
def squareRoot(number) { java> What's the square root of 360?
println "groovy> Sqrt of ${number} is" groovy> Sqrt of 360 is
Math.sqrt(number) java> 18.973665961010276
} 34 © 2012 IBM Corporation
- 35. Example: How to set options in JRuby
■ JRuby provides many options to the developer to allow for the JRuby ScriptEngine to be
customised and finely-tuned
■ In JRuby, these options are set using SystemProperty
– Outside the spec of JSR 223
– Requires language-specific knowledge
// Make JRuby's engine thread safe
System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”);
// Turn on JIT verbose logging
System.setProperty("jruby.jit.logging.verbose", “true”);
// Set JRuby home
System.setProperty("jruby.home", “/path/to/jruby”);
35 © 2012 IBM Corporation
- 36. Example: Comparison of setting options in JRuby
// JRuby EmbedCore API
// Make JRuby's engine thread safe
// Set via a constructor argument of Scriptingcontainer
ScriptingContainer instance = new
ScriptingContainer(LocalContextScope.THREADSAFE);
// JSR 223 API
// Make JRuby's engine thread safe
System.setProperty("org.jruby.embed.localcontext.scope", “threadsafe”);
■ Jruby's EmbedCore API
– Set on a per engine basis
– Well documented and easy to find
■ Javax.script API
– Set system wide
– Multiple engines will all have the same behaviour
– Harder to find documentation (not part of an API)
36 © 2012 IBM Corporation
- 37. Example: Comparison of setting options in Groovy
// Groovy Embed API
// Set the compiler warning message level
CompilerConfiguration.setWarningLevel(int warningLevel);
// JSR 223 API
// Set the compiler warning message level
No easy way to do it
37 © 2012 IBM Corporation
- 38. How far does javax.script go?
■ Provides useful interaction between Java and many scripting languages
– Plug 'n Play support for multiple languages
– Great for simple embedding
– Easy-to-use API
■ Limitations
– The Invocable and Compilable interfaces are optional
– Setting language-specific options removes the abstraction JSR 223 provides
– Not all engines will provide the same configuration options
– Requires knowledge of the underlying ScriptEngine implementation beyond JSR 223
38 © 2012 IBM Corporation
- 39. Scripting on the JVM is great
■ Some of the most popular languages support Java embedding
■ Embedding a language in a new application is easy to get started
■ Deciding how to embed has consequences
–JSR 223 is a great framework for basic embedding
–If you need to harness the power of the language, you will need to use the
language API
• For example, JRuby Embed Core
■ How are you embedding your scripting language on the JVM?
39 © 2012 IBM Corporation
- 40. References
■ JSR 223
– JSR 223 specification
• http://www.jcp.org/en/jsr/detail?id=223
– JRuby implementation
• http://kenai.com/projects/jruby/pages/JavaIntegration
– Groovy implementation
• http://groovy.codehaus.org/JSR+223+Scripting+with+Groovy
■ Jython Java Integration
– http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html
■ Scripting in Java: Languages, Frameworks, and Patterns
– Dejan Bosanac, Addison-Wesley
40 © 2012 IBM Corporation
- 41. References
■ Get Products and Technologies:
– IBM Java Runtimes and SDKs:
• https://www.ibm.com/developerworks/java/jdk/
– IBM Monitoring and Diagnostic Tools for Java:
• https://www.ibm.com/developerworks/java/jdk/tools/
■ Learn:
– IBM Java InfoCenter:
• http://publib.boulder.ibm.com/infocenter/java7sdk/v7r0/index.jsp
■ Discuss:
– IBM Java Runtimes and SDKs Forum:
• http://www.ibm.com/developerworks/forums/forum.jspa?forumID=367&start=0
41 © 2012 IBM Corporation
- 42. Copyright and Trademarks
© IBM Corporation 2011. All Rights Reserved.
IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business
Machines Corp., and registered in many jurisdictions worldwide.
Other product and service names might be trademarks of IBM or other companies.
A current list of IBM trademarks is available on the Web – see the IBM “Copyright and trademark
information” page at URL: www.ibm.com/legal/copytrade.shtml
42 © 2012 IBM Corporation