Groovy jsr-223 script engine @ scripting.dev.java.net has been updated to use Groovy version 1.5.6.
If you want to learn more about Blu-ray disc and what Java has to do with it, you may want to attend the following talks/BOFs @ JavaOne 2008!
| Date/Time | Session ID | Session Name |
|---|---|---|
| Wednesday, May 07 9:30 AM - 10:30 AM | TS-5449 | Java™ Technology for Blu-ray™ and TV: Creating your own Blu-ray Java Discs |
| Wednesday, May 07 9:30 AM - 1:30 PM - 2:30 PM | TS-6464 | Blu-ray Disc Security |
| Wednesday, May 07 9:30 AM - 6:30 PM - 7:20 PM | BOF-5451 | Blu-ray and Java™ Technology Roundtable |
| Thursday May 08 1:30 PM - 2:30 PM | TS-5638 | Writing Connected Device Configuration Applications for Resource-Constrained Devices |
| Thursday May 08 1:30 PM - 2:30 PM | TS-5888 | Driving Innovation in Packaged Media (Blu-ray) User Experience |
From our group talk (TS-5449), we will be focusing on the open source project @ https://hdcookbook.dev.java.net. Meet you soon @ JavaOne !!
Updates on the world of Scripting for the Java platform:
My recent fun with virtualization continues. In the last JavaOne, I missed the talk titled "Everything Java": JPC, a Fast x86 PC Emulator. But, I downloaded the source and binary of JPC just to check it out. I ran the classic game "Prince". Nostalgia
I am thrilled to know this news!! And that is not without a bit of self-interest. I work on some blu-ray related activities @ Sun (more on that in future!).
BTW, if you are interested in learning about blu-ray and related Java programming platform called BD-J, you may consider the following:
Updates on the Scripting project.
Sorry about the looo..ng hibernation! Now, it is time for updates on the Scripting project.
import javax.script.*;
public class Test {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("javafx");
e.eval("<<java.lang>>.System.out.println(\"hello\");");
}
}
Please note that you need to build JavaFX Script compiler by checking out sources from the SVN repository and put the jar in the CLASSPATH.
javac has "hidden" and "even more hidden" options. This blog entry is about how to use one such option without actually modifying javac's source code. [Read More]
If you are a programming languages enthusiast, you'll probably like this. I downloaded ANTLR Parser Generator. In addition to ANTLR, I downloaded the following:
I downloaded java compiler (javac) source code from the JDK 7 site. I did not download entire JDK – I just downloaded compiler-7-ea-src-b15-05_jul_2007.zip I've installed JDK 6 and NetBeans 5.0
I extracted the source zip file into c:\javac directory. From NetBeans IDE, File->Open Project menu, I chose c:\javac\compiler directory. Then, I build the project – I scrolled the build output log to the end and I saw:
Building jar: C:\javac\compiler\dist\lib\javac.jar
build-bin.javac:
Copying 1 file to C:\javac\compiler\dist\bin
build:
BUILD SUCCESSFUL (total time: 8 seconds)
So, I tried to run the newly compiled java compiler. I attempted to compile a simple “Hello World” program. I got the following error:
C:\javac\compiler\dist\lib>java -jar javac.jar Hello.java
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/Main
What happened? I looked at the build log again. I missed the following lines – because I had seen only at the end!!
Copying 7 files to C:\javac\compiler\build\bootclasses
recompiling compiler with itself
javac: invalid flag: C:\javac\compiler\build\classes
Usage: javac <options> <source files>
use -help for a list of possible options
Java Result: 2
Copying 7 files to C:\javac\compiler\build\classes
Copying 1 file to C:\javac\compiler\build\classes\com\sun\tools\javac\resources
Building jar: C:\javac\compiler\dist\lib\javac.jar
build-bin.javac:
Copying 1 file to C:\javac\compiler\dist\bin
build:
BUILD SUCCESSFUL (total time: 8 seconds)
Looks like there is a build error. The compiler in built in two steps:
The sources are built with javac in JDK 6 (on which my NetBeans IDE ran)
Then, compiler sources are built again – but this time with the new compiler binary generated by step (1).
Looks we got error in the step (2) [see above: recompiling compiler with itself] . I searched the ant script used to build for “recompiling compiler with itself”. The following is the fragment after that:
<echo message="recompiling compiler with itself"/>
<pathconvert pathsep=" " property="src.javac.files">
<path>
<fileset dir="${src.classes}">
<patternset refid="src.javac"/>
</fileset>
</path>
</pathconvert>
<java fork="true" classpath="${build.bootclasses}" classname="com.sun.tools.javac.Main">
<arg value="-sourcepath"/>
<arg value=""/>
<arg value="-d"/>
<arg file="${build.classes}"/>
<arg value="-g:source,lines"/>
<arg line="${src.javac.files}"/>
</java>
The problem seems to be with “java” command above. Empty string is set as value for -sourcepath option. I changed that to the following:
<arg value="-sourcepath"/>
<arg value="${src.classes}"/>
When I re-built the compiler after the above change, there were no errors – yes, I scrolled the build output to check it
And newly compiled javac could compile “Hello World” program.
Now, I wanted to make some to “interesting” but simple change to the compiler source. From a “doc” page, I came to know that there is a hidden javac option called “-printflat”. It appears that with -printflat option javac prints source code after doing transformations for generic types, inner classes, enhanced for-loops, assertions etc. It would be great to visualize the kind of transformations done by javac. So, I wanted to make “hidden” option available. I searched for “printflat” in the project. I got three hits:
JavaCompiler.java
RecognizedOptions.java
java.properties
As usual, I am impatient – wanted to enable printflat option always [regardless of what the command line is]. So, I changed the following line in JavaCompiler.java
printFlat = options.get("-printflat") != null;
to
printFlat = true; // options.get("-printflat") != null;
so that the secret option is enabled always. After rebuilding the compiler, I tried compiling my “Hello World” program. Surprise! I got the following error:
C:\javac\compiler\dist\lib>java -jar javac.jar Hello.java
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/Main
When I checked “javac.jar” by “jar tvf javac.jar”, I saw only “.java” files instead of “.class” files! Remember I mentioned that javac is recompiled by itself (step (2) above)? Apparently with “-printflat” option, javac just write transformed files but does not generate .class files! Because I had hardcoded printflat to be true always, during the second bootstrap compilation javac did not generate .class files. Looks like my lazy way does not work! I need to find how to really change the code to accept printflat command line option explicitly. I cut the story shot and just summarize the changes I made:
added a enum value to com.sun.tools.javac.main.OptionName – PRINTFLAT("-printflat");
In com.sun.tools.javac.main.RecognizedOptions class, I added PRINTFLAT to “static Set<OptionName> javacOptions” initialization value.
In public static Option[] getAll(final OptionHelper helper) method of RecognizedOptions class, I added “new HiddenOption(PRINTFLAT)” as an element in the returned Option[].
I managed to compile and run the compiler after the above changes! Now when I can pass “printflat” option!! I compiled the following simple Book.java:
class Book {
private String name;
public Book(String name) {
this.name = name;
}
class Order {
private int quantity;
public Order(int quantity) {
this.quantity = quantity;
}
}
}
with the following command:
c:\javac\compiler\dist\lib\>java -jar javac.jar -printflat c:\Book.java
Now, I can see the generated Book.java and Book$Order.java in the current directory where java compiler was run:
class Book {
private String name;
public Book(String name) {
super();
this.name = name;
}
{
}
}
class Book$Order {
/*synthetic*/ final Book this$0;
private int quantity;
public Book$Order(/*synthetic*/ final Book this$0, int quantity) {
this.this$0 = this$0;
super();
this.quantity = quantity;
}
}
Wow! I can see how java compiler generates a hidden synthetic parameter for the outer class object and so on. Note that the java compiler does not overwrite your original source files. You need to run the compiler in a different directory – compiler generates new files [which is good, you won't accidentally overwrite your original code with generics, inner classes and so on].
Now, you can experiment with constructs like asserts, inner class methods accessing outer's private methods/fields, anonymous/local classes, local class accessing final parameters/locals of enclosing method, generics, enhanced for-loop and so on and see how java compiler transforms those constructs to generate good-old “flat” classes without these features. Have fun!!
Jim Holmlund (blog?) compiled this very nice summary of serviceability related code in hotspot JVM -- http://openjdk.java.net/groups/serviceability/.
JavaFX Script, as you may know already, is a declarative and statically typed scripting language. It has first-class functions, declarative syntax, list-comprehensions, and incremental dependency-based evaluation.
JavaFX Script syntax includes object literals - a declarative syntax to construct objects. If you know JavaScript, you may know about JavaScript Object Literals and it's subset called JSON - which is a lightweight data-interchange format (considered to be an alternative for XML in certain use-cases). There are some parallels between JavaScript object literal syntax and that of the JavaFX Script. Of course there are differences. The following is an attempt to summarize the differences.
JavaFX Script is statically typed. But, user may omit types in many places. JavaFX can infer types from the context. While defining object literals, the type of the object is specified. For example:
class Person {
attribute name: String;
attribute children: Person*;
}
var chris = Person {
name: "Chris"
children:
[Person {
name: "Dee"
},
Person {
name: "Candice"
}]
};
But except for the "top most" object, we can omit types elsewhere and JavaFX will infer types. For example, the above may also be written as shown below:
class Person {
attribute name: String;
attribute children: Person*;
}
var chris = Person {
name: "Chris"
children:
[ Person {
name: "Dee"
},
Person {
name: "Candice"
}]
};
JavaScript is dynamically typed. So, we don't and can't specify the type of the object. [And yes, I do know about JavaScript 2.0 - which is optionally typed. But, I am talking about the current implementations]. We write the above object in JavaScript as
var chris = {
name: "Chris",
children:
[ {
name: "Dee"
},
{
name: "Candice"
}]
};
JavaFX object literal examples do not include comma between property specifications. For example,
class Person {
attribute name: String;
attribute children: Person*;
}
var chris = Person {
name: "Chris"
children:
[Person {
name: "Dee"
},
Person {
name: "Candice"
}]
};
Please note that there is comma between elements of the array but
there is no comma between properties (between name and
children in above). But, JavaScript object literals
(and JSON) have comma between properties as well. But,
JavaFX implementation seems to accept comma. So, the following
var chris = Person {
name: "Chris", // <-- comma here is fine!
children:
[Person {
name: "Dee"
},
Person {
name: "Candice"
}]
};
JavaFX allows local variables in object literal. We can write something like:
class Person {
attribute name: String;
attribute likes: String;
}
var v = Person {
// n is local to this literal
var n = "sundar"
name: n,
likes: "Java"
};
In JavaScript, we can not use local variables within literal definition. If we want such variables, we may do something like this:
var obj = (function() {
// n is local in function
var n = "sundar";
return {
name: n,
likes: "Java"
}
})();
i.e., we define an anonymous function surrounding the object literal and call it to get the object.
In JavaFX, arrays are flat.
var v = ["Jan", ["Feb", "Mar"]];
// the above is same as ..
// var v = ["Jan", "Feb", "Mar"];
In JavaScript (and in JSON), arrays can be nested.
JavaFX allows Java objects to be created with object literal syntax. For example:
import javax.swing.JFrame;
import javax.swing.JButton;
var f = new JFrame { title: "hello world" };
var b = new JButton { label: "ok" };
f.add(b, "Center");
f.pack();
f.setVisible(true);
Mozilla Rhino implementation of JavaScript (which is included in Sun's JDK 6) allows accesing Java classes. But, JSON-like initialization is not supported for Java objects. Java bean conventions are supported. So, it is possible to use field access syntax for getXXX()/setXXX() method calls. We may write the above as
importClass(javax.swing.JFrame);
importClass(javax.swing.JButton);
var f = new JFrame();
// Java bean convention
f.title = "hello world";
var b = new JButton();
b.label = "ok" ;
f.add(b, "Center");
f.pack();
// bean convention again
f.visible = true;
Is it possible at all to have JSON-like syntax to create Java objects? Yes, it is! We can use JSAdapter. We can define the following two JavaScript functions using JSAdapter.
function junwrap(o) {
var origObj = "__wrapped__";
if (o instanceof Array) {
var res = new Array(o.length);
for (var e in o) {
res[e] = junwrap(o[e]);
}
return res;
}
if ((typeof(o) == 'function' ||
typeof(o) == 'object') &&
origObj in o) {
return o[origObj];
} else {
return o;
}
}
function jimport(ctr, name) {
var origObj = "__wrapped__";
var obj = new ctr();
this[name] = function(initObj) {
var res = new JSAdapter() {
__has__ : function(name) {
return (name in obj) || (name == origObj);
},
__get__ : function(name) {
if (name == origObj) {
return obj;
} else {
var v = obj[name];
if (typeof(v) == 'function') {
return function() {
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = junwrap(arguments[i]);
}
return v.apply(obj, args);
}
} else {
return v;
}
}
},
__put__: function (name, value) {
if (name != 'origObj') {
value = junwrap(value);
obj[name] = value;
}
}
}
for (var f in initObj) {
res[f] = initObj[f];
}
return res;
}
}
With the above functions, we can write
jimport(javax.swing.JFrame, "Frame");
jimport(javax.swing.JButton, "Button");
var f = new Frame() { title: "hello world"; };
var b = new Button() { label: "ok" };
f.add(b, "Center");
f.pack();
f.visible = true;
Note that this JSON-like Java object initialization may be used in the server side JavaScript as well. For example, we may create a java.util.Date object as
jimport(java.util.Date, "JDate");
var d = new JDate() {
date : 1,
month: 0, // 0 is January!
year : 17 // offset from year 1900
};
Two server side use-cases with the Phobos framework include:
Typically, we may create these POJO class instances and persist/marshall for subsequent use. These POJO classes follow Java bean conventions. So, it is easy to use JSON-like object creation with these classes.
JRuby 1.0 has been released. The jsr-223 script engine for JRuby had an issue because of a recent change in JRuby parse API during 1.0.0RC3. Thanks to the java.net user "bongobongo" for reporting this issue along with the patch. I've included this fix and regenerated binaries and changed the engine to use JRuby 1.0 version -- as usual, you can find the sources and binaries at @ scripting.dev.java.net
It has been a while. I've not updated on scripting.dev.java.net project and related activities. Here it is ...
You probably know this already, but just in case you missed: JavaFX Script has jsr-223 script engine for it (included in javafxrt.jar). See also:
You probably checked out the OpenJDK project and even built it on your favorite platform. And you are wondering how can you do a small, but interesting project with OpenJDK. In Nov 2006, I mentioned about HotSpot Serviceability Agent (SA) which is a set of APIs and tools for debugging HotSpot Virtual Machine processes and core dumps. You may want to look at HotSpot Serviceability page and HotSpot SA sources in the hotspot/agent/ directory and the subdirectories.
One of the components of HotSpot SA is (pure Java) disassemblers for SPARC and x86 processors. These are used to view HotSpot compiled code, HotSpot interpreter code (recall that hotspot Java bytecode interpreter is generated at the start of the virtual machine) as well as the compiled C/C++ code of the virtual machine. You may want to refer to the asm and subdirectories. But, there is no disassembler yet for AMD64.
Maxwell Assembler Framework has assemblers and disassemblers for SPARC, PowerPC, AMD64 and IA32. From the project web page:
The architecture of our system is largely based on the Klein assembler system, which has been developed in the Klein project. Its main idea is to generate assembler methods that are very well tested against existing textual assemblers.
How about using the Maxwell framework with HotSpot SA? It will get us AMD64 disassembler and we can replace the existing disassemblers for SPARC and x86 as well! I think this is a small enough, but interesting project to work on.