Thứ Năm, 4 tháng 10, 2012

JavaOne 2012: Community Keynote

The third and final keynote, the Java Community Keynote, started the final day of JavaOne 2012. Although the first two keynotes were held in the Masonic Center, this one was held in Hilton Continental Ballroom.

Sharat Chander started the Community Keynote at the 17th JavaOne (JavaOne 2012). He stated that sixty percent of JavaOne 2012's content has been presented by the community. He said JavaOne is "by the community and for the community." He had those who participated on the submission committee stand up to receive recognition and applause. Chander's opening was perfect: it recognized the community, it was enthusiastic and was an appropriate duration.

Donald Smith joined Chander on the stage, acknowledged Chander's contributions to JavaOne, and started a wave in the audience in Hilton Continental Ballroom.

Gary Frost joined Donald Smith on stage to talk about Project Sumatra and Aparapi. It sounds like Project Sumatra is currently planned for JDK 9 (giving JDK 8 a change to introduce Lambda expressions).

An expert panel came to the stage to talk about their respective organizations' participation in the Java ecosystem. There were representatives from Eucalyptus, Twitter (Chris Aniszczyk, who stated that Twitter is built on JVM with Scala and Netty), Cloudera, Eclipse Foundation (Mike Milinkovich stated that the majority of Eclipse projects use Java), and Perrone Robotics (Paul Perrone).

One of the panelists stated that "low egos and high ambition level" coupled with desire to be truly innovative are what "smart venture capitalists" look for in startups. Another panelist stated, "Communities are great at innovation because they are open."

Georges Saab came to the stage to introduce one of the Duke's Choice Award winners. He had Martijn Verburg join him to talk about the London Java Community winning an award. Martijn talked about organizing a Java Users Group and the Adopt-A-JSR Program. Although I normally loathe the mixing of politics with technical seminars (my one and only complaint about the Colorado Software Summit), I have to admit that I laughed out loud when Verburg joked "if the presidential elections don't work out...the queen has agreed to take you back as a colony."

In another humorous quote, Bruno Souza explained Brazil's recent World Cup woes, "You cannot be good at everything, so Brazil will be good at Java." I also found another perspective of his interesting concerning spoken language (Portuguese/English) issues related to a programming language: "The important thing that user groups do is translate - to the local language, between technologies, and to bridge culture gaps" (as quoted by Trisha Gee). John K. Waters also captured another related Souza quote: "Java is the lingua franca" that transcends other language differences."

Paul Perrone of Perrone Robotics returned to the stage to discuss how Perrone Robotics uses Java with their Rumbles robotic vehicle. The bot used for the demonstration (Rumbles's "little brother") is built for outdoor use, so it had duct tape on its wheels so that it could have better traction inside (he said think chains on tires).

James Gosling was introduced with a bit of drama to talk about Liquid Robotics (Guillermo Castro called it!). Gosling explained that the robot he was talking about is not like the robots most of us think about with wheels or legs and arms. He talked about use of ARM processors, running Linux, and embedded C code.

One of the challenges Gosling discussed is to use as little power as possible, especially when in the "middle of a storm in the arctic" with no ability to use solar recharge. Due to high "Iridium satellite communication costs" ($1/kb or one million dollars for a terrabyte), they focus on using approach of short texts for communication. Gosling quipped, "We don't have a Big Data problem." Although they don't have a lot of data, what they do have is "precious." Gosling explained some of the hazards their robots face including big waves and even sharks.

Gosling built his own "NoSQL-ish" database and he said this was "either the most exciting thing or stupidest thing" he has done in a while. Gosling said he's been "a real Jelastic fan."

Although Gosling's presentation was interesting in its own right, I think the "effect" of having someone so obviously connected to Java and JavaOne return to speak at a JavaOne keynote (on the "other side" [community]) was probably more significant than the message itself.

As is typically the case with JavaOne keynotes, the Community Keynote went past its scheduled end time of 10:30 am. Gosling was allowed to take more than his allotted time, but this is not a big surprise for the "Father of Java." Gosling showed a demonstration using NASA World Wind (his "favorite Swing application," like "Google Maps with a real API"). Gosling stated to some applause, "It makes my head explode when there are people who think you can do everything in HTML." Gosling pointed out that he does like HTML and especially likes jQuery, but pointed out that some things are simply out of the realm of HTML still.

After throwing out some t-shirts, Chander asked for attendees to fill out the surveys to help make JavaOne more about the community. He also encouraged attendees to share knowledge with students and others wanting to learn Java. It has also been announced that Stephen Chin will be chair of next year's JavaOne.

Community has been a big theme of this edition of JavaOne and the Community Keynote is just one part of that. I have heard pleas for help and feedback from the community in a large percentage of the presentations and keynotes that I have attended this year.

JavaOne 2012: Diagnosing Your Application on the JVM

It was worth attending Staffan Larsen's (Oracle Java Serviceability Architect) presentation "Diagnosing Your Application on the JVM" (Hilton Plaza A/B) just for learning of the new jcmd command-line tool provided with Oracle's JVM 7. The rest of the presentation was "bonus" for me, which was nice for the last session I attended on Wednesday of JavaOne 2012.

The Oracle HotSpot JDK provides jcmd, a command-line tool designed to be both backwards compatible and forward adaptable for future versions of Java. It is designed to support new tools and features that come with new SDKs in a standardized approach. The following screen snapshot shows it used for most basic jps-like functionality (Larsen mentioned jps almost as briefly as I just did and referred to jcmd as "like jps but more powerful").

As the above image shows, jcmd can be used like jps.

Larsen showed some handy features of the jcmd command. He had some small sample Java applications that helped him to demonstrate jcmd. For my purposes, I'm running jconsole in one terminal on my machine and then I'll run jcmd commands against that JVM in which jconsole is running. The next screen snapshot shows how the basic (no arguments) jcmd call provides information on that JConsole process.

jcmd supports execution against JVM processes either by process ID (pid) or by process name. The next screen snapshot shows running jcmd against the JConsole process by that name and passing it help to see which options can be run against that particular process. Note that I tried unsuccessfully to run this against 'dustin' (no existing process) to prove that jcmd is really showing options available for running processes.

The feature demonstrated in the last screen snapshot is one of the most compelling reasons for moving from existing command-line tools provided with the Oracle JDK to jcmd. This image shows how jcmd can provide a list of the available options on a per process basis, allowing for ultimate flexibility in terms of supporting past versions or future versions of Java that support different/new commands.

Just as jcmd <pid> help (or replace pid with process name) lists the available operations that can be run by jcmd against a particular JVM process, this same help mechanism can be run against any one of those specific listed commands [with syntax jcmd <pid> <command_name> help (or use process name instead of pid)], though I could not get this to work properly on my Windows machine.

The next image shows actually running that command against that JVM process rather than simply asking for help on it.

In the two screen snapshots immediately above, I ran jcmd against the pid instead of the process name simply to show that it works against both process ID as well as name. The next screen snapshot shows executing jcmd against the JVM process to get VM flags and command-line options from the JVM process (the pid of this instance of JConsole process is 3556).

Running jcmd's Thread.print command against a supporting JVM process makes easy work of viewing the targeted JVM's threads. The following output is generated from running jcmd JConsole Thread.print against my running JConsole process.


3556:
2012-10-04 23:39:36
Full thread dump Java HotSpot(TM) Client VM (23.2-b09 mixed mode, sharing):

"TimerQueue" daemon prio=6 tid=0x024bf000 nid=0x1194 waiting on condition [0x069af000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x23cf2db0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at java.util.concurrent.DelayQueue.take(DelayQueue.java:209)
at javax.swing.TimerQueue.run(TimerQueue.java:171)
at java.lang.Thread.run(Thread.java:722)

"DestroyJavaVM" prio=6 tid=0x024be400 nid=0x1460 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE

"AWT-EventQueue-0" prio=6 tid=0x024bdc00 nid=0x169c waiting on condition [0x0525f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x291a90b0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at java.awt.EventQueue.getNextEvent(EventQueue.java:521)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:213)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

"Thread-2" prio=6 tid=0x024bd800 nid=0x4a8 in Object.wait() [0x04bef000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x2917ed80> (a java.io.PipedInputStream)
at java.io.PipedInputStream.read(PipedInputStream.java:327)
- locked <0x2917ed80> (a java.io.PipedInputStream)
at java.io.PipedInputStream.read(PipedInputStream.java:378)
- locked <0x2917ed80> (a java.io.PipedInputStream)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
- locked <0x29184e28> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
- locked <0x29184e28> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at sun.tools.jconsole.OutputViewer$PipeListener.run(OutputViewer.java:109)

"Thread-1" prio=6 tid=0x024bd000 nid=0x17dc in Object.wait() [0x047af000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x29184ee8> (a java.io.PipedInputStream)
at java.io.PipedInputStream.read(PipedInputStream.java:327)
- locked <0x29184ee8> (a java.io.PipedInputStream)
at java.io.PipedInputStream.read(PipedInputStream.java:378)
- locked <0x29184ee8> (a java.io.PipedInputStream)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
- locked <0x2918af80> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
- locked <0x2918af80> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at sun.tools.jconsole.OutputViewer$PipeListener.run(OutputViewer.java:109)

"AWT-Windows" daemon prio=6 tid=0x024bc800 nid=0x16e4 runnable [0x0491f000]
java.lang.Thread.State: RUNNABLE
at sun.awt.windows.WToolkit.eventLoop(Native Method)
at sun.awt.windows.WToolkit.run(WToolkit.java:299)
at java.lang.Thread.run(Thread.java:722)

"AWT-Shutdown" prio=6 tid=0x024bc400 nid=0x157c in Object.wait() [0x04c6f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x2918b098> (a java.lang.Object)
at java.lang.Object.wait(Object.java:503)
at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:287)
- locked <0x2918b098> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:722)

"Java2D Disposer" daemon prio=10 tid=0x024bbc00 nid=0x3b8 in Object.wait() [0x0482f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x2918b128> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x2918b128> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at sun.java2d.Disposer.run(Disposer.java:145)
at java.lang.Thread.run(Thread.java:722)

"Service Thread" daemon prio=6 tid=0x024bb800 nid=0x1260 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" daemon prio=10 tid=0x024c6400 nid=0x120c waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE

"Attach Listener" daemon prio=10 tid=0x024bb000 nid=0x1278 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x024bac00 nid=0xe3c runnable [0x00000000]
java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x024a9c00 nid=0x15c4 in Object.wait() [0x046df000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x2918b358> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x2918b358> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)

"Reference Handler" daemon prio=10 tid=0x024a4c00 nid=0xe40 in Object.wait() [0x0475f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x2917e9c0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x2917e9c0> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x024a3800 nid=0x164c runnable

"VM Periodic Task Thread" prio=10 tid=0x024e7c00 nid=0xcf0 waiting on condition

JNI global references: 563

Larsen showed how to use thread information provided by jcmd to resolve a deadlock.

Larsen showed getting a class histogram from the running JVM process with jcmd. This is done using the command jcmd <pid> GC.class_histogram. A very small subset of its output is shown next (the pid of this JConsole process is 4080 this time).


4080:

num #instances #bytes class name
----------------------------------------------
1: 1730 3022728 [I
2: 5579 638168
3: 5579 447072
4: 645 340288
5: 4030 337448 [C
6: 645 317472
7: 602 218704
8: 942 167280 [B
9: 826 97720 java.lang.Class
10: 3662 87888 java.lang.String
11: 2486 79552 javax.swing.text.html.parser.ContentModel
12: 3220 77280 java.util.Hashtable$Entry
13: 1180 67168 [S
14: 2503 60072 java.util.HashMap$Entry
15: 181 59368
16: 971 43584 [Ljava.lang.Object;
17: 1053 41160 [[I
18: 206 29040 [Ljava.util.HashMap$Entry;
19: 111 27880 [Ljava.util.Hashtable$Entry;
20: 781 18744 java.util.concurrent.ConcurrentHashMap$HashEntry
21: 1069 17104 java.lang.Integer
22: 213 9816 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
23: 202 9696 java.util.HashMap
24: 201 9280 [Ljava.lang.String;
25: 24 8416 [[I

Larsen also demonstrated jstat and several of its useful functions. He demonstrated use of jstat -gcnew (new generation behavior), jstat -precompilation (compilation method statistics), and jstat -options (displays options).

During the course of his presentation, Larsen needed to convert a decimal number (pid?) to its hexadecimal representation for comparing it to the output of another tool. He used the handy printf "%x\n" <pid> command to get the hexadecimal representation of the pid.

Larsen demonstrated use of VisualVM to compare two heap dumps and browse a heap dump. He also demonstrated the VisualVM Profiler.

Larsen moved from the tools previously covered aimed at running JVMs to tools that can be used to analyze JVM core files. He returned to jstack to analyze contents of the core file.

Larsen talked about remotely accessing JVM information via JMX and tools like jconsole and jvisualvm. He demonstrated that jcmd can be used to start JMX exposure as well: ManagementServer.start "with a bunch of parameters." Larsen feels that VisualVM and JConsole would use ManagementServer.start rather than Attach API if implemented today.

jstat can also connect to daemon remotely through use of jstatd. There is no encryption or authentication with jstatd.

jps and jcmd find what's running on system using "well-known file for each JVM": /hsperfdata_<user>/<pod> This file is created on JVM startup and deleted on JVM shutdown. Unused previous files are deleted on startup, so jps and jcmd, as Java programs themselves, will clean these old ones up.

The Attach API "allows sending 'commands' for executionin the JVM," but only works on local machine and for current/same user. This is what jcmd and jstack use. Larsen then went onto explain the different mechanics of using the Attach API for Linux/BSD/Solaris (uses temporary file creation) versus Windows (uses code injection). I employed the Attach API in my post Groovy, JMX, and the Attach API.

Diagnostic commands are "helper routines inside the JVM" that produce "text output." They can be executed via the jcmd utility (and soon via JMX). They each have a self-describing facility: jcmd PerfCounter.print to see the raw contents.

Larsen showed an informative table comparing "communicating with the JVM" approaches: attach, jvmstat, JMX, jstatd, and Serviceability Agent (SA). The SA "should be used as a last resort ('typically for a JVM that is hung')" and uses a "debugger to read information."

Larsen transitioned to talk of future tools. He started this portion of the presentation with coverage of Java Flight Recorder. Java Flight Recorder is a "JVM-built-in profiler and tracer" with "low overhead" and is "always on." Other coming tools are Java Mission Control ("graphical tool providing very detailed runtime monitoring details"), more diagnostic commands for jcmd ("eventually replacing jstack, jmap, jinfo" for various reasons), JMX 2.0 ("something we're picking up again; it was started a very long time ago"), improved logging for JVM (JVM Enhancement Proposal [JEP] 158), and Java Discovery Protocol (anticipating forthcoming JEP for this).

One question asked was if one could see MBeans in VisualVM as can be done in JConsole. As I've blogged on, there is a VisualVM plug-in for doing just that.

Although I felt somewhat comfortable with the Oracle HotSpot JDK command line tools, I was unfamiliar with jcmd and appreciated Larsen's coverage of it. I learned some other things along the way as well. My only complaint is that Larsen's presentation (especially the demonstration) was so rapid fire and so content-rich that I wish I could see it again.

A related (but older) presentation with some of the same content is available at http://www.oracle.com/javaone/lad-en/session-presentations/corejava/22260-enok-1439100.pdf

Thứ Tư, 3 tháng 10, 2012

JavaOne 2012: What's New in Groovy 2.0

Guillaume Laforge's (SpringSource/VMware/@glaforge) "What's New in Groovy 2.0" presentation was in the same conference room (Hilton Golden Gate 6/7/8) as Martin Odersky's "What's New in Scala 2.10" presentation, but I decided to leave the room between these sessions for three reasons:

  1. You tend to get kicked out of a room before the next session anyway to ensure that registered individuals get equal opportunity to "the good seats" (and probably to make sure someone not registered for the session doesn't displace someone who is registered for the most popular sessions)
  2. This is the longer-than-normal one-hour break (no such break tomorrow on the final day of JavaOne 2012)
  3. The outside temperature is significantly lower than yesterday and it's refreshing to stand in a shaded area outside while a cool breeze blows between the buildings

Laforge introduced himself and the way he says his own name with intentional French accent is far cooler than how I pronounce his name. He is the Groovy Project Manager at VMWare, the initiator of the Grails framework, creator of Gaelyk, and a co-author of Groovy in Action. Laforge is another speak who likes to take questions as they come.

Laforge listed some features introduced with Groovy 1.8 command chains, gpars (concurrency/parallelism), closures improvements, built-in JSON support, and new AST Transformations.

Laforge showed a command chain that looked like English words but is really an alternative combination of methods and parameters (every other word is a method name with the words in between being the parameters to the preceding method name). With some exceptions, command chains allow code to be written without parentheses and some other types of punctuation. He showed several examples of this, including use of commas for multiple arguments. He also explained that no-argument methods do require parentheses.

GPars is "bundled in the Groovy distribution" with Groovy 1.8 and "covers a wide range of parallel and concurrent paradigms." He emphasized that this can be used "from plain Java as well!" GPars is friendlier for Groovy developers.

Closure annotation parameters is the ability to use closures within annotations. This is achieved by encoding the closure in the form of a class.

Because "closures are used a lot in the context of functional programming" and because Groovy has a "functional flavor especially with the use of closures," Groovy closures in Groovy 1.8 support closure memoization. This feature potentially brings performance improvements due to caching of results for same parameters to the same closure. More granularity in terms of the number of times to use cache for closure results is available via methods like memoizeAtLeast, memoizeAtMost, and memoizeBetween.

Laforge explained that Groovy introduced from the beginning powerful XML marashaling and unmarshaling capabilities "back when XML was popular." He said it was thus quite natural to add built-in JSON support similar to that XML support. He then showed code samples (embedded within the slides like I prefer) indicating how to use JsonSlurper to consume JSON content and how to use JsonBuilder to generate JSON content.

Groovy 1.8 introduced some new Groovy ASTs as discussed in the earlier JavaOne presentation A Walk Through of Groovy's AST Transformations. He had some nice slides that combined simple text bullets of select AST Transformations with a simple code snippet using that AST Transformation. The new Groovy 1.8 AST Transformations that he covered included @Log, code execution controlling (@ThreadInterrupt for example), @ToString, @EqualsAndHashCode (similar transforms to Project Lombock), @TupleConstructor, @InheritConstructors (replicate all parent class's constructors such as when writing a class that overrides Exception).

At exactly the half-way point in his presentaion, LaForge transitioned to coverage of Groovy 2.0. He stated that it was released in June 2012 and some "other dot releases" have been released since then with "bug fixes and so on." The key themes of Groovy 2.0 include modularity, JDK 7 alignment,

Groovy's single "all" JAR "weighs in at 6 MB," but "nobody needs everything." The new core JAR in Groovy 2.0 is half that sizs (3 MB) and there are module-specific JARs. The "big Groovy old JAR" is still available if you'd like to use it.

The effort to make Groovy modular led to the "extension modules" concept. This allows a developer to "contribute instance extension methods." This feature works with static type checking and is IDE friendly, two advantages that some of the other Groovy approaches for adding dynamic methods do not equally enjoy. These are structured similarly to Groovy Categories and require a descriptor in META-INF/services/org.codehaus.groovy.runtime.ExtensionModule.

Because "Groovy supports 99% Java syntax," Groovy supports JDK 7 enhancements such as underscores in numeric literals, multicatch exception handling, and better runtime performance due to use of invokedynamic.

One of the biggest new features in Groovy 2.0 is static type checking, which Laforge's first bullet put this way, "Goal: make Groovy compiler grumpy!" Laforge went on to show Groovy code samples with things in the code that will lead to compile-type breakage. He showed off the @TypeChecked annotation. There are aspects of Groovy that cannot be type checked by a compiler. An example of this is the builders prevalent in Groovy. This is what makes using @TypeChecked useful: use it where type checking makes sense and not where it doesn't make sense.

Laforge went on to show how Groovy allows avoidance of explicit casting after an instanceof check as a specific example of Groovy's type inference. Another Laforge example demonstrated how Groovy's static type checking catches changing of data type in the same code.

Laforge listed several "gotchas" with static type checking. For example, static type checker cannot allow use of dynamic metaClass. Another gotcha example is that the implicit "it" variable in a closure body cannot be assured to be a certain type. There is a Groovy Enhancement Proposal to make it so that this situation can be type checked. It seems that anytime Groovy cannot guarantee the type during static type checking, that situation is not allowed. This does seem to be the safest approach.

Advantages of static Groovy code include type safety, faster code, and immunity from monkey patching. The price for this is loss of dynamic features and dynamic dispatch. One audience member asked why one wouldn't always use static compilation and the answer is that many of us like being able to use the builders and other Groovy dynamic features. You can use the @CompileStatically annotation for portions to be compiled statically.

Groovy 1.8 primitive optimizations have dramatically improved performance and Groovy 2.0 static compilation closes gap with Java in Fibbonacci, Pi Quadrature, Binary Trees micro benchmarks. (Laforge did issue the usual caveats about performance benchmarks.)

Groovy 2.0 introduces modularity, Project Coin, invokedynamic, static type checking, and static compilation.

One interesting side note that Laforge mentioned is that "it is possible that Groovy 3 will require JDK 7" (to use invokedynamic). Laforge's slides are already posted online.

JavaOne 2012: What’s New in Scala 2.10

After getting lunch, I went to Hilton Golden Gate 6/7/8 to see Martin Odersky's (Typesafe) presentation "What’s New in Scala 2.10." It is always an opportunity to hear a language's creator discuss the language that he created.

Odersky stated by providing a brief history of Scala:

1996-1997Pizza
1998-2000GJ, Java generics, javac
 
2003-2006The Scala "Experiment"
2006-2009Industrial Strength Programming Language

Scala is a unifier between worlds of functional programm and object-oriented programming and is a unifier of agile (with lightweight syntax) and safe/performant/strongly typed programming.

Functional programming on the rise. 12 years ago OOPSLA had ten times attendance of ECOOP but today ICFP has three times ECOOP attendance and OOPSLA is no longer an independent conference. Functional programming important now because of market drivers. Odersky stated, "The world of software is changing because of hardware trends" and added, "Moore's Law is now achieved by increasing number of cores rather than clock cycles."

In this new world of clock cycle limitations, we have a "Triple Challenge": "Parallel" (how to use multicore), "Asynchronous" (how to deal with asynchronous events), and "Distributed" (how to deal with failures). In this world, "every piece of mutable state you have is a liability." The "problem in a nutshell" is "non-determinism caused by concurrent threads accessing shared mutable state."

non-determinism = parallel processing + mutable state

Non-deterministic behavior is something "we are uncomfortable with" and "avoiding mutable state means programming functionally." Eliminating mutable state is the one thing we have control over and can change. This is why Odersky believes that functional programming is just now rising out of the academic world to be used in the business world. Functional programming has always been inherently tied to fancy machines.

Odersky pointed out that writing functional programming is quite different than writing object-oriented programming. The "thought process of functional programming is really quite different" because it requires thinking of things spatially rather than temporally.

Having made the case for functional programming, Odersky asked if we should all move to Haskell now? He answered that there are still important things learned from object-oriented development. His slide stated, "What the industry learned about OO decompositionis analysis and design stays valid." We want to have functions and objects in our coding.

Odersky quoted Grady Booch, "Objects are characterized by state, identity, and behavior. Odersky maintains we now want to "eliminate, or at least reduce, mutable state." We want to get away from mutable state being the default. Odersky also believes we want to get away from referential equality and focus on structural equality.

Odersky listed simplicity, productivity, and fun as other reasons for functional programming in addition to dealing with the hardware environment of parallel processors.

Odersky moved from general functional programming discussion to specific Scala discussion. His bullet stated, "Scala can be as simple or as complex as you like, but it's best when it's simple." He cited Kojo as an example of Scala's alignment with simplicity. He also referenced "Sadaj's great talks." Odersky then began to work on some examples based on Ninety-Nine Scala Problems.

Scala 2.10 is "very close to RC1" and is in "code freeze" while working on three remaining code blockers and several documentation blockers. Odersky talked about the Scala Improvement Process (SIP) and showed the "Pending SIPs" that are accepted, postponed, or rejected.

SIP 12 ("String Interpolation" addresses the weaknesses and difficulties associated with concatenation of Strings using the + operator. It is shorter and safer to use string interpolation. The biggest obstacle to adding string interpolation was that $ is "already a legal character in strings." Rather than using a "special trick" of placing "s" in front of strings for which $ should be escaped and used for string interpolation, Scala will use more general solution of recognizing arbitrary IDs. The "f" string processor will interpret $ and %.

Developers could implement their own string processors and Odersky showed examples of this that might be written for XML and JSON. Odersky stated that, "Adding XML support in Scala is something that did not turn out so well." He says now there would be an advantage to using an XML string processor instead and remove the XML specific library dependency Scala currently has.

Odersky addressed why Scala does not have extension methods that "other cool languages" have. He answered that Scala does not have extension methods because "we can't abstract over them." It is "impossible to have them implement an interface."

Odersky introduced SIP 11 ("Implicit Classes"). One issue to think about here is "runtime overhead." SIP 15 ("Value Classes") introduces idea that Scala classes could extend AnyVal instead of Object. Classes extending AnyVal are "value classes" and are always unboxed. Odersky showed what code using these value classes would expand (be compiled) to.

The implicit keyword in Scala enables "very poweful" implicit conversions, but Odersky warns that "they can be misused" particularly if "there are too many of them." I like that Odersky likened them to chocolate: a little is very good, but too much leads to a stomach ache. You can turn off implicit conversion warnings by "bringing the identifier scala.langage.implicitConversions into scope (typically via import).

Odersky briefly discussed SIP 18 ("Language Imports") and then covered "Better tools." I found Odersky's goal for his language to be interesting: Odersky wants to "make Scala the language of choice for smart kids." To him, it's the ideal of what the language should be.

One attendee felt that boilerplate code is one of the best forms of simplicity and wondered whether Scala was missing its goal of simplicity by displacing boilerplate code. Odersky replied that boilerplate code would not be his preferred form of simplicity.

Odersky stated that Scala is largely mature from the perspective of significant API changes and so forth. He pointed out that all languages reach the point where it is difficult to make wholesale fundamental changes and that Scala's changes are smaller in nature now than they were in the late 2000s.

In response to an audience member's question, Odersky said that the best way to learn Scala is to read a book or take a course. He says many of the people he sees who try and struggle with Scala tried to learn it by studying its API documentation.

When asked to compare Scala to Groovy and JRuby, Odersky said that Scala is about as complicated as JDK 7 and will be less complicated than JDK 8. He feels Groovy is more complicated because it is a superset of Java. This is an interestingly different perspective on complexity. I have found Groovy to be very simple to learn, but I do have years of Java experience. I wonder if someone without Java experience would find Scala less difficult to learn. For me, even with all of Scala's great features, it cannot be easier to learn than Groovy was.

Another audience member's question led to Odersky mentioning some alternate IDE support (including Emacs and IntelliJ IDEA) for Scala in addition to ScalaIDE. There is a NetBeans plugin for Scala.

Odersky pointed out something I like about Scala in response to another question. He stated that Scala allows the developer to easily specify a piece of data is mutable. I like that Scala "does not prejudice" against mutable data and allows the developers to choose to do so if they want to. I really don't like it when "opinionated software" forces me to do what the framework's or language's author thinks is best.

I really enjoyed this presentation. I had changed from a differently planned session to this one last night and am happy with the change (although the other likely would have been good as well). My only concern about this presentation had been that, given my lack of Scala familiarity, that I'd be overwhelmed by discussion of new Scala 2.10 features without proper foundation. Fortunately for me, Odersky did not get into Scala 2.10-specific features until half way into the session. His coverage of functional programming and basics and history of Scala were helpful to me in general and were helpful specifically in preparing me to appreciate the new Scala 2.10 features. Between this presentation and the Scala Tricks presentation, my interest in trying out Scala is being renewed.

The photograph in this post was taken at Muir Woods National Monument before the beginning of JavaOne 2012.

JavaOne 2012: JavaFX Graphics Tips and Tricks

I returned to the Hilton (Imperial Ballroom B) to see Richard Bair's (Oracle Java Client Architect) "JavaFX Graphics Tips and Tricks." Bair is associated with FX Experience and obviously knows JavaFX.

Bair said a theme of his talk is on performance. He cautioned that as with most things performance related, avoid performance pre-optimization. He had a big yellow caution screen stating "WRITE CLEAN CODE, THEN PROFILE!" He said his talk is based on JavaFX 2.2 and some of the tips and tricks may not be applicable with JavaFX 8.

Bair covered the "GUIMark 2 Vector" benchmark for several browers on three different operating systems (versions not specified): Windows, Linux, and Mac OS X. Bair compared JavaFX to these browsers' native support. He also pointed out that sometimes SceneGraph is faster and sometimes Canvas is faster. Many of the points Bair brought up are more important on smaller devices than on desktops.

JavaFX was much quicker than the browsers in GUIMark 2 Bitmap and JavaFX Canvas was the quickest of all. The GUIMark 2 Text test did not provide useful data for Windows due to limited rate, but JavaFX did well on Linux and Mac OS X. Bair intends to release benchmarking approaches for public consumption and he showed a chart indicating significant performance improvement from JavaFX 2.2 to JavaFX 8.

Bair's Performance Rule #1 is "Do Less Work." Bair stated, "Smaller systems require a much more intense round of performance tuning." He added that "every line counts" and "extra method calls add up." Although in traditional desktop Java we've been taught not to worry about number of methods calls, this can be an issue on smaller devices ("excessive inlining is expensive" and "excessive method invocations are expensive"). Bair showed how to use a local final variable to reduce the number of method invocations. He acknowledged that it is "absolutely micro performance pre-optimization" on the desktop, but is a useful tactic for smaller devices.

Bair said that "fill rate" is a limitation with "nearly 100% certainty." Geometry rate is unlikely to be a significant limit in JavaFX unless you have "zillions of vertices." CSS overhead is a possible limitation as is layout computation. JavaFX does a lot of caching and the latter may not always be an issue. There is a "good chance" that system I/O will limit you, especially on smaller devices.

Bair showed an example of "abusing the fill rate" by drawing the furthest back background first and then drawing over the majority of that with another fill. He had some points for avoiding this unnecessary filling such as "only draw what has changed." Bair pointed out that the developer identifies "dirty regions" in Swing, but that JavaFX SceneGraph "does this automatically!" He did caution that JavaFX Canvas requires the developer to identify the "dirty regions."

Another approach for improving fill rate is to "limit use of (some) effects." "Effects are almost free on your desktop systems," but may need to watch them more closely on smaller devices. Bair discussed a bullet stating, "Limit use of non-rectangular non-axis aligned clips" as another tactic for improving fill rate. Directly clipping aligned images is quick, but the process of anti-aliasing, rendering as a background image, and rotating non-aligned pixel boundaries "costs you a little more" (but you won't notice on most desktop applications).

Bair stated that reducing overdraw is an effective way of improving fill rate. Related to reduction of overdraw, he discussed using "image skinning." Bair also mentioned here that JavaFX 8 includes automatic region texture cache. Other ideas for reducing overdraw include simplifying the style (Metro, Android), consolidating background fills, and reducing the number of overlapping nodes.

Bair stated that Microsoft intentionally came up with an easy-to-draw style in Metro. The Android style is similarly quicker and easier to draw.

"Occlusion Culling" allows avoidance of drawing (culling) things that won't be visible." Doing this allows us to "reduce overdraw and increase rendering performance." The JavaFX engine can respond to JavaFX CSS opaque insets to know when to not redraw these areas.

There are CSS costs to be aware of such as parsing a stylesheet. Bair showed a "CSS Horror Show" slide with .parent:hover .child {...} and explanation of why this is so terrifying: all the children must be revisited each time the parent is hovered over. Similarly, .parent .child {...} can be bad if there is a large number of children since "when we encounter a node with the .child style class, we must walk up the entire scene graph until we find it." It is better to limit the search to immediate parent.

Bair stated that the setStyle CSS property is very convenient, but can be costly. The parsing and other support can add to performance problems. CSS provides power, flexibility, and convenience, but that does come at a performance cost.

One of Bair's tips is to "avoid structural changes to SceneGraph." All CSS from the changed point on down must be recomputed. Besides this reapplication of CSS, "structural integrity checks" are required when the SceneGraph is changed. JavaFX has optimized toFront/toBack, so use these rather than removing and adding back.

Another Bair tip is to "use FXCollections." His first bullet on this stated, "Shoot for minimal notification overhead." A sub-bullet recommended using setAll instead of clear and addAll. Another sub-bullet added, "Avoid multiple add calls."

Use of FXColections.sort() is best because it "sends 'permutation' change events." This means that JavaFX engine knows what has changed and so only recomputes what is necessary for that specific type of change. These "permutations" are "handled by separate fast paths."

Bair stated that "ListView is blistering fast" because it "reuses nodes" and maintains minimum changes. Bair concluded that slide with "Reuse ListView for all your virtualization needs!"

Bair's "Manual Layout" tip included the idea of custom extensions of Region. He cautioned that you almost always need to implement computePrefWidth and computePrefHeight when extending Region.

Bair had a slide listing the questions that "JavaFX asks" when handling layout. These are questions like "How wide/tall would you like to be?" and "Can you be resized?" JavaFX asks these questions at least once and sometimes many more times that number of times when trying to render a layout. A customized layout can reduce the number of times attempted and the number of questions asked. "JavaFX asks a lot of questions" and they are "all asked for each node during layout."

Bair had a "Major Tip!" related to "Content Bias." If height depends on width, you're HORIZONTAL biased. If width depends on height, you're VERTICAL biased. Bair stated that "(contentBias = null) is by far the fastest" (all computed preferences for height and width are cached). Content Bias is typically null or horizontal. There is a bug in that "contentBias != null isn't actually well supported in the built-in layouts."

Everything covered so far has been under Bair's Rule #1 (do less work). Rule #2 is now "Know Your Device." Bair showed a slide comparing the powerful NVidia GForce GTX 690 to the less powerful NVidia GForce 310 and to the even lowlier PowerVR SGX543MP3. Bair's point, of course, is that "JavaFX gives you a single development platform and a single set of APIs, but which APIs you can and can't use is going to depend on the inherent performance characteristics of the device."

Bair had some rules of thumb for JavaFX on devices. Use desktop application for handling 20 thousand to 100 thousand nodes. Five hundred to one thousand nodes is the better range for embedded. For really small embedded devices, stick to range of 100 to 200 nodes for the JavaFX application.

Bair provided another tip related to cache. He talked about caching a chart because it will then only be drawn to the image once and can then quickly be drawn to the screen "a bazillion times." Bair cautioned, though, that this "backfires if the node is changing a lot." Bair said that he'll often turn cache to true, do an animation, and then set cache to false again.

CacheHint can be set to SPEED when rotating and scaling for better performance. If you want it redrawn when it rotates for greater accuracy, then use cache hint other than SPEED.

JavaFX 8 has a Pulse Logger (-Djavafx.pulseLogger=true system property) that "prints out a lot of crap" (in a good way) about the JavaFX engine's execution. There is a lot of provided information on a per-pulse basis including pulse number (auto-incremented integer), pulse duration, and time since last pulse. The information also includes thread details and events details. This data allows a developer to see what it taking most of the time.

Bair ended the session with the same bright yellow caution slide: Write Clean Code, Then Profile! The slide also points out, "Don't overdo it or you will have an unmaintainable mess."

JavaOne 2012: JSR 353: Java API for JSON Processing

I went to Parc 55 Mission to see Jitendra Kotamraju's (Oracle) presentation "JSR 353: Java API for JSON Processing." Kotamraju is the JSR 353 specification lead, so it's safe to assume he knows something about this "JSON for Java" JSR. I have written about Groovy's impressive JSON support and have looked forward to Java having something like this.

JSON (JavaScript Object Notation) in Java has been a popular topic for some time now. It is refreshing to see that JSR 353 ("Java API for JSON Processing") is in Early Draft Review and looks likely to be part a forthcoming Java EE release.

Kotamraju began with a brief overview of JSON and looking at an alternate (JAX-RS) use case of JSON before moving onto coverage of JSR 353 and JSON processing in Java. He described JSON as it's typically described: "lightweight data exchange format" that is "easy for humans/machines to read and write." One of his bullets emphasized that JSON is textual and fairly concise. He showed a slide with numerous "popular web sites" that provide "RESTful web services" using JSON.

Kotamraju had a slide focusing on the JSON used with Amazon Cloud Services. Another slide focused on the same for Twitter Search.

Kotamraju first showed slides on JAX-RS that showed exposed services returning XML via JAXP and JAXB. He then introduced the idea of using JSON ("application/json") rather than XML ("application/xml").

He stated that while the JAX-RS specification doesn't currently support JSON, many of the JAX-RS implementations do support JSON.< The downside to JSON being a nonstandard feature of JAX-RS implementations includes work-arounds used to make this work (such as converting JAXB to JSON or converting JAXB to XML to JSON), limitations in some implementations, and the need to bundle extra libraries. Standardizing JSON support would help make its use leaner and cleaner and more consistent.

The JSON standard support is encapsulated in JSR 353. This JSR currently includes a "streaming API to produce/consume JSON" and an "object model API to represent JSON." The Expert Group for this JSR includes Oracle, RedHat, and Twitter as well as individual and community members.

Kotamraju showed a bubble chart showing the states of a JSR with the current state of JSR 353 (Early Draft Review) highlighted. JSR 353 is implemented as a java.net open source project. They have mailing lists and an issue tracker, both of which Kotamraju provided URLs for on one of his slides. The JSR 353 reference implementation (jsonp) falls under the "GlassFish umbrella."

Kotamraju had a nice slide summarizing (two bullets each) the characteristics of the two JSR 353 APIs (Steaming API and Object Model API). He then went into more detail on each of these two APIs.

The JSR 353 Streaming API is similar to StAX and includes JsonParser for "parsing JSON in a streaming way from input sources." An instance of JsonParser is acquired via Json.createParser() or Json.createParserFactory().createParser(). This parser is optionally configured to use certain features and supports several state events including START_OBJECT, END_OBJECT, KEY_NAME, and VALUE_STRING. Kotamraju pointed out that the Streaming API is very low-level and not type safe (difficult to be type safe with String-oriented things like this!).

The Streaming API also includes a JsonGenerator that "generates JSON in a streaming way to output sources" and is "similar to StAX's XML StreamWriter.

The JSR 353 Object Model API core classes include JasonObject and JsonArray as well as JsonBuilder, JsonReader, and JsonWriter.

JsonObject is immutable and "holds name/value pairs" that are accessible as Map<String, JsonValue>. The JsonValue returned from the "value" portion of that map supports a getNames() method. JsonArray is similar to JsonObject in terms of immutability but is a List of values.

JsonBuilder is used to "build JsonObject and JsonArray from scratch." It allows for method chaining and is "type-safe" in terms of not allowing mixing of objects and arrays.

JsonWriter writes JsonObject and JsonArray to output source and uses pluggable JsonGenerator. There will be optional configuration features such as "pretty printing" (what's pretty will be up to implementation) and single-quote strings.

The JSR 353 Expert Group still needs to define equals/hashcode semnatics, how to handle exceptions, and other miscellaneous to-do items. Kotamraju encouraged attendees to try read more about JSR 353 and try out the reference implementation. He'd like to know if it's simple enough to understand and meets peoples' needs.

There were several points during this presentation when Kotamraju stated that the JSR 353 Expert Group would appreciate feedback on a specific design decision or other design choice. This again fits a common theme of JavaOne 2012 that community feedback is desired. This common goal of basing standards on developer feedback is the polar opposite of the old we-know-better-than-you expert committee approach of "you'll have EJB 1.x/2.x and you'll like it."

I liked that Kotamraju showed code samples embedded within his slides. I did this when I presented at Colorado Software Summit and received rave reviews from the audience members for doing so. It's certainly more work for the developer than simply showing code in the IDE, but it allows for greater focus on what's important and makes the sample code readily available for anyone reviewing the slides at a later time. I now regularly include sample code directly within slides of presentations that I give.

JavaOne 2012: Griffon, Up Close and Personal

After another tasty breakfast at Honey Honey Cafe & Crepery, I attended my initial Wednesday session, again in the Hilton (Imperial Ballroom A). The presentation was "Griffon, Up Close and Personal" and the presenters were Ix-chel Ruiz (@ixchelruiz) and Andres Almiray (@aalmiray). Their presentation was largely editing Griffon/Groovy code and running Griffon scripts and commands and conversing about Griffon's features. The presentation slides that were shown were shown before the actual presentation even started.

As we were waiting for the presentation to begin, there was a set of rotating slides appearing on screen touting the virtues and characteristics of Griffon. One of these pre-presentation slides was titled "Advantages" and listed convention over configuration, command line tools, IDE integration, out-of-the-box test support, and plug-in platform.

Another pre-presentation slide, titled "Features," listed application lifecycle, binding, threading, resource injection, and internationalization. The "Profile" pre-presentation slide listed Version 1.1.0; 174 plugins; toolkits of Swing, JavaFX, and SWT; and languages of Groovy, Java, Scala, Clojure, Jython, Kotlin, Mirah, Erlang.

During the course of this session, several useful online resources were mentioned. These included the main Griffon page, the sample application code for this presentation, the Griffon Guide, the Griffon Artifact Portal (described here), and the Griffon Plugins page.

Almiray showed creating GRIFFON_HOME environmental variable and adding it to the path. He showed used of griffon --version to see basics of Griffon installation and commented that this information can be helpful when asking questions on forums or issuing bug reports.

Almiray said that Intellij and NetBeans have support for Griffon, but an Eclipse plugin still needs to be developed based on the Grails plugin. Griffon is often described as Grails for the Desktop (Swing) and it certainly has the feel of Rails and Grails. For example, Almiray showed running the script to create a new application's scaffolding.

The presenters showed off some of Griffon's nicest features (not coincidentally, the features listed in their pre-presentation slides). They especially emphasized convention over configuration and internationalization capabilities of Griffon. When they spoke about plugins, they showed use of the command (on the command line) griffon list-plugins to see a list of available plugins. They followed this with a command to get more details on a specific plugin of interest (griffon plugin-info [name] [version] --repository=<repositoryName>).

Griffon supports Swing, but it also supports JavaFX and SWT. Almiray showed installation of the JavaFX plugin for Griffon.

The only slides in this presentation were the pre-presentation slides that automatically transitioned from one slide to another on a loop and the closing "Thank You!" slide. The rest of the presentation was scripted conversation between the two presenters and live demonstrations built prepared code plus some dynamically typed in code and scripts. The downside to this approach is that the slides, when made available, won't be very useful.

I had some basic familiarity with Griffon coming into this presentation, but it was nice to fill in some "holes" in my knowledge by attending this introduction to Griffon. Although there were only about 25 people in attendance at this session, the fact that a very small number (1 or 2) left early indicates that those who were in attendance were getting what they sought from the presentation. There were a couple presentations I attended yesterday that started with much larger groups, but ended up with much smaller groups as droves of people headed for the doors early.

The photograph featured in this post was taken in Muir Woods National Monument shortly before the JavaOne 2012 conference began.