When a method is called on a SmallTalk object, the methods associated with that object's class and its superclasses are searched at runtime. If none of these classes implement a method of given name, the Smalltalk virtual machine calls doesNotUnderstand (see also Reflective Facilities in SmallTalk) method on the object. How about this facility for JavaScript? We can easily implement such a feature for JavaScript engine in Mustang. We can use JSAdapter feature.
function Wrapper(obj) {
return new JSAdapter() {
__has__ : function(name) {
// this object supports property or method of any name
return true;
},
__get__ : function(name) {
// check whether wrapped object supports given
// member (field or method).
if (name in obj) {
return obj[name];
} else if (typeof(obj["doesNotUnderstand"]) == 'function') {
// if object has 'doesNotUnderstand' method, then
// return a function that would call it
return function() {
return obj.doesNotUnderstand(name, arguments);
}
} else {
// unsupported
return undefined;
}
}
};
}
Code that uses could look like:
var v = {
a : 10,
toString: function() { return "I am v"; },
doesNotUnderstand: function(name) {
print(name + " called");
}
};
var x = Wrapper(v);
x.a; // This is same as v.a which is 10
x.toString(); // This is same as v.toString()
x.func(); // calls v.doesNotUnderstand("func")
JavaScript is lot similar to Self Programming Language. Similarities include:
// 'b' property is accessed by get accessor method
var d = { get b() { return "hello"; } }
alert(d.b); // calls function defined above
// explicit accessor method set for property "f"
d.__defineGetter__("f", function() { return 23 * 2} );
alert(d.f); // calls function set in __defineGetter__
But, Mustang includes Rhino JavaScript engine and therefore does not support getters and setters. But, we have added global constructor called JSAdapter. This is more flexible than the
getters and setters. JSAdapter accepts an object with specially named methods: __get__, __has__, __put__, __delete__
and __getIds__
var y = {
__get__ : function (name) { ... }
__has__ : function (name) { ... }
__put__ : function (name, value) {...}
__delete__ : function (name) { ... }
__getIds__ : function () { ... }
};
var x = new JSAdapter(y);
x.i; // calls y.__get__
i in x; // calls y.__has__
x.p = 10; // calls y.__put__
delete x.p; // calls y.__delete__
for (i in x) { print(i); } // calls y.__getIds__
Note that JSAdapter may also be created using Java anonymous class-like syntax:
var x = new JSAdapter() {
__get__ : function (name) { ... }
__has__ : function (name) { ... }
__put__ : function (name, value) {...}
__delete__ : function (name) { ... }
__getIds__ : function () { ... }
};
The caller/user of the adapter object is isolated from the fact that the property accesses/mutations/deletions are really calls to JavaScript methods on adaptee. Use cases include 'smart' properties, property access tracing/debugging, encaptulation with easy client access - in short JavaScript becomes more "Self" like. In fact, we have used JSAdapter feature in Object Query Language (OQL) implementation.
Note that Rhino already supports special properties like __proto__ (to set, get prototype), __parent__ (to set, get parent scope). We follow the same double underscore nameing convention here for special methods for JSAdapter.
It is Rhino 1.6R2. For historians :-)
function f() {
print('hello world');
}
// Thread constructor requires java.lang.Runnable
// You can pass script function 'f' as parameter
// script function is wrapped as interface implementor
// using java.lang.reflect.Proxy mechanism
var v = new java.lang.Thread(f);
v.start();
Java access in Rhino JavaScript engine can be used to get soft, weak references in scripts. For example, we may define the following script wrappers:
Object.prototype.softRef = function() {
return new java.lang.ref.SoftReference(this);
}
Object.prototype.weakRef = function() {
return new java.lang.ref.WeakReference(this);
}
Because we have added function properties to Object.prototype, we can create soft, weak references of any script object as shown below:
var x = "hello";
// create a SoftReference of script String 'hello'
x = x.softRef();
// may get null or "hello" depending on whether
// the SoftReference is cleared or not
x.get();
Java overloaded method calls are resolved are resolved at compile time (i.e., static resolution). But, when you call Java methods from JavaScript, the overload resolution occurs at runtime. JavaScript method overload resolution is explained in LiveConnect 3 document. In most cases, the expected method is called. Sometimes, you may want to force the choice and choose a particular method. For example, you may want to call a specific println() method of java.io.PrintStream class. For such scenarios, you can explicitly specify the method to be invoked.
Note that in JavaScript, object members are accessed in two forms:
var out = java.lang.System.out;
out.println("hello world"); // calls PrintStream.println(java.lang.Object)
out['println(double)'](13); // calls PrintStream.println(double)
The second member access form is useful in other scenarios as well. For example, when JavaScript reserved word is used as field/method name of an object:
// store System input stream in a variable
var s = java.lang.System.in; // This does not work!
You get the following error in jrunscript
// in is a keyword in JavaScript and therefore can not be used
// as field name, but the following works:
var s = java.lang.System["in"];
As I've been repeatedly highlighting, Mustang (Java SE 6) includes Rhino JavaScript engine. How do we write multithreaded scripts? JavaScript engine allows Java method calls. So, we can use that to create script wrappers for Java platform classes as shown below:
// creates a java.lang.Runnable wrapping given script function.
function runnable(func) {
return new java.lang.Runnable() {
run: function() { func(); }
}
}
// add 'thread' function property to Function prototype.
Function.prototype.thread = function() {
var t = new java.lang.Thread(runnable(this));
t.start();
return t;
}
After including above code (using load function in jrunscript), we can easily create threads in script:
function myFunc() {
//... code here...
}
// start 2 threads with myFunc as starting function
myFunc.thread();
myFunc.thread();
But, what about mutual exclusion/communication/co-operation between threads? You may want locks, condition variables etc. Well, you may write few script wrappers using java.util.concurrent
API as shown below:
// creates a ReentrantLock
function lock() {
return new java.util.concurrent.locks.ReentrantLock();
}
// runs given function after acquiring given lock and releases the lock
// after the function is finished. (in effect the script function is
// 'synchronized' in Java sense
Function.prototype.sync = function(lock) {
lock.lock();
try {
this.call();
} finally {
lock.unlock();
}
}
The caller of the above code would look like:
function myFunc() {
// code here
}
// create a lock
var lk = lock();
// run myFunc in 'synchronized' way
// no two threads can run myFunc concurrently.
myFunc.sync(lk);
Note that I've not handled script functions with arguments. For eg., you may want to start a thread with a function that accepts arguments. As usual, that is left as an exercise to the reader :-)
Mustang (Java SE 6) includes JavaScript engine. How can we execute JavaScript functions asynchronously?
// This function accepts a script function and returns an object that implements
// java.util.concurrent.Callable
function callable(func) {
return new java.util.concurrent.Callable() {
call: function() { return func(); }
}
}
// create an Executor
// for 'background' executions.
var theExecutor = java.util.concurrent.Executors.newSingleThreadExecutor();
// future function executes given function asychronously
// returns a java.util.concurrent.FutureTask as result.
// calling get method on result method would potentially
// block the caller and make it wait for completion.
function future(func) {
return theExecutor.submit(callable(func));
}
You can save the above script code in a file (say, "future.js") and load it in jrunscript prompt and play with it. Sample jrunscript session is as follows:
js> load('future.js')
js> function f() { return 344 * 22; }
js> x = future(f)
js> x.get()
If you don't want to add a global function (future), you may do:
function callable(func) {
return new java.util.concurrent.Callable() {
call: function() { return func(); }
}
}
var theExecutor = java.util.concurrent.Executors.newSingleThreadExecutor();
Function.prototype.future = function() {
return theExecutor.submit(callable(this));
}
With above code, the caller can use the following:
function timeConsumingFunc() {
// length computation here...
}
var result = timeConsumingFunc.future();
// when you want result value, you can say
y = result.get();
// the above get call would block if asynchronous computation is not completed.
// or else you will get result immediately...
Note that I've not handled function arguments for future functions. That is left as exercise to the reader :-) The JavaScript object XMLHttpRequest of AJAX fame is just a special case of running a script function asynchronously. With above scheme, you can run any script function asynchronously....
As you may already know, Mustang (Java SE 6) includes scripting framework (JSR 223 subset) and a reference JavaScript engine based on Rhino. Initially, we had used Rhino version 1.5R5 in Mustang. Then, during build 53, we switched to Rhino 1.6R1. After we switched to 1.6R1, Mozilla has released Rhino 1.6R2. We are hoping to migrate to Rhino 1.6R2 in a future build of Mustang.
Although Mustang includes Rhino 1.6R1 (and probably will change to Rhino 1.6R2 before FCS), we are not including E4X (ECMAScript for XML) support in it. We had removed this feature primarily because of footprint consideration. Note that E4X Rhino implementation uses Apache XMLBeans (xbean.jar).
If you attempt to use E4X with Mustang (for eg. with jrunscript), you'll get error as shown below:
$ jrunscript
js> var x = <html><body>hello</body></html>
script error: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "XML" is not defined. (
var v = new java.lang.Runnable() {
run: function() { print('hello'); }
}
v.run();
with Mustang as well. Under the hood, javax.script.Invocable.getInterface
is used to implement this feature.
If jhat throws java.io.IOException: Unrecognized magic number, you may want to check whether you passed a proper HPROF binary format heap dump file to jhat or not. If you use hprof to generate your heap dump, do not forget to use format:b option. With this option, hprof generates heap dump in binary format. Without this option, hprof dumps heap in ascii format (which is format:a option). i.e., by default hprof dumps heap in text format. jhat can read only the binary format heap dump.
Your command would look like:
java -Xrunhprof:format=b ToBeProfiledClass
java -agentlib:hprof=format=b TobeProfiledClass // JDK 5.0 or above
Bill Foote has announced this!. Heap Analysis Tool (HAT) is now historical -- so is the HAT java.net project. jhat that is included in Mustang replaces HAT.
java -jar jhat.jar [<options for jhat>] <YourHeapDumpFile>
Happy hacking jhat!
Mustang's jhat has been reported to throw OutOfMemoryError (OOM) on large heap dump files. This is a known issue and we are making some improvements to reduce memory requirement. Having said that jhat requires larger memory because it reads entire heap dump and forms in-memory object model. Hence, please use -J-Xmx512MB (or even -J-Xmx1G!) with jhat.
Short answer: Yes. Mustang's jhat works against heap dumps produced from earlier JDKs as well. It just works -- because it uses the same HPROF binary file format as used by hprof profiler and jmap tool. jmap tool can dump from live Java processes and Java core dumps. This feature has been backported to 1.4.2_09 (solaris only) and 5.0 update 5 (solaris and linux only) releases. hprof produces heap dump with allocation site trace information in the same format -- you need to use format=b option with hprof. As you'd probably know, hprof prodifier has been existing in JDK for quite some time.
And yes, HPROF binary file format is platform independent. Therefore jhat on any platform can parse and view heap dumps produced from any platform
Java permanent generation holds holds data needed by the virtual machine to describe objects that do not have an equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation.
Let us see how OQL to analyze/understand Java permanent generation. Before proceeding, generate a sample heap dump. I created a sample heap dump from a Tomcat webserver instance on Solaris/sparc using jmap.
Let us ask few questions and try to answer those by OQL:
select count(heap.classes())
We use the classes method of heap object and used count built-in
to count the result of the same. The output was: 1950
select count(heap.classes(), 'it.loader == null')
Note that we use a filter condition "it.loader == null". The output
for this query was 1327. i.e., out of 1950 classes, 1327 are really bootstrap
classes. Note that once loaded bootstrap classes are never unloaded (unlike
other classes which could be unloaded if the classloader is dead. In other words,
bootstrap loader is always alive)
select { loader: cl, count: cl.classes.elementCount }
from instanceof java.lang.ClassLoader cl
Here we select multiple values for each loader (loader and count of
classes) and so we use JavaScript object literal. instanceof
keyword is used so that objects of all subclasses of java.lang.ClassLoader
are selected. java.lang.ClassLoader has a private field of name 'classes'
and of type java.util.Vector. This holds the classes loaded by it. We access
the vector from each loader and print the count from it (elementCount as you'd
expect is a private field of java.util.Vector class).
select { loader: cl, parent: cl.parent }
from instanceof java.lang.ClassLoader cl
As you'd have guessed, 'parent' is private field of java.lang.ClassLoader
that points to the parent loader.
select map(heap.objects('java.lang.ClassLoader'),
function(it) {
var res='';
while (it != null) {
res += toHtml(it) + "->";
it = it.parent;
}
res += "null";
return res + "<br>";
})
Here we use map built-in to call a function (defined inline) on each
class loader instance. The function returns a HTML string by walking all
child-parent chain by a while-loop.
select map(sort(map(heap.objects('java.lang.ClassLoader'),
'{loader: it, count: it.classes.elementCount }'), 'lhs.count < rhs.count'),
'toHtml(it) + "<br>"')
Explanation of the above query is left as exercise to reader :-)
select { loader: cl,
classes: filter(map(cl.classes.elementData, 'it'), 'it != null') }
from instanceof java.lang.ClassLoader cl
As mentioned earlier, classes Vector has elementData array that holds
the loaded classes. We filter null entries in it by filter built-in (note
that a Vector can have more space allocated for possible future expansion.
These slots will have nulls)
select unique(map(heap.objects('java.lang.ClassLoader'), 'classof(it)'))
Here we use unique built-in function to find unique classes of java.lang.ClassLoader
instances.
select count(heap.objects('sun.reflect.DelegatingClassLoader'))
Output for my Tomcat instance was 52. So, 52 classes were generated for reflection
speedup.
select { loader: cl, liveness: heap.livepaths(cl) }
from instanceof java.lang.ClassLoader cl
We have seen few OQL queries. One thing we missed: the output for these queries! The output from jhat will have hyperlinks. You can navigate Java objects,classes from query output objects easily. If you have still not downloaded Mustang, please do it now and play with jhat and do let us know your suggestions/comments!