Rhino JavaScript engine (which is included in Mustang) supports Continuations. Rhino optimizer needs to be switched off to enable continuations -- i.e., scripts are run in interpreted mode and Rhino does not generate bytecodes for scripts. In Mustang, Rhino optimizer has been removed -- so Rhino in Mustang runs in interpreter mode always. So, continuations are enabled always.
Java has final fields, parameters and local variables. And JavaScript 2.0 has const modifier. But, there is no support for finals or consts in JavaScript 1.x (although const and final are reserved words). We will see how we can implement equivalent of finals in JavaScript (in Mustang's JavaScript engine).
function finals() {
var map = new Object();
return new JSAdapter() {
__put__ : sync(function (name, value) {
// already exists, do not allow assignment again
if (name in map) {
throw "can't modify final field";
}
// does not exist in map, allow first assignment
map[name] = value;
}),
__get__ : sync(function (name) {
return map[name];
}),
__has__ : sync(function (name) {
return name in map;
})
}
}
Note that the sync built-in is used to wrap the methods so that the
object returned by finals function is MT-safe. Let us assume that the above code is stored in a file named "finals.js". Now, we can start jrunscript
using the following command line:
jrunscript -f finals.js -f -
The interactive jrunscript session is shown below:
js> var constants = finals()
com.sun.script.javascript.JSAdapter@a8c488
js> constants.x = 3
3.0
js> constants.x = 34
script error: sun.org.mozilla.javascript.internal.EvaluatorException: can't modify
final field (finals.js#7) (<STDIN>#1) in <STDIN> at line number 1
js> constants.y = 4
4.0
js> constants.y
4.0
js> constants.x
3.0
js> constants.y = 5656
script error: sun.org.mozilla.javascript.internal.EvaluatorException: can't modify
final field (finals.js#7) (<STDIN>#1) in <STDIN> at line number 1
js> quit()
A finals objects like 'constants' may be used with JavaScript with statement so that the properties may be accessed like variables (without the obj.field syntax).
Java objects of classes that override Object.finalize() method put lot of pressure on garbage collector. There was a nice talk on finalization in JavaOne 2005 (TS-3281). Important advice in this talk was avoid finalize() if you can!
But, you may have an application (or use a library) that uses finalize() methods. So, you may want to analyze your heap and see which objects, if any, are queued for finalization. Using jhat in Mustang build 61+, you can analyze finalizer queue. When you run jhat against your heap dump, there is a link called Show finalizer summary in the first page. If you click on this link, you can see histogram of objects waiting for finalization. i.e., it shows classwise count of objects pending finalization. Also, OQL now supports a method called finalizables on the built-in heap object. This method returns an iterator for objects pending finalization. The resulting iterator may be used with built-in functions operating on arrays/iterators.
With Mustang, Rhino JavaScript engine is included in JRE. Now, do you want <SCRIPT> support (and DOM) for Swing's JEditorPane? If so, please take the survey at http://java.sun.com/webapps/survey/display?survey_id=5370. And how about using javax.script framework, so that we can have support for language="<your-favorite-language>" and not just JavaScript (assuming ofcourse there will JSR 223 compliant script engine for your favorite language!).
This is continuation of my earlier post on namespaces. We saw how to implement namespace for JavaScript. How about a feature equivalent to Java's import (or C++ using)? We can implement something like:
/**
* imports all or subset of names from given namespace.
*
* @param ns namespace
* @param patten names matching this pattern will be imported
* pattern is optional. If not specified, all names are
* imported (like Java's import package_name.*).
*/
function using(ns, pattern) {
if (pattern == undefined) {
// import all
for (var name in ns) {
this[name] = ns[name];
}
} else {
if (typeof(pattern) == 'string') {
pattern = new RegExp(pattern);
}
// import only stuff matching given pattern
for (var name in ns) {
if (name.match(pattern)) {
this[name] = ns[name];
}
}
}
}
Sample script that uses namespace and using:
var ns = namespace("function p() { print('p'); }; function s() { print('s'); }");
ns.p(); // call 'p' in namespace 'ns'
using(ns); // import all from namespace 'ns'
p(); // call ns.p()
s(); // call ns.s();
Another script sample that uses imports subset:
var ns = namespace("function p() { print('p'); }; function s() { print('s'); }");
ns.p(); // call 'p' in namespace 'ns'
using(ns, /p.*/); // import only the names matching
p(); // call ns.p()
ns.s(); // call ns.s() -- but can only use qualified name
Thanks Alex. I had a typo (missing double quote) in namespace call
It is difficult to work with independently developed JavaScripts. There is no built-in Java "package" (or C++ "namespace")-like feature in JavaScript. You have to use script objects for everything. Yes, there is a namespace proposal in JavaScript 2.0. But, what do we do now?
Well designed JavaScript APIs (like TrimPath API) avoid polluting global namespace by exposing API as methods in few (may be just one!) objects. But, most of the useful JavaScript code out there may not have been written in that style. There will be many global variables and functions. You may still find those scripts useful. It is not always feasible or desirable to edit such scripts to avoid global namespace pollution. How about a simple namespace solution for JavaScript (in the context of Mustang's JavaScript engine)?
function namespace(code) {
// new global scope for the new namespace
var myGlobals = new Packages.javax.script.SimpleBindings();
// use 'engine' variable to execute code with
// new global scope
// 'engine' variable is of type javax.script.ScriptEngine
// This is exposed in jrunscript tool. But, it is easy to expose this
// from your Java programs as well. Please refer below...
engine.eval(code, myGlobals);
// return a wrapper object that exposes
// globals of the new namespace
return new JSAdapter() {
__has__: function (name) {
return myGlobals.containsKey(name);
},
__get__: function (name) {
return myGlobals.get(name);
},
__getIds__ : function () {
return myGlobals.keySet().toArray();
}
}
}
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine engine = m.getEngineByName("js");
// add a global variable called "engine"
engine.put("engine", engine);
With the above definition of namespace (I'd have preferred 'package', but that
is a JavaScript reserved word!), we can write:
var ns = namespace('var s = 3; function hello() { print('hello'); }');
// print 3 - value from namesapce
print(ns.s);
// print 'hello' by calling hello in namespace ns
ns.hello();
For better package/namespace level encapsulation, we may want to expose only functions from the namespace and hide all package-level variables. It is easy to modify above namespace function as shown below:
function namespace(code) {
var myGlobals = new Packages.javax.script.SimpleBindings();
engine.eval(code, myGlobals);
return new JSAdapter() {
__has__: function (name) {
// do not expose non-function type stuff!
var res = myGlobals.containsKey(name);
if (res) {
return typeof(myGlobals.get(name)) == 'function';
}
},
__get__: function (name) {
// do not expose non-function type stuff!
var val = myGlobals.get(name);
return typeof(val) == 'function'? val : undefined;
},
__getIds__ : function () {
return myGlobals.keySet().toArray();
}
}
}
Now, we have namespace. What about namespace using or package import-like feature? Well, that is a topic for another blog or an exercise to reader :-)
How do we write synchronized methods in JavaScript? Rhino JavaScript shell supports a global function called sync. sync function creates a synchronized function from an existing function. The new function synchronizes on the "this" object of its invocation. Scripts executing in the shell have access this sync function. But, in Mustang's JavaScript engine, the sync function is available always (i.e., global scope is always initialized with this function).
var obj = { f: sync(function () {
print('I am synchronized!');
}
};
// 'f' is a "synchronized" method.
obj.f();
If you just need mutual exclusion,
then sync function is enough. But, what if
you need wait,
notify and
notifyAll?
We can add these as function properties to Object.prototype as shown below:
Object.prototype.wait = function() {
var objClazz = java.lang.Class.forName('java.lang.Object');
var waitMethod = objClazz.getMethod('wait', null);
waitMethod.invoke(this, null);
}
Object.prototype.notify = function() {
var objClazz = java.lang.Class.forName('java.lang.Object');
var notifyMethod = objClazz.getMethod('notify', null);
notifyMethod.invoke(this, null);
}
Object.prototype.notifyAll = function() {
var objClazz = java.lang.Class.forName('java.lang.Object');
var notifyAllMethod = objClazz.getMethod('notifyAll', null);
notifyAllMethod.invoke(this, null);
}
We have added wait, notify and notifyAll to all JavaScript objects. Note that you can call the above methods only inside methods wrapped by sync. Or else you'll get IllegalMonitorStateException.
If you need multiple condition queues, read-write locks, semaphores, barriers and so on, then you can use java.util.concurrent API in JavaScript. (please refer to my earlier post )
As you may know already, Mustang's jmap utility can create heap dump from a live process or core dump. Also, hprof profiler can create heap dump with or without allocation site information. Heap dumps are binary format files that contain snapshot of Java heap. Mustang's jhat (Java Heap Analysis Tool) tools can be used to view and analyze the Java heap dumps. jhat includes interesting features such as OQL - Object Query Language.
Kelly Ohair has created a java.net project (https://heap-snapshot.dev.java.net/) to specify new Java heap dump file format. Please participate in this project and give us your feedback and suggestions.
Many Java applications use various configuration files. These are mostly of the form
With Mustang, JavaScript engine is part of JRE. With Mustang, Java programmers can make use of JavaScript files as "config" files. It is easy very easy to use ScriptEngine.eval method to parse the config file. The idea of using "scripting" language(s) for configuration is nothing new (for example, XEmacs uses Lisp)
For each "config parameter", you can define and initialize a script global variable in your script file. ScriptEngine.get method can be used to get the config parameter value from Java. If you want to be able to use your config. file(s) by other systems/programs without access to JavaScript engine as well, then you may want to consider JSON - JavaScript Object Notation. Because JSON uses subset of JavaScript object literal syntax -- so you can continue to use JavaScript engine to parse config file(s) in your Java programs.
Yes, E4X is not included in Mustang's Rhino JavaScript engine. But, we have rich XML API in JDK. We can easily use Java API to create reusable JavaScript functions for XML. We will see how we can write nice XPath scripting API using javax.xml.xpath package.
function XPath(expr) {
var global = XPath.__parent__;
function isJSName(qname) {
return qname.namespaceURI == 'http://www.mozilla.org/rhino/';
}
// We create a XPathVariableResolver that resolves
// variables names as script global variables.
function varResolver() {
return new Packages.javax.xml.xpath.XPathVariableResolver() {
resolveVariable: function(qname) {
if (isJSName(qname)) {
return global[qname.localPart];
}
return null;
}
}
}
// We create a XPathFunctionResolver that resolves
// function names as script global functions.
function funcResolver() {
return new Packages.javax.xml.xpath.XPathFunctionResolver() {
resolveFunction: function(qname, arity) {
// ignore arity...
if (isJSName(qname) &&
typeof(global[qname.localPart]) == 'function') {
// implement XPathFunction that calls the underlying
// JavaScript function
return new Packages.javax.xml.xpath.XPathFunction() {
evaluate: function(argsList) {
var func = global[qname.localPart];
var argsArray = argsList.toArray();
var args = new Array(argsArray.length);
for (var i in argsArray) {
args[i] = argsArray[i];
}
return func.apply(global, args);
}
}
}
return null;
}
}
}
// create a NamespaceContext
// we map mozilla URL to "js" prefix
function namespaceCtx() {
return new Packages.javax.xml.namespace.NamespaceContext() {
getNamespaceURI: function(prefix) {
switch (prefix) {
case "xml":
return "http://www.w3.org/XML/1998/namespace";
case "xmlns":
return "http://www.w3.org/2000/xmlns/"
case "js":
return "http://www.mozilla.org/rhino/";
default:
return "";
}
},
getPrefix: function(uri) {
switch (uri) {
case "http://www.w3.org/XML/1998/namespace":
return "xml";
case "http://www.w3.org/2000/xmlns/":
return "xmlns"
case "http://www.mozilla.org/rhino/":
return "js";
default:
return "";
}
}
}
}
var xpath = Packages.javax.xml.xpath.XPathFactory.newInstance().newXPath();
xpath.setXPathVariableResolver(varResolver());
xpath.setXPathFunctionResolver(funcResolver());
xpath.setNamespaceContext(namespaceCtx());
return xpath.compile(expr);
}
function XMLSource(file) {
return new Packages.org.xml.sax.InputSource(java.io.FileInputStream(file));
}
We'll use the following simple XML file ("t.xml") as example:
<html>
<head>
<title>hello</title>
<body>
<img src="mustang.jpg"></img>
</body>
</head>
</html>
Using the above XPath and XMLSource functions, we can write something like:
function toUpper(s) {
return s.toUpperCase();
}
var src = XMLSource("t.xml");
var xp = XPath("js:toUpper(/html/head/title)");
print(xp.evaluate(src)); // prints "HELLO".
In the above code, we make use of user defined JavaScript function toUpper inside XPath expression. We can easily write useful script functions and call the same in XPath expressions. I've 'js' namespace prefix for JavaScript functions and variables. So, you need to use the prefix "js:" to call script functions. This prefix may be changed by editing XPath function given above. Also, as a convention, I've used Rhino URL as URI for "js" prefix.
JSR 223 API allows exposing multliple scopes (called "Bindings") to scripts. ScriptEngine allows one or more Bindings to be specified while evaluating scripts via ScriptContext. Script engine will search these "scopes" while looking for global variables.
Java program that executes JavaScript (by eval) can expose different ENGINE_SCOPE bindings for each Java thread. This way the script global variables accessed from script executing in different Java threads would be different.
But, what if the script itself creates Java thread(s)? In that case, script can make use of java.lang.ThreadLocal directly as shown below:
var tls = (function () {
var map = new Object();
return new JSAdapter() {
__has__: function(name) {
return map[name] != undefined;
},
__get__: function(name) {
if (map[name] != undefined) {
return map[name].get();
} else {
return undefined;
}
},
__put__: sync(function(name, value) {
if (map[name] == undefined) {
var tmp = new java.lang.ThreadLocal();
tmp.set(value);
map[name] = tmp;
} else {
map[name].set(value);
}
}),
__delete__: function(name) {
if (map[name] != undefined) {
map[name].set(null);
}
}
}
})();
With the above code, we can write:
tls.x = 10;
print(tls.x); // prints 10
// create another thread and start it
var th = new java.lang.Thread(
function () {
tls.x = 'hello';
print(tls.x); // prints 'hello'
});
th.start();
print(tls.x); // prints 10 -- value is thread local.
We can easily create multiple thread local variables by adding more properties
to "tls" object. Also, we can use "tls" object in JavaScript with statement
so that the scope uses thread local variables:
with(tls) {
print(x); // prints thread local x in each thread
}
We saw similarities between Self and JavaScript in my post titled Self, JavaScript and JSAdapter. One important difference between JavaScript and Self is that Self supports multiple inheritance. Self supports more than one parent slots per object. Note that parent slot of Self is similar to JavaScript's prototype (settable by __proto__ property). But, in JavaScript, there is only one rototype per object. So, how do we have multiple inheritance in JavaScript? We can use JSAdapter. We will code a JSAdaper based 'extend' function for multiple inheritance (I'd have preferred 'extends' -- but that is a reserved word in JavaScript!)
// first parameter is the object extended.
// rest of the parameters are 'super' objects.
// or in Self terminology, multiple 'parent' slot values.
function extend(object /*,proto1, proto2, ....*/) {
if (arguments.length < 2) {
throw "should extend from atleast one proto";
}
// collect all prototypes in an array
var protos = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
protos[i-1] = arguments[i];
}
// save the first param as 'self'
var self = object;
self.__proto__ = new JSAdapter() {
// check the property in all prototypes
__has__: function(name) {
for(var i in protos) {
if (name in protos[i]) {
return true;
}
}
return false;
},
// check the property in all prototypes
__get__: function(name) {
for(var i in protos) {
if (name in protos[i]) {
var p = protos[i];
var prop = p[name];
// treat function type properties differently
if (typeof(prop) == 'function') {
// we need to make the 'this' to be the 'self'
return function() {
return p[name].apply(self, arguments);
}
} else {
return prop;
}
}
}
return undefined;
},
__put__: function(name, value) {
for(var i in protos) {
if (name in protos[i]) {
protos[i][name] = value;
return;
}
}
},
__delete__: function(name) {
for(var i in protos) {
if (name in protos[i]) {
delete protos[i][name];
return;
}
}
},
__getIds__: function() {
var res = new Array();
for (var i in protos) {
for (var j in protos[i]) {
res[res.length] = j;
}
}
return res;
}
}
return self;
}
Using the above extend function, we can use multiple inheritance as shown below:
var x = { b : 10, f: function() { print(this.b); } }
var y = { a : 12, add: function() { return this.b + this.a } }
var m = new Object;
extend(m, x, y);
print(m.b); // prints 10
print(m.a); // prints 12
m.f(); // prints 10 by calling x.f
print(m.add()); // prints 22!
m.a = -2;
print(m.add()); // prints 8!
Wow! We really got multiple inheritance in JavaScript! Now, you may want to write
reusable mixins in JavaScript!!
JavaScript supports watch method for every script Object. This method adds a watchpoint to a property of the object. Whenever a value is assigned to the mentioned property, it calls up a handler function allowing you to watch the new value assigned. If required, you can even alter the value assigned. But, this is supported only in SpiderMonkey, but not in Rhino. As you may know already, Mustang includes Rhino. So, what do we do? Well, we can use JSAdapter to implement a similar feature.
// creates a wrapper for a given object. The wrapper
// objects passes field access/assignment to the wrapped
// object except for the watched property. For the watched
// property, the wrapper calls a callback function.
function WatchWrapper(obj, prop, callback) {
return new JSAdapter() {
__has__: function(name) {
return (name in obj);
},
__get__: function(name) {
return obj[name];
},
// if property assigned is the watched property
// then, call the callback function. Otherwise
// just assign the field value.
__put__: function(name, value) {
if (name == prop) {
callback(obj, name, value);
} else {
obj[name] = value;
}
}
};
}
Let us say you want watch assignment to salary field in Employee objects:
function Employee(nm, sal) {
this.name = nm;
this.salary = sal;
}
We can change the above code as below:
function salaryWatcher(emp, name, newSal) {
if (emp.name == 'sundararajan') {
emp.salary = newSal * 100; // make it 100 times :-)
} else {
emp.salary = newSal;
}
return emp.salary;
}
function Employee(nm, sal) {
return WatchWrapper(
{ name: nm, salary: sal },
"salary",
salaryWatcher);
}
Note that the call sites that use Employee constructor need not change at all (whether or not field modification is watched). We can remove the watch by simply reverting back to the original code of the Employee function.
In JavaScript, all members (fields and methods) of any object are public. There is no equivalent of private, protected access of Java. What if we want to have encapsulate fields in JavaScript? The trick is to use Closures. If you know what closures are, then skip next section.
function f(a) {
function g() {
// we access argument 'a' of enclosing function 'f'
return a++;
}
// we return the function 'g' here
return g;
}
x = f(10);
print(x()); // prints 10
print(x()); // prints 11
print(x()); // prints 12
In the example, 'x' acts as generator of sequence with 10 as starting point
You may want to read Douglas Crockford's "Private Members in JavaScript" to see how closures are used to implement private instance fields.
Example with private instance fields:
function Employee(name, salary) {
// name and salary are private instance fields
this.getName = function() {
return name;
};
this.getSalary = function() {
return salary;
};
this.setSalary = function(amount) {
salary = amount;
};
this.increaseSalary = function(increment) {
if (increment < 0.0) {
throw "Huh! can't decrement!";
}
salary += increment;
};
}
var e = new Employee('Mr. X', 10000);
print(e.getSalary());
e.increaseSalary(1000);
print(e.getSalary());
e.increaseSalary(-100);
The above looks lot similar to the way objects are defined in the programming language E.
Okay, now we have got private field and getter/setter methods or getter method only (for read-only field such as name in the above example). But, the caller has to use method calls instead of 'natural' field access syntax. What if we want to have field access like syntax and still encaptulate the access by getter/setter? Yes, we can use JSAdapter
function GetterSetterWrapper(obj) {
return new JSAdapter() {
__has__ : function(name) {
// check whether obj has the property or getter method
return name in obj ||
typeof(obj['get' + name]) == 'function';
},
__get__: function(name) {
if (name in obj) {
return obj[name];
} else {
var getter = 'get' + name;
// if there is getter method, then call it
if (typeof(obj[getter]) == 'function') {
return obj[getter]();
} else {
return undefined;
}
}
},
__put__: function(name, value) {
var setter = 'set' + name;
// if there is setter method, call it
if (typeof(obj[setter]) == 'function') {
return obj[setter](value);
} else {
// just set the property
return obj[name] = value;
}
}
}
}
With above wrapper function, we can write:
// wrap the employee object with get-set wrapper
var e = GetterSetterWrapper(new Employee('Mr. X', 10000));
print(e.getSalary());
// or equivalently
print(e.Salary);
e.increaseSalary(1000);
// or equivalently
e.Salary += 1000;
print(e.getSalary());
// or equivalently
print(e.Salary);
e.increaseSalary(-100);
// or equivalently
e.Salary -= 100;
Ah! It looks like we can have the cake and eat it as well! Note: I've not implemented JavaBean
convention for property names (Note the use of e.Salary instead of e.salary). As usual,
that is left as an exercise to reader :-) (hint: modify __get__, __put__ and __has__ methods
above to implement JavaBean convention).
With Mustang's JavaScript engine, there are atleast 4 ways to implement Java interfaces in script:
var r = new JavaAdapter(java.lang.Runnable,
{
run: function() { print('hello'); }
});
r.run();
This feature may also be used with Java anonymous class-like syntax as shown below:
var r = new java.lang.Runnable() {
run: function() {
print('hello')
}
};
r.run();
Unlike, Rhino's JavaAdapter, Mustang's JavaAdapter does not support implementing
multiple Java interfaces. Also, extending a super class is not allowed.
var x = { run: function() { print('hello') } }
var r = engine.getInterface(x, java.lang.Runnable);
r.run();
function run() {
print('hello');
}
// script function is wrapped automatically
var t = new java.lang.Thread(run);
t.start();
This feature works only if all the methods of the interface have the same signature or there is only one method in the interface. For interface with multiple
methods, script function receives the name of the method as first parameter.
function Invoker(obj) {
return new JSAdapter() {
__has__: function(name) {
return true;
},
__get__: function(name) {
return function() {
return obj.invoke(name, arguments);
}
}
}
}
var r = {
invoke: function(name, args) {
print(name + " called");
}
};
var x = new JavaAdapter(java.lang.Runnable, Invoker(r));
x.run(); // this calls r.invoke('run');
This scheme works even if interface methods don't have identical signature. But,
invoke method has to handle variable number of arguments passed as args array
(second argument). The first argument is the name of the interface method.