Newsletter sign-up
View all newsletters

Sign up for our Enterprise Java Newsletter

Enterprise Java

Discover new dimensions of scripted Java

BeanShell scripts become real Java classes

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Scripting, albeit slower than execution of precompiled byte code, has many advantages. First, it allows high-level code execution at runtime, without compiler access. This proves particularly useful in situations where the compiler is no longer available (deployment environment) or for languages where compilers simply do not exist. Second, scripted code provides extension points to modular programs. For example, jEdit, an excellent text editor, uses BeanShell for storing user-defined actions (macro definitions). The popular Web browser Mozilla utilizes JavaScript extensively to provide highly configurable and extensible user interface components. I could cite numerous more examples—the need for scripted code execution at runtime is evident by the sheer number of different language interpreters available (see Resources for a list).

In spite of being so popular, incorporating support for a scripting framework usually requires explicit code fragments that evaluate the interpreted code, handle exceptions, and pass parameters between the script and the rest of the application (Ramnivas Laddad explains this task in "Scripting Power Saves the Day for Your Java Apps," (October 1999)). While all this complexity may seem reasonable for languages that do not share Java's object-oriented paradigm, in this article, I show that this often painful overhead can be quite easily trimmed for object-oriented language interpreters.

This article shows how to freely and transparently mix interpreted (scripted) code with precompiled Java code. Moreover, I attempt to mix the code in such a way that neither the JVM nor other running classes can distinguish between precompiled classes and scripted classes. I focus on BeanShell because it is widely known and extends Java syntax to make the examples easier to understand. You could adopt this article's approach to any object-oriented scripting language interpreter.

I assume you are familiar with certain Java topics, such as reflection and class loading. The article provides learning opportunities in dynamic code compilation and loading, and utilization of scripted code in a runtime environment. Furthermore, it also demonstrates the powerful new synergies that can be achieved by combining various open source projects like BCEL (Byte Code Engineering Library), BeanShell, and Ant.

Think big: Set up the goals

BeanShell is an excellent Java interpreter with several extensions to the Java syntax that make it particularly interesting. The script can access real Java classes, execute their methods, load new classes if necessary, or even implement an interface and return to the JVM as an instance of that interface. For example, the Java code below creates a fully functional scripted instance of the java.lang.Runnable interface:

Interpreter interpreter = new Interpreter();
// Define a method called run() in the interface
interpreter.eval("run() { ... }");
// Fetch a reference to the interpreter as a Runnable
Runnable runnable = (Runnable)interpreter.getInterface( Runnable.class );


The capability of acting as any Java interface is one of BeanShell's great advantages. Also note that the script does not even need to declare all of the interface's methods! If Java invokes an undefined method, the interpreter first attempts to evaluate the default handler for undefined methods—a method named simply invoke(). If the script also fails to specify that default handler, an exception will result.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources