« September 2006 »
SunMonTueWedThuFriSat
1
2
5
8
10
13
14
15
17
19
20
21
23
25
27
29
    
       
Today
XML

Blog::Navigation

GetJava Download Button
Get the Source
Personal Blog

Blog::Referers

Today's Page Hits: 164

Powered by Roller Weblogger.
« Previous month (Aug 2006) | Main | Next month (Oct 2006) »
20061031 Tuesday October 31, 2006

HotSpot source: classloading

In the past, I wrote about Java class loading in these entries:

Now, if you have downloaded JDK source from http://jdk6.dev.java.net and you want to understand classloading in HotSpot JVM, you may want to look at these files: You may want to refer to Dynamic Class Loading in the Java Virtual Machine as well. A good to way to learn classloading is to trace JVM using DTrace on Solaris OS. There is a hotspot::class-loaded probe. For example, on class-loaded probes, you may call jstack action to print stack trace whenever a java class is loaded (or unloaded). If you are reading (and planning to hack!) HotSpot sources, you may want to try these as well:
  1. HotSpot is a C++ program. You can try what is described in "Using DTrace to Profile and Debug A C++ Program"
  2. Insert your own USDT probes in HotSpot source and recompile! [refer: User-land tracing gets better and better]

Note that aforementioned DTrace tricks can be used to trace any subsystem of HotSpot - not neccesarily classloading!



( Oct 31 2006, 05:21:37 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061030 Monday October 30, 2006

HotSpot source: command line arguments

You may have read Joseph D. Mocker's excellent collection of JVM Options - a compilation of all the JVM options for various versions of the JVM on primarily SPARC/Solaris Platform. If you have downloaded JDK source from http://jdk6.dev.java.net, you may want to look at these files:

Please note that I am not suggesting this for tuning JVM on deployment - you may want to read No Tuning Required: Java SE Out-of-Box Vs. Tuned Performance.

You may be curious to know what options are available in product, debug modes of the HotSpot JVM. In particular, you may want to see what diagnostic/debug options which may help in debugging/troubleshooting.

These files have HotSpot command line flags (specified by -XX) and argument parsing code (in arguments.cpp). Also, you may want to look at Java launcher source at [some options by "java" are implemented by launcher sources (eg. -client, -server and -J-XXX) and many other options are implemented by hotspot JVM sources]

The launcher sources help in better understanding of JNI Invocation API as well.



( Oct 30 2006, 12:59:52 PM IST ) Permalink Comments [6] del.icio.us | furl | simpy | slashdot | technorati | digg

20061028 Saturday October 28, 2006

My son's Windows "magic"!

This morning my son (3 year old) was watching some video on my PC. He kept pressing keyword - suddenly the screen started looking like this...


I couldn't find how he managed to change (some) setting. Re-starting Windows didn't help. Kannan Balasubramanian helped me. Thanks Kannan! (Sustaining saves the day again!).

Steps to fix "tilted Windows":

For some reason, while Kannan was able to make it "Normal" and immediately view the change, I had to re-boot! Anyway, now it is "Normal" :-)



( Oct 28 2006, 03:46:44 PM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

20061026 Thursday October 26, 2006

HotSpot source: Where to begin?

Hope you had read my previous post on the prerequisites for reading HotSpot sources. Please note that I am not an expert in HotSpot. I'll post "random tips" which may be useful to you :-)

You may want to read Mikhail Dmitriev's thesis - Chapter 7, Section 7.1. In particular, section 7.1.2.5 titled "Internal Data Structures". This section is a very nice (dated, but still useful) description of HotSpot data structures. Of course, you can read the entire thesis if you are interested in the topic of the thesis - it is an interesting thesis to read!. While reading those sections, you may want to look at the header [.hpp] files under $JDK/hotspot/src/share/vm/oops/ directory.

Most files in this directory have the word "oop" in the name. The "oop" here stands for "ordinary object pointer". What is "ordinary"? May be, this explains!



( Oct 26 2006, 06:33:16 PM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

20061024 Tuesday October 24, 2006

So you want to read HotSpot source?

I joined Sun Microsystems as a sustaining engineer - so I had to read code more often than writing new code (which is true in general for many of us!). I like to read great source code and learn from it. Sun's HotSpot Virtual Machine is one such gold mine!

May be, you've already downloaded the source bundles from http://jdk6.dev.java.net. Or you may be waiting for the "open source" announcement. In any case, if you are planning to read HotSpot source, you may want to know the prerequisites for reading HotSpot Java Virtual Machine sources. If so, read ahead ...

  1. Knowlegdge of C and C++ - You need not know each and every corner of C++ (for example it is okay to not know what explicit or mutable means nor you need to know "partial specialization of templates" etc.) - a decent level of understanding is enough :-)
  2. Knowledge of assembly language (of SPARC or X86 or AMD64) - no assembler is used. In fact, assembler is actually a C++ class - but you need assembler level understanding.
  3. Knowledge of Java

In addition to programming/assembly language(s), you may want to read the Java Virtual Machine Specification (2'nd Edition). To understand Java Virtual Machine Specification, I've used Java assembler(s) - working at the level of Java bytecode helps a lot. I used Jasmin Assembler.

You may also use a byte code engineering libraries such as

In addition, it is better to view/analyze existing .class files [may be, you compiled your .java files to create those files]. For that purpose, you can use .class viewers such as

I like to generate hypertext for source base and browse it. Tools that I used (and still use!) are:



( Oct 24 2006, 05:50:36 PM IST ) Permalink Comments [5] del.icio.us | furl | simpy | slashdot | technorati | digg

20061022 Sunday October 22, 2006

JRuby JSR-223 engine uses version 0.9.1

JRuby version 0.9.1 has been released. Updated jsr-223 JRuby script engine at scripting.dev.java.net to use version 0.9.1. With JRuby 0.9.1, there is new syntax for accesing Java classes.



( Oct 22 2006, 11:16:32 AM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061018 Wednesday October 18, 2006

Higher order messages in Groovy

I came to know about higher order messages (HOM) - messages that take another message as argument - from here: Higher Order Messaging in Ruby. Then, I read this paper: Higher Order Messaging

To implement higher-order messages with Ruby, two things are used

Implementing higher-order messages with Groovy

In a blog entry, I mentioned about doesNotUnderstand in Groovy. But, there are no open classes in Groovy. But, Groovy supports class categories - a facility by which we can "add" methods to existing classes (within a specific "use" context).


// A class that forwards any message 
// to it to the objects of the list 
// and returns the result list
class Do {
  def list
  Do(l) { list = l }

  def invokeMethod(String name, args) {
     list.collect { it.invokeMethod(name, args) }
  }
}

// A class that filters the objects of the list
// using the message invoked on it
class Where {
  def list
  Where(l) { list = l }

  def invokeMethod(String name, args) {
     list.findAll { it.invokeMethod(name, args) }
  }
}

// A class that sorts the objects of a list
// using the message invoked on it
class Order {
  def list
  Order(l) { list = l }
  
  def invokeMethod(String name, args) {
     list.sort { it.invokeMethod(name, args) }
  }
}

// A class category that "adds" methods to List
// class
class ListCategory {
   static def getDo(List list) {
     return new Do(list);
   }
   static def getWhere(List list) {
       new Where(list);
   }
   static def getOrderBy(List list) {
       new Order(list);
   }
}

// we use our List category
use(ListCategory) {
   strings = ["JavaScript", "JRuby", "Java", "Groovy", "BeanShell"]

   // find all strings that start with "J"
   println strings.where.startsWith("J")

   // make a list of upper case strings
   println strings.do.toUpperCase()

   // sort the strings by length
   println strings.orderBy.length()
}

As you can see, with higher-order messages, we avoid closures in the method call-chain - making the method chain easily readable.



( Oct 18 2006, 08:18:17 PM IST ) Permalink Comments [1] del.icio.us | furl | simpy | slashdot | technorati | digg

20061016 Monday October 16, 2006

A convention for circular reference handling with JSON

Update: I was not aware of JSPON - JavaScript Persistent Object Notation (JSPON) - which addresses the problem below (I wrote the text below before my knowledge of JSPON!). Thanks to Andres Almiray for pointing me about that.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. JSON can be used as replacement for XML (AJAX without the "X" for XML).

But, JSON does not have syntax for circular references - most JSON libraries expect the data structure to-be-serialized to have no cycles. In XML, typically special attributes such as ID and IDREF (or HREF in HTML) are used to create links between elements. (see also XML:id).

Here is a proposal for simple conventions to handle circular references. We can use few special properties with name starting with a "$". "$id" property uniquely identifies a JSON object within a JSON document. Such objects can be referred elsewhere by "$idref". In addition, we may "reserve" all properties starting with a letter "$".

Few examples:

I've checked-in Java classes to serialize/de-serialize JSON with the above "extensions" at http://scripting.dev.java.net - the code is here

There is one issue with this scheme - with JavaScript we can deserialize JSON with "$id" and "$idref" etc. and resolve references, it is difficult to serialize. There is IdentityHashMap or equivalent in (pure) JavaScript [did I miss any such cool-trick?]. To detect whether we have serialized an object already or not [so that we can generate $idref instead of serializing it again], we may have to keep a list of visited objects (i.e, JS array) and walk through that list everytime and so the implementation would be slow for bigger object graphs. Note that this issue does not arise with Rhino implementation - because we can use IdentityHashMap API with Rhino.



( Oct 16 2006, 07:16:57 PM IST ) Permalink Comments [1] del.icio.us | furl | simpy | slashdot | technorati | digg

20061012 Thursday October 12, 2006

No reserved words!

Came across Rémi Forax's blog entry titled Languages Evolution: introduction of new keywords. He proposes the idea of contextual keywords. i.e., keywords can be used as identifier in other places - which helps in introducing new keywords in a mature language - without breaking existing programs. I've renamed "enum" during JDK 5.0. I've seen others renaming of "assert" during 1.4. So, how about avoiding renaming - but, still have new (context sensitive) keywords....

Now, that reminds me of PL/I - no reserved words! PL/I's "keywords" are recognized only in context, and may otherwise be used as identifier elsewhere. I've never programmed in PL/I. My friend (who used to be a mainframe programmer) used to "scare" us by showing programs such as this one.

Interestingly, Smalltalk does not have reserved words at all. Sometimes it is said that Smalltalk has only 5 reserved words:

  1. nil (null)
  2. true
  3. false
  4. self (this)
  5. super
But, it is possible to create methods even with these names!



( Oct 12 2006, 07:53:20 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061011 Wednesday October 11, 2006

JSR-223 script engine for JUEL

Just added JSR-223 script engine for JUEL - Java Unified Expression Language - which is an implementation of the Unified Expression Language (EL), specified as a part of the JSP 2.1 standard (JSR-245).

EL started as part of JSTL. Then, the EL moved into the JSP 2.0 spec. Now, although EL is part of JSP 2.1, the EL has been separated into package javax.el and all dependencies to the core JSP classes have been removed. So, the EL can be used by non-JSP applications as well. With this new JSR-223 script engine, it is possible to use EL through javax.script API. As usual, the script engine sources and binaries are available at scripting.dev.java.net.

Sample Program


import javax.script.*;

public class Main {
  public static void main(String[] a) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine e = manager.getEngineByName("juel");
    // expose PI
    e.put("PI", Math.PI);

    // prints false
    System.out.println(e.eval("${222 < 32}"));

    // context is pre-defined variable of type
    // javax.script.ScriptContext
    System.out.println(e.eval("${context}")); 

    // print "hello world"
    e.eval("${out:print('hello world')}");

    // lang:import function imports all static methods
    // of the given class.

    // import all static functions in java.lang.Math
    e.eval("${lang:import(context, 'Math', 'java.lang.Math')}");

    System.out.println();
    System.out.println(e.eval("${Math:sin(3.1415/2)}"));
  }
}

Compiling the above code is straightforward. While running it, you need to put the JUEL jar and the jsr-223 script engine jar in the CLASSPATH. For example:

D:\scripting\engines\juel\bin>java -cp D:\scripting\engines\juel\lib\juel-2.1.0-rc2.jar;D:\scripting\engines\juel\build\juel-engine.jar;. Main
false
javax.script.SimpleScriptContext@10b9d04
hello world
0.999999998926914

If you are looking for a lightweight, expression-only language (rather than a full-blown scripting language), you have (atleast) 4 different options:

  1. JEP (Java Math Expression Parser)
  2. JEXL (Java Expression Language)
  3. JUEP (Java Unified Expression Language)
  4. OGNL (Object Graph Navigation Language)



( Oct 11 2006, 01:33:49 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061009 Monday October 09, 2006

Calling overriden superclass method on subclass instance

With OO languages, we can call the superclass version of a overriden method - but, only within the subclass methods. But, how about calling a overriden superclass method from outside the subclass?

You may think you could perhaps use reflection and call specific superclass method on a subclass instance. But, when you call a method by Method.invoke (in Java) or send (in Ruby) perform: (in Smalltalk) the subclass method is called. You may want to refer to the javadoc for Method.invoke which clearly states:

If the underlying method is an instance method, it is invoked using dynamic method lookup as documented in The Java Language Specification, Second Edition, section 15.12.4.4; in particular, overriding based on the runtime type of the target object will occur.

Java Example

import java.lang.reflect.Method;

class Person {
  public void greet() {
    System.out.println("Person's greet");
  }
}

class Employee extends Person {
  public void greet() {
    System.out.println("Employee's greet");
  }
}

class Main {
  public static void main(String[] args) 
        throws Exception {
    // get the method object from Person class.
    Method g = Person.class.getMethod("greet",
                     new Class[0]);

    Employee e = new Employee();
    // When "g" is invoked on an "Employee" object, 
    // the "Employee.greet" method is called.
    g.invoke(e, null);
  }
}

Now, back to same question at the start. How do we call Person.greet on an employee object? It turns out that is possible with Smalltalk. If you don't know Smalltalk, you may skip the next section and goto Ruby section -- knowing that it is possible with Smalltalk!

Smalltalk Example

I tried the following with Squeak 3.8.


"Assume that Person and Employee are classes"
"greet methods of Person and Employee are below"

greet
  Transcript show: 'Person''s hello'; cr.

greet
  Transcript show: 'Employee's hello'; cr.

For completeness, here is the "file-out" of Person and Employee classes:

Object subclass: #Person
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MyTest'!

!Person methodsFor: 'as yet unclassified' stamp: 'AS 10/9/2006 07:11'!
greet
  Transcript show: 'Person''s Hello'; cr.! !

Person subclass: #Employee
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MyTest'!

!Employee methodsFor: 'as yet unclassified' stamp: 'AS 10/9/2006 07:12'!
greet
  Transcript show: 'Employee''s Hello'; cr.! !

With the above code, you can do something like the following (in a workspace):

(Employee new) perform: #greet withArguments: (Array new:0) inSuperclass: Person.

So, perform:withArguments:inSuperclass: lets us call any superclass method on a subclass instance (even if that method is overriden in subclass).

Ruby Example

It is possible to do the above with Ruby too. In Ruby, method objects carry the receiver object. It is possible to disassociate the receiver by unbind method and then re-associate the unbound method with another object using bind method.

It is possible to

Example:

class Person 
  def greet
    puts "Person's Hello"
  end
end

class Employee < Person
  def greet
    puts "Employee's Hello"
  end
end

e = Employee.new
p = Person.new
# get greet method from Person instance
m = p.method(:greet)

# unbind greet from "p" and rebind it "e"
# and then call. So, you are calling 
# Person.greet on an Employee instance.

um = m.unbind()
um.bind(e).call()

Note for the JRuby users: With JRuby 0.9.0 version, the above "bind" call does not work. You get en error that looks like:
org.jruby.exceptions.RaiseException: bind argument must be an instance of Person

When I looked at the JRuby 0.9.0 source (RubyUnboundMethod.java - bind method), it had this comment:


// FIX replace type() == ... with isInstanceOf(...)

It turns out that this issue ( JRUBY-103) has been fixed in JRuby 0.9.1.

Why Java does not allow this?

Calling any method on any object!

Smalltalk allows us to call any method on any object! For example, you can get method (CompiledMethod) object from one class and call that on an object of unrelated (by inheritance relation) class. For example, let us assume SomeClass is defined as follows (file-out)


Object subclass: #SomeClass
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'MyTest'!

!SomeClass methodsFor: 'as yet unclassified' stamp: 'AS 10/9/2006 10:14'!
someMethod
  Transcript show: 'someMethod'; cr.! !

We can call the SomeClass.someMethod method on say a Person instance: (Person is unrelated to SomeClass by inheriatance)

(SomeClass methodDict at: #someMethod) valueWithReceiver: (Person new) arguments: nil



( Oct 09 2006, 11:18:18 AM IST ) Permalink Comments [3] del.icio.us | furl | simpy | slashdot | technorati | digg

20061007 Saturday October 07, 2006

Java Integration: BeanShell and Jython

When using scripting and dynamically typed languages with the Java platform, you would want to take advantage of the Java platform API. In this blog entry, we will see how to use Java API from BeanShell and Jython.

I used the following versions to test my scripts:

  • BeanShell version 2.0b5.
  • Jython 2.1.
I used all these through JSR-223 script engines for these languages.

Feature BeanShell Jython
Importing Java packages Same as Java!

import java.awt.*;
import javax.swing.*;

By default, BeanShell imports java.lang, java.util, java.io, java.net, java.awt, java.awt.event, javax.swing, javax.swing.event packages.

There is also (an experimental) import entire classpath option - which may be useful in interactive use.


import *


from java.util import *

Importing specific class(es) Same as Java!

import javax.swing.JFrame;

By default, BeanShell imports bsh.EvalError and bsh.Interpreter classes.

from javax.swing import JFrame

Type alias (Referring Java class with different name) It does not seem possible. You can assign class name to a variable - resulting variable is of type "ClassIdentifier". But, it does not appear that you can treat class identifier as though it is a class.

JF = javax.swing.JFrame
// prints "Class Identifier: javax.swing.JFrame"
print(JF)


from javax.swing import JFrame
JF = JFrame
print(JF)
Creating a Java object Same as Java!

f = new JFrame("hello");


from javax.swing import JFrame

# treat class name as a function name
# just call as though it is a function.

f = JFrame("hello")

Calling instance methods Same as Java!

f = new javax.swing.JFrame("hello");
f.setSize(100, 100);
f.setVisible(true);


from javax.swing import JFrame
f = JFrame("hello")
f.setSize(100, 100)
f.setVisible(1)

Calling static methods Same as Java!

java.lang.System.exit(0)


from java.lang import System
System.exit(0)

JavaBean support

f = new JFrame("hello");
f.setSize(100, 100);
// calls setVisible
f.visible = true;
// calls getTitle for "title" access
print(f.title);


from javax.swing import JFrame
f = JFrame("hello")
f.setSize(100, 100)
# calls setVisible
f.visible = 1;
# calls getTitle for "title" access
print(f.title);

instanceof check Same as Java!

f = new JFrame("hello");
// prints true
print(f instanceof JFrame);


from javax.swing import JFrame
f = JFrame("hello")
# prints "1"
print(isinstance(f, JFrame))

Java overloaded resolution BeanShell automatically selects the overload method to call (based on java overload resolution algorithm) using argument types. It seems we need to use reflection to force selection of a particular method. There is automatic selection of the overload variant based on arguments. But if there are two methods, say void func(int x) and void func(byte x), to call the second method you can write:

from java.lang import Byte
func(Byte(10))

Another example:

from java.lang import Double
from java.lang import System

System.out.println(Double(33.33))

Handling Java exceptions Same as Java!

try {
  ioFunc();
} catch (IOException e) {
  print("caught it: " + e);
} catch (EOFException e1) {
  print("caught it: " + e1);
}

It is possible to omit the exception type in catch clause:


try {
  ioFunc();
} catch(e) {
  e.printStackTrace();
} 


from java.io import *
import sys

try:
  f = FileInputStream("myfile")
  c = f.read()
except FileNotFoundException:
  print(sys.exc_info())
except IOException:
  print(sys.exc_info())


Creating Java Arrays Same as Java!

s = new String[2];
print(s);

"jarray" module is used to create Java arrays. The jarray module exports two functions: array(sequence, type) and zeros(length, type). array will create a new array of the same length as the input sequence and will populate it with the values in sequence. zeros will create a new array of the given length filled with zeros (or null's if appropriate).


from java.lang import String
import jarray

s = jarray.zeros(2, String)
print(s)

Another example:

from java.lang import String
import jarray

s = jarray.array(["hello", "world"], String)
print(s)

Accessing Java Arrays Same as Java! usual [] and .length are supported.

s = new String[2];
s[0] = "hello";
s[1] = "world";
print(s.length);
print(s[0]);
print(s[1]);

Similar to Java [] operator for access - but array length is accessed by "len" function.

from java.lang import String
import jarray

s = jarray.zeros(2, String)
s[0] = "hello";
s[1] = "world";
print(len(s))
print(s[0])
print(s[1])

Implementing a Java interface Same as Java! (except loose typing can be used)

r = new Runnable() {
   run() {
     print("I'm runnable");
   }
};

print(r instanceof Runnable);
r.run();

class MyRunnable implements Runnable {
  public void run() {
    print("hello world");
  }
}

new MyRunnable().run();


from java.lang import Runnable
from java.lang import Thread

# just extend like a Python 
# super class
class MyRunnable(Runnable):
    def run(self):
       print("run called")

t = Thread(MyRunnable())
t.start()

When I tried this example, I got this error:
jython> Exception in thread "Thread-0" Traceback (innermost last):
(no code object) at line 0
AttributeError: abstract method "run" not implemented

But, this seems to be an issue with jsr-223 script engine for Jython. If the above is run with Jython 2.1's jython runner script, it works as expected. I've to fix this in jsr-223 script engine.

This issue has been fixed. Please download the lastest binary and source.

Implementing multiple interfaces Same as Java! (except that loose typing may be used in few places)

import java.util.concurrent.Callable;

class MyClass implements Runnable, Callable {
  public void run() {
     print("run called");
  }

  public call() {
     print("call called");
  }
}

m = new MyClass();
print(m instanceof Runnable);
print(m instanceof Callable);
m.run();
m.call();

Jython supports multiple inheritance. Treat each Java interface to be implemented as a "superclass".

from java.util.concurrent import Callable
from java.lang import Runnable

class MyClass(Runnable, Callable):
  def run(self):
    print("run called")
  def call(self):
    print("call called")

m = MyClass()
# prints 1
print(isinstance(m, Runnable))
# prints 1
print(isinstance(m, Callable))
m.run()
m.call()

Extending a Java class Same as Java! (except that loose typing may be used)

class MyHashtable extends Hashtable {
  // Override Hashtable.get method
  public get(key) {
    print("get called");
    // call super class method
    return super.get(key);
  }
}

m = new MyHashtable();
m.put("hello", "world");
print(m.get("hello"));


from javax.swing import JFrame

class MyFrame(JFrame):
  # override method
  def setVisible(self, flag):
    print("set visible")
    # call super class method
    JFrame.setVisible(self, flag)
 
f = MyFrame("hello")
print(isinstance(f, JFrame))
f.setVisible(1)

The above overriding of setVisible works with Jython 2.1 but not with jsr-223 script engine for it. As I mentioned earlier in interface impl. item, this is an issue with the jsr-223 engine for Jython.

This issue has been fixed. Please download the lastest binary and source.

References



( Oct 07 2006, 02:00:20 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061006 Friday October 06, 2006

Java Integration: JavaScript, Groovy and JRuby

When using scripting and dynamically typed languages with Java platform, you would want to take advantage of Java platform API. We know that there is Java API for (nearly) everything under the "Sun" ;-). In this blog entry, we will see how to access Java from JavaScript, Groovy and JRuby.

Note: I used the following versions to test my scripts:

  • Rhino 1.6R2 based JavaScript engine that is bundled with JDK 6.
  • Groovy 1.0 JSR-06.
  • JRuby 0.9.0.
I used all these through JSR-223 script engines for these languages.

Updates:

  • Jochen "blackdrag" Theodorou notes that the Groovy overload resolution can be forced to select a specific method in future - check out Groovy 1.0.
  • Nick Sieger, Thomas E Enebo and Charles Oliver Nutter note that JRuby's Java integration is improving - check out JRuby 0.9.1+.

Feature JavaScript Groovy JRuby
Importing Java packages importPackage function.

Examples:

importPackage(java.awt);
importPackage(javax.swing);

Rhino has a built-in variable by the name Packages. You have to use Package.javax.swing to refer to javax.swing package. But, "java" is a short-cut for "Packages.java". In JDK 6, short-cuts have been added to all commonly used package prefixes as well (like javax, org, com, net etc.). If you are using Rhino standalone, you can eval the following:

var javax = Packages.javax;
var com = Packages.com;
var net = Packages.net;
var edu = Packages.edu;

Note: java.lang package is not automatically imported in Java (that would result conflicts - example: JavaScript Object vs. Java's java.lang.Object).

If you are importing too many packages and classes, you may be polluting the global namespace. You can avoid that by using JavaImporter function.


var guiPkgs = new JavaImporter(
     java.awt, java.awt.event, javax.swing);

with (guiPkgs) {
   // here you can access all classes
   // in java.awt, java.awt.event and
   // javax.swing classes by simple names
}

// outside the above "with" statement
// you can't use simple class names.

Same as Java!

import java.awt.*;
import javax.swing.*;

By default, Groovy imports java.lang, java.util, java.io, java.net, groovy.lang, groovy.util packages.
You can not import all classes of a package in top-level scope. Instead, you have to import within a module.

module MyJava
  include_package 'java.util'
end

$o = MyJava::Hashtable.new
puts $o

Importing specific class(es) importClass function.

importClass(java.util.HashMap);
importClass(javax.swing.JFrame);

Same as Java!

import javax.swing.JFrame;

By default, Groovy imports java.math.BigInteger and java.math.BigDecimal classes.
include_class(classname_or_list_of_classnames) {|package, name| optional_renaming_block }

require 'java'

include_class('javax.swing.JFrame')
include_class ["JFrame"].map {
 |e| "javax.swing." + e
}

Note: The Java import packages/class is improving. See also:
Type alias (Referring Java class with different name)

var Format = java.text.SimpleTextFormat;
// use "Format" as class name below


import java.text.SimpleTextFormat
 as Format;
// use "Format" as class name below

include_class(classname_or_list_of_classnames) { |package, name| optional_renaming_block }

require 'java'

include_class('java.lang.String') {
 |package,name| "J#{name}" 
}

# after this you can use "JString"

Creating a Java object

importClass(javax.swing.JFrame);
var f = new JFrame("hello");


import javax.swing.JFrame;
f = new JFrame("hello");


include_class('javax.swing.JFrame');
f = JFrame.new('hello');

Calling instance methods

var f = new javax.swing.JFrame("hello");
f.setSize(100, 100);
f.setVisible(true);


f = new javax.swing.JFrame("hello");
f.setSize(100, 100);
f.setVisible(true);


include_class('javax.swing.JFrame');
f = JFrame.new('hello');
f.setSize(100, 100);
f.setVisible(true);

Calling static methods java.lang.System.exit(0) System.exit(0) include_class('java.lang.System'); System.exit(0)
JavaBean support

f = new javax.swing.JFrame("hello");
f.setSize(100, 100);
// calls setVisible
f.visible = true;
// calls getTitle for "title" access
println(f.title);


f = new javax.swing.JFrame("hello");
f.setSize(100, 100);
// calls setVisible
f.visible = true;
// calls getTitle
println(f.title);


require 'java';
include_class('javax.swing.JFrame');
f = JFrame.new("hello");
# calls setVisible
f.visible = true;
# calls getTitle
puts f.title

instanceof check

importClass(javax.swing.JFrame);
var f = new JFrame("hello");
// prints true
println(f instanceof JFrame);


import javax.swing.JFrame;
f = new JFrame("hello");
// prints true
println(f instanceof JFrame);


require 'java';
include_class('javax.swing.JFrame');
f = JFrame.new("hello");
# prints true
puts f.kind_of?(JFrame)

Java overloaded resolution

In most cases, Rhino selects proper overload variant automatically. But, if you want to force selection of a particular method, you can use the following:


var out = java.lang.System.out;
out["println(double)"](3.14);

Essentially, we specify full singature of the method as a string. Note that JavaScript objects are associative arrays - it is always possible to use property/method name within square bracket (as a string). This is same as ".field" or ".method" syntax.

Groovy selects the "most appropriate" overload automatically (see also Mutlimethods in Groovy). I am not sure if there is any way to force a particular overload to be called.. Update: Jochen "blackdrag" Theodorou notes that the overload resolution will be improved in Groovy 1.0. For now, you can use java reflection API directly.

require 'java';
include_class('java.lang.System');

System.out.println("hello");

# the following don't print numbers
# I am not sure how to resolve to
# a particular overload variant

# System.out.println(33.33);
# System.out.println(2)

I think it should be possible to use low-level reflection of JRuby - may be I can do this little less verbose than what is below??


require 'java';

cl = Java::JavaClass.for_name(
   "java.io.PrintStream");

m = cl.java_method(:println, :double)
include_class('java.lang.System')
include_class('java.lang.Double')
d = Double.new(3.141596)

m.invoke(System.out.java_object,
     d.java_object)
Handling Java exceptions

var Stream = java.io.FileInputStream
try {
  s = new Stream("non_existent");
} catch (e) {
  // handle FileNotFoundException
}

It is possible to have multiple catch classes like in Java. JavaScript error objects have "javaException" property - which points to the actual underlying Java exception (if error was thrown due to a Java exception). You can do instanceof check on the underlying java exception.


var Stream = java.io.FileInputStream
try {
  s = new Stream("myfile");
} catch (fnfe
  if fnfe.javaException instanceof 
     java.io.FileNotFoundException) {
  println("file not found");
  fnfe.javaException.printStackTrace();
} catch (ioe
  if ioe.javaException instanceof
     java.io.IOException) {
  println("some io error");
  ioe.javaException.printStackTrace();
}

Exception handling is same as Java.

try {
  s = new java.io.FileInputStream("myfile");
} catch (FileNotFoundException fnfe) {
  println("file not found");
  fnfe.printStackTrace();
} catch (IOException ioe) {
  println("some io error");
  ioe.printStackTrace();
}


require 'java';

include_class("java.io.FileInputStream")
include_class("java.io.FileNotFoundException")
include_class("java.io.IOException")

begin
 f = FileInputStream.new("myfile");
rescue FileNotFoundException=>fnfe
 puts fnfe.backtrace
rescue IOException=>ioe
 puts ioe.backtrace
end

Creating Java Arrays There is no "direct" syntax. But, whenever a Java array is needed (say as an argument to a Java method call), JavaScript array can be passed. Script arrays are automatically converted to Java arrays as needed. If you want you can use java.lang.reflect.Array

// create a Java String[] of
// 3 elements
var s = java.lang.reflect.Array.
   newInstance(java.lang.String, 3);
println(s);

Same as Java!

s = new String[3];
println(s);

Update: Seems like no direct support. Nick Sieger notes that arrays can be created with easier syntax: (Thanks!)

include_class("java.lang.String") {
  "JString"
}

s = JString[].new(2)
puts s

I had the following code before Nick Sieger's comment - You can use java.lang.reflect.Array directly:

include_class("java.lang.reflect.Array") {
  "JArray"
}

include_class("java.lang.String") {
  "JString" 
}

s = JArray.newInstance(JString, 2);
puts s

Accessing Java Arrays Same as Java! usual [] and .length are supported.

// create a Java String[] of
// 3 elements
var s = java.lang.reflect.Array.
   newInstance(java.lang.String, 3);
s[0] = "hello";
s[1] = "world";
s[2] = "JavaScript";
println(s.length);
println(s[0]);
println(s[1]);
println(s[2]);

Same as Java!

s = new String[3];
s[0] = "hello";
s[1] = "world";
s[2] = "Groovy";
println(s.length);
println(s[0]);
println(s[1]);
println(s[2]);

Same as Java!

include_class("java.lang.reflect.Array") {
  "JArray"
}

include_class("java.lang.String") {
  "JString" 
}

s = JArray.newInstance(JString, 3);
s[0] = "hello";
s[1] = "world";
s[2] = "JRuby";
puts s.length;
puts s[0];
puts s[1];
puts s[2];

Implementing a Java interface Use Java anonymous class-like syntax:

var r = new java.lang.Runnable() {
  run: function() {
     println("I'm run method");
  }
};

println(r instanceof java.lang.Runnable);
new java.lang.Thread(r).start();

For single method interfaces, you can pass JavaScript function directly:

function f() {
 println("I'm function f");
}

new java.lang.Thread(f).start();

Similar to Java - but anonymous classes are not supported (yet). There is an RFE to allow auto-conversion of Closure to single-method interfaces

class MyRunnable implements Runnable {
  void run() {
    println("I'm run method");
  }
}

r = new MyRunnable();
println(r instanceof java.lang.Runnable);
new java.lang.Thread(r).start();


require 'java';
include_class('java.lang.Runnable');

class MyRunnable < Runnable
 def run
   puts "I'm run method"
 end
end

r = MyRunnable.new
puts r.kind_of?(Runnable)

include_class('java.lang.Thread') {
 |e| "JThread" }

JThread.new(r).start

Another example:

require 'java'

include_class "java.awt.event.ActionListener"

class MyActionListener < ActionListener
 def actionPerformed(event)
   puts event
 end
end

Charles Oliver Nutter notes that there is also a more "anonymous" way to implement interface:

require 'java';

include_class('java.lang.Runnable');

r = Runnable.new { puts "I'm running"; }
puts r.kind_of?(Runnable)

Implementing multiple interfaces

Rhino standalone download supports implementing multiple interfaces through the use of JavaAdapter. But, the bundled JavaScript engine in JDK 6 does not support this. See also: JDK 6 release notes - scripting section. But, it is possible to use java.lang.reflect.Proxy as shown below:


importClass(java.lang.Runnable);
importClass(java.util.concurrent.Callable);

Proxy = java.lang.reflect.Proxy;

r = new Proxy.newProxyInstance(
     null,
     [ Runnable, Callable ],
     new java.lang.reflect.InvocationHandler() {
        invoke: function(obj, name, args) {
          println(name + " called"); 
        }
     }
    );

println(r instanceof Runnable);
println(r instanceof Callable);

r.run();
r.call();

Same as Java!

import java.util.concurrent.Callable;

class MyClass 
 implements Runnable, Callable {
 void run() {
   println("run called");
 }

 Object call() {
   println("call called");
 }
}

r = new MyClass();
println(r instanceof Callable);
println(r instanceof Runnable);
r.run();
r.call();

It appears that it is not possible currently. See also: Interfaces Should Be Modules I think you can use java.lang.reflect.Proxy trick for now. But, when I tried the following I got StackOverflowError! I've filed a bug (Attempting to create a java.lang.reflect.Proxy instance results in StackOverflow)
require 'java';

include_class('java.lang.reflect.InvocationHandler');
include_class('java.lang.reflect.Proxy') {
  |x| "JProxy" 
};

include_class('java.lang.Runnable');
include_class('java.util.concurrent.Callable');
include_class("java.lang.reflect.Array") {
  |x| "JArray"
};

include_class("java.lang.Class") {
  |x| "JClass" 
}

class MyRunnable < InvocationHandler
 def invoke(obj, name, args) 
   puts name + " called"
 end
end

include_class('java.lang.Runnable')

types = JArray.newInstance(JClass, 2);
types[0] = Runnable
types[1] = Callable

m = MyRunnable.new
r = JProxy.newProxyInstance(nil, types, m);

puts r.kind_of?(Runnable)
puts r.kind_of?(Callable)

Extending a Java class Rhino standalone download supports extending a java class through JavaAdapter. But, the bundled JavaScript engine in JDK 6 does not support this. Supporting this requires .class file generation -- which has been removed in JDK 6 (for security and footprint reasons). See also: JDK 6 release notes - scripting section. Same as Java!

import java.awt.*;
import java.awt.event.*;

class MyListener extends WindowAdapter {
  // override just one method
  void windowClosing(WindowEvent evt) {
    println("Why did you close?");
    System.exit(0);     
  }
}

f = new Frame();
f.addWindowListener(new MyListener());
f.setVisible(true);

This requires generation of .class files. As of now, JRuby is interpreted only. And so extending a Java class and passing it to Java API is not possible.

References



( Oct 06 2006, 03:42:59 PM IST ) Permalink Comments [9] del.icio.us | furl | simpy | slashdot | technorati | digg

20061004 Wednesday October 04, 2006

jhat swing interface

Sandip Chitale has created Swing interface to query Java heap dumps.

Java binary heap dumps can be created using

  1. jmap
    
      jmap -dump:format=b,file=heap.bin <pid-of-java-process>
    
    
  2. hprof profiler
  3. From jconsole, access hotspot diagnostic MBean.

Recall that jhat (Java Heap Analysis Tool) supports webbrowser based interface. jhat parses a heap binary file and starts a webserver. Then, we'd use a webbrowser to query the heap. With this new Swing based tool for heap dumps, it is easier to work with heap dumps. I used the following commands to create and view a heap dump using jhat swing interface:


D:\jdk1.6.0\demo\jfc\Java2D>jmap -dump:format=b,file=heap.bin 1204
Dumping heap to D:\jdk1.6.0\demo\jfc\Java2D\heap.bin ...
Heap dump file created

D:\jdk1.6.0\demo\jfc\Java2D>java -Xmx256m -classpath D:\jdk1.6.0\lib\tools.jar;S
wingJHAT.jar  org.netbeans.profiling.tools.SwingJHAT heap.bin
Dump file created Wed Oct 04 19:16:13 GMT+05:30 2006
Resolving 54815 objects...
Chasing references, expect 10 dots..........
Eliminating duplicate references..........

Note: classes in tools.jar may be changed without notice. Not all classes in tools.jar are part of platform interface. Such non-public classes may be renamed or removed in next release!

If you have ideas on improving heap dumps, like different/better file format and/or what needs to be included in heap dumps and so on, then please join and contribute to the heap snapshot project.



( Oct 04 2006, 07:31:25 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20061003 Tuesday October 03, 2006

Prototype based OO with Groovy

Part of the attraction of languages such as Groovy, JRuby is flexible method dispatching (which is part of metaprogramming). How about Self or JavaScript style prototype based OOP with Groovy?

With the addition of ProtoObject class given below, it is possible to do prototype based OOP with Groovy. [Note that with JRuby's support for singleton classes and clone method, it is possible to write prototype based JRuby scripts].

import groovy.lang.*;
import org.codehaus.groovy.runtime.InvokerHelper;
import java.util.*;

public class ProtoObject extends GroovyObjectSupport 
             implements Cloneable {
    private static final Object[] EMPTY_ARGS = new Object[0];
    private static final String PROTO = "__proto__";

    public ProtoObject() {
        this(new HashMap());
    }

    public ProtoObject(Map properties) {
        this.properties = Collections.synchronizedMap(properties);
    }

    public Object getProperty(String property) {
        try {
            return super.getProperty(property);
        } catch (GroovyRuntimeException e) {
            return getAttribute(property);
        }
    }

    public void setProperty(String property, Object newValue) {
        try {
            super.setProperty(property, newValue);
        } catch (GroovyRuntimeException e) {
            properties.put(property, newValue);
        }
    }

    public Object invokeMethod(String name, Object args) {
        try {
            return super.invokeMethod(name, args);
        } catch (GroovyRuntimeException e) {
            Object value = this.getProperty(name);
            if (value instanceof Closure) {
                Closure c = (Closure)value;
                return invokeClosure(c, (Object[])args);
            } else {
                throw e;
            }
        }
    }
    
    public String toString() {
        Object method = getAttribute("toString");
        if (method instanceof Closure) {
            Closure c = (Closure)method;
            return invokeClosure(c).toString();
        } else {
            return properties.toString();
        }
    }

    public boolean equals(Object obj) {
        Object method = getAttribute("equals");
        if (method instanceof Closure) {
            Closure c = (Closure)method;
            Object res = invokeClosure(c, new Object[] {obj});
            Boolean ret = (Boolean) res;
            return ret.booleanValue();
        } else {
            return super.equals(obj);
        }
    }

    public int hashCode() {
        Object method = getAttribute("hashCode");
        if (method instanceof Closure) {
            Object res = invokeClosure((Closure)method);
            Integer ret = (Integer) res;
            return ret.intValue();
        } else {
            return super.hashCode();
        }
    }


    protected Object invokeClosure(Closure closure, 
                                   Object[] args) {

        Object[] tmp = new Object[args.length + 1];
        tmp[0] = this;
        System.arraycopy(args, 0, tmp, 1, args.length);
        return closure.call(tmp);        
    }

    protected Object invokeClosure(Closure closure) {
        return invokeClosure(closure, EMPTY_ARGS);        
    }

    protected Object getAttribute(String name) {
        if (properties.containsKey(name)) {
            return properties.get(name);
        }
        Object proto = properties.get(PROTO);
        if (proto != null) {
            return InvokerHelper.getProperty(proto, name);
        } else {
            return null;
        }
    }

    protected final Map properties;
}


With the above class in CLASSPATH, it is possible to write Groovy script like the following one:

// create a prototype object
def p = new ProtoObject();
// add "method" to it.
p.func = { self -> println("hello from " + self) }
// create another object
def d = new ProtoObject();
d.greet = { println "hello world" }
// set prototype to be "p"
d.__proto__ = p

// prints "hello world"
d.greet();
// calls p.func (because of __proto__)
d.func()

The ProtoObject class is similar to Groovy's Expando. But, Expando sets current ("this") object as delegate to the Closure -- and therefore will not work property with multithreading. In the ProtoObject class, I'm passing "this" as first argument to Closure. Besides, while a closure's delegate is used for method search within closure code, property access is not direct (user has to write delegate.property anyway) - so having explicit "self" as first argument is probably okay.



( Oct 03 2006, 08:13:29 PM IST ) Permalink Comments [2] del.icio.us | furl | simpy | slashdot | technorati | digg

Copyright (C) 2005, A. Sundararajan's Weblog