|
|
|||||||||||||||||||||||||||||||
Graham Hamilton's BlogJ2SE ArchivesHurtling Towards JavaOne...Posted by kgh on May 05, 2006 at 09:13 AM | Permalink | Comments (3)I'm in my normal ten-days-to-JavaOne panic phase, but the various pieces are starting to come together. Bill Shannon are I are finalizing the slides for the JavaOne 2006 Technical General Session at 12:15 on Tuesday the 16th. This is the session where we provide the overall roadmaps for the Java SE and EE platforms, to try to give people a context for the many individual technical sessions and BOFs that follow. As usual we're panicking over having far too much material for the available time. We'll be covering Mustang and Java EE 5, but we'll also have a section towards the end looking forward to Dolphin and other new technologies. This year we're including a range of demos, so you can see the reality, both of the "Now and How" for Java EE 5 and for some of the future ideas. So grab your box lunch and bring it into the keynote room for our 12:15 start! The program of general sessions start with the Tuesday morning Sun executive keynote with Jonathan Schwartz and Jeff Jackson. The Thursday morning keynote from Erich Gamma and John Wiegand of IBM should be particularly interesting: it promises many insights from their Eclipse experiences. And on Friday, Scott and James will show us the latest, greatest, craziest, most fun Java innovations! There are, of course, a vast range of Technical Sessions and BOFs covering all kinds of key Java technologies. but, in addition to the sessions and BOFs, I wanted to plug a few associated community events:
Now I have to run - Chet has just got me some new benchmark data to expose (!) concrete numbers for the benefits of the famous Gray Rect UI fix...
AOP: Madness and SanityPosted by kgh on March 08, 2006 at 11:50 AM | Permalink | Comments (18)When people ask me "what do you think of AOP?", I tend to flinch, because the term AOP has come to be used to cover a very wide range of different uses, some of which I think are Totally Wonderful and some of which I think are Thoroughly Bad Ideas. Here's a brief survey of the range and of my reactions. Quick Overview of AOP The core concept of Aspect Oriented Programming is that there are common issues that apply across a range of otherwise unrelated classes. In AOP, these common issues are often referred to as "cross cutting" concerns because they cut across the normal inheritance class structure. The goal of AOP is to allow cross cutting concerns to be addressed by applying some common logic (or "aspects") to a set of classes, without having to individually modify the source code for each class. The idea of wrapping extra functionality around target classes will be very familiar to Java EE developers. Java EE containers typically add extra functionality and semantics to target classes by intercepting incoming calls to target objects. For example, an EJB container can add transactional semantics to a target class. (Yes, J2EE has been using AOP all along!) Java Language Principles The Java language has been designed and evolved with certain specific underlying principles in mind. We have put great emphasis on source code readability. As far as possible we have tried to follow the principle that "what you get is what you see". We have worked to maintain a clear and consistent base semantic model and to avoid language constructs that might undermine source code readability. People should be able to quickly read Java source code and then reliably understand what that Java source code does. That meaning should be independent of the particular compilers, tools, or runtime environments that are used. Now, we aren't ivory tower philosophers. We want a Java language that is productive for writing and maintaining large applications. So there will always be a trade-off between principles and pragmatics. However, in looking at the success and popularity of the Java language, much of it does seem to derive from these core principles. They seem to have worked well and to be worth maintaining and protecting. The Good: Container Based AOP One use of AOP is based on running objects within containers. These objects can only be accessed via their container. The container can intercept incoming calls and add additional semantics. An example of this approach is the way that Java EE containers can add transactional semantics to EJB components by intercepting incoming calls. In general this use of AOP seems fairly benign. The source code within the target objects is all behaving exactly as a developer should expect. Developers do need to be aware that they are accessing the objects indirectly and that the container may perform extra tasks. However the idea of operating through a level of indirection is a fairly normal Java concept. Now, within this general use case, there are probably a range of good and bad uses. Uses of container intervention such as adding transactional semantics in EJB, or adding logging, or adding extra security checks seem very reasonable. The Bad: Modifying Language Semantics Some uses of AOP rely on using runtime mechanisms to modify semantics that are specified by the Java Language Specification (JLS). For example, side files might specify that various modifications are to be made to target classes to invoke additional code when various operations are performed. Some uses of AOP allow extra code to be invoked when fields are accessed or when methods are called. The JLS carefully specifies the precise semantics of the Java language. For example, it precisely specifies the behavior that occurs when fields are accessed and it precisely specifies the rules by which one method may call another, including the cases when the call may proceed through other code as well as the cases when it must proceed directly from caller to callee. Developers should be able to rely on these semantics when they are reading source code. To take an extreme example, if a developer has written a statement "a = b;" then they should be able to rely on the value of the field "b" being assigned to the field "a", with no side effects. Some AOP toolkits allow arbitrary extra code to be executed when this statement runs, so that there can be arbitrary extra side effects as part of this assignment or even so that an arbitrary different value may be assigned to "a". Yikes! Similarly, some uses of AOP permit extra code to be inserted on a method call from one method to another, even when the JLS clearly specifies that that method call will occur directly. This enables arbitrary extra code to be executed, with potentially arbitrary side effects, in situations where a Java developer should expect there will be no side effects. This is the kind of arbitrary intervention that I think quickly races across the boundary line to insanity. (And I think most serious AOP proponents would agree.) I don't want the fundamental behavior of a chunk of source code being changed by someone magically reaching in and changing the code's meaning from the outside. That seems like a really bad idea! The core problem with these approaches is that if someone relies on techniques like these in writing their code, then other developers will no longer be able to understand that source code, because it has been developed to rely on side effects that are both at odds with the Java language definition and which are magically applied from somewhere outside the source file. You should not need to have global knowledge of a whole environment in order to understand some local fragments of code. Overall, using AOP to modify the meaning of the Java language seems like a really bad way to go. The New: Java Language Annotations In J2SE 5.0, the concept of annotations was added to the Java language. In many ways, annotations were designed to meet similar goals to AOP. The concept of annotations is that developers may apply special markers to target method, fields, or classes in order to designate that they should be processed specially by tools and/or runtime libraries. Now, annotations are not allowed to modify the behavior defined in the Java Language Specification. Within a source file that contains annotations, at runtime all the source code must execute exactly as defined by the JLS. That was a deliberate choice - we don't want annotations to become a way of defining arbitrary magic behavior within normal Java code. However, the annotations may cause changes to the overall behavior of the program, for example by directing a container to apply special behavior when forwarding calls into a target class. For me, one big benefit of annotations over classic AOP is that annotations are clearly visible in source code. So if you are reading an application you can clearly see which specific annotations are affecting the code. That readability advantage normally seems to outweigh the AOP advantage of being able to apply new semantics silently without modifying the affected class. My sense is that many use cases that were initially considered for use with AOP can now be better solved by the use of annotations. That is part of what is happening with the extensive use of annotations in Java EE 5. Conclusion The use of container based AOP seems to provide a reasonable mechanism for supporting AOP "cross cutting concerns" within Java environments, without breaking developers' expectations of how Java source code behaves. Similarly, Java language annotations appear to provide a convenient mechanism for supporting some of the use cases originally targeted by AOP. However, I think AOP quickly drifts from good to evil when it starts being used to mutate the meaning of source code or to otherwise modify what people can and should expect from Java source code. So, yes, I am a fan of AOP. But of a sane, restrained AOP!
My Favorite (Dead) Java BoilerplatePosted by kgh on November 13, 2005 at 04:03 PM | Permalink | Comments (31)In the Java platform we have tended to focus on adding lots of power and flexibility. That's great, but sometimes that power and flexibility can get in the way of doing common tasks. As part of the Ease-of-Development initiative we have been focusing on simplifying common tasks and getting rid of unnecessary boilerplate code. Here are my five of my favorite cleanups so far: #1: Opening a Text File In JDK 1.1 to 1.4, in order to open a simple text output file you needed to do: FileWriter fout = new FileWriter("fred.txt");
BufferedWriter bout = new BufferedWriter(fout);
PrintWriter pout = new PrintWriter(bout);
Say what? Why are we having to type three "new"s in order to do what should be a simple operation? In Tiger we have finally added direct support for the common case and now you can do: PrintWriter pout = new PrintWriter("fred.txt");
This is an interesting example of a common glitch in our thinking. In the Java platform we often like to provide lots of well designed, well separated components that can be plugged together in interesting ways. In fact some people might argue be that the design is cleaner if the PrintWriter class doesn't know anything about files. Well, personally, I don't think so. I think it is good to provide clean, well separated components, but we also need to provide simple shortcuts to support the most common use cases. #2: Avoiding the Content Pane Pain In JDK 1.1 to 1.4, if you wanted to add a Swing GUI component to a container you simply said container.add(component). Well, yes, except that if the container happened to be a JFrame you would get a helpful runtime exception saying that you ought to be saying frame.getContentPane().add(component); Umm, say what? Rather than raising the exception, couldn't the JFrame.add method itself call JFrame.getContentPane().add()? Yes it could. And in Tiger it does. Now you can just call add, as you would with any other container object. frame.add(component); This only saves a few keystrokes, so is this really a big deal? Yes. The real saving is that you can avoid having to learn a whole new unnecessary concept. The reason that the JFrame.add method originally threw an exception was because JFrames actually support three different panes (content, glass and root), and it was considered important to educate developers about those choices. Well, I've written various Swing applications over the years and I've never actually found the need to exploit the various different panes. The old behavior of JFrame.add forced me to go away and learn about panes. And that was distracting and unhelpful. The lesson here is that (once again) it is normally better to provide simple sensible defaults and to avoid forcing people to learn about complex options. #3: Self Registering JDBC Drivers Since JDK 1.1, in order to load a JDBC driver, you needed to do: Class.forName("com.fred.FredDriver");
Connection con = DriverManager.getConnection("jdbc:fred:fredsite.com");
Umm, what exactly is that Class.forName doing there?
This one is my fault. Back in the early days of JDBC, we needed a way
for the JDBC DriverManager to locate drivers. We arranged that newly
loaded driver classes would register with the
DriverManager. And then we asked that developers call
"Class.forName" to force the driver class to be loaded.
Sigh. This is an ugly wart. I'm happy to report that this one is going away as part of JDBC 4.0 in Mustang. The JSR-221 Expert Group is adding a new mechanism so that the JDBC DriverManager can locate and load driver classes without the need for developers to explicitly type Class.forName. So you will be able to just do the obvious: Connection con = DriverManager.getConnection("jdbc:fred:fredsite.com");
#4: Locating Resources in J2EE In J2EE 1.4, if you wanted to locate a reference to a remote EJB you needed to type: Context context = new InitialContext();
Object obj = context.lookup("fred");
FredHome fred = (FredHome) PortableRemoteObject.narrow(obj, FredHome.class);
Yikes. What on earth is going on with that PortableRemoteObject.narrow? I have to confess that I'm one of the prime culprits here and, given some of the constraints, it may have been unavoidable. But I think this one definitely does win "Ugly Boilerplate of the Year". As part of Java EE 5, there are now specific mechanisms for dependency injection, so you can now replace that code with a simple annotated field definition: @Resource FredHome fred; And then the Java EE runtimes will take care of locating the resource, doing the "narrow" for you and injecting the resource object into your field. By default the resource name is inferred from the field name and the type is inferred from the field type. This is an example of using JSR-175 annotations to restructure how we handle a common task so that it can become much simpler. I'm very excited with what is happening with annotations as part of Java EE 5 - I think it is allowing us to greatly simplify Java EE programming. And I'd like to find more ways to use annotations in Java SE, too. #5: Iterating over Collections My last example is from Tiger. We've all been used to typing some standard boilerplate for iterating over collections, such as: Vector<Wombat> v = getWombats();
Enumeration<Wombat> e = v.elements();
while (e.hasMoreElements()) {
Wombat w = e.nextElement();
...
}
Josh Bloch successfully argued for a language change to make it easier to iterate over both collections and arrays, so now in Tiger we can do: Vector<Wombat> v = getWombats();
for (Wombat w : v) {
...
}
We all knew this would be useful, but I have been really surprised by how much I have enjoyed using it, for both arrays and collections. This has turned into one of my favorite Tiger features. The resulting code is distinctly easier to read, partly because we have managed to eliminate an unnecessary local variable. This is an example of fixing a boilerplate problem we barely realized we had. I'd like to find a few more things like this! To be continued... I'll continue this topic in my next blog.
Java SE and the Google ToolbarPosted by kgh on October 04, 2005 at 12:04 PM | Permalink | Comments (21)Sun has announced an agreement with Google to distribute the Google toolbar along with consumer Java SE downloads from java.com. Here's what is happening and why. The Background We've been working for several years to increase adoption of the latest Java SE Runtime Environment (JRE) among home consumers on the internet. We've been pursuing two tactics. First, we've been working with the major PC hardware vendors to include the JRE on new PCs. That has been very successful - a majority of new PCs now ship with the JRE preinstalled, which is great. Second, we created the java.com site as a new consumer friendly site where consumers could easily download the JRE, at zero cost. That has also been wildly successful and we are getting a very high volume of consumer downloads (well over ten million a month). That's been great progress, but of course we are eager to find even more ways of reinforcing Java technology on the desktop. At the same time, we want to be careful not to do anything that would be onerous or unpleasant or otherwise discourage consumers from using Java. And even more importantly, we want to be very sensitive to the needs of Java developers and ISVs and we want to avoid changes which might interfere with developers' ability to use or distribute Java. In searching for possible opportunities, Sun got connected with the Google toolbar team, who were looking for ways to encourage adoption of the Google toolbar. Our goals seemed very compatible. Like Sun, Google was extremely concerned to avoid doing things that would mislead or annoy or disrupt consumers, which was very reassuring. It probably also helped that many of us are avid users of google.com and that Google in turn does a lot of Java development and contributes to various JCP expert groups. (Did you know that Google is a JCP Executive Committee member?) What We're Doing Here's what we have announced and what we will be rolling out over the next few months. We will be adding some options to the Windows JRE installation from java.com. These options will allow downloading and installation of the Google toolbar (and possibly other Google tools in future) as part of the Windows JRE installation. I want to emphasize that these will be options. If someone doesn't want these tools they can easily opt out and still download and install the JRE. Our core principle here is to avoid forcing anything on anyone. So we will take care to make it clear to end users what is going on and we won't force the toolbar or other tools on people who don't want them. (Yes, I know that probably sounds kind of obvious, but we don't want any misunderstanding on that point!) If someone wants to uninstall the Google tools they will be able to do that, while leaving the JRE installed (and vice versa). Again, this is about allowing reasonable end user choices, with no hidden "gotchas". These changes are primarily focused on the consumer JRE downloads hosted from java.com (although they may also affect some related "online" JRE installation bundles on java.sun.com). The way that the "online" installers work is that a small initial installer is downloaded and it then downloads additional material depending on which options the end user selects. So, as with other optional material, the Google tools will only be downloaded if the end user actually selects them. Note that we are not requiring developers or ISVs to redistribute the Google toolbar with their applications. In particular, the redistributable JRE bundles that developers can redistribute with their apps won't include the toolbar. Similarly, enterprise system administrators can continue to get redistributable JRE bundles from java.sun.com for use in deployments within enterprises, without the toolbar. We are also looking into the possibility that in the future we might offer Google toolbars during JRE auto-updates. If we do go down that route we will again be very careful to make sure that people can opt out and that there are no surprises or gotchas. Conclusion Hopefully this will be a good experience for everyone. Consumers will get an option to install useful search tools and Sun will get some extra help around Java development and deployment, especially as we head towards the new Java SE 6 "Mustang" release. Finally, I'd like to offer Big Congratulations to Thorsten Laux, the Java SE Desktop Engineering Director for figuring all this out and for driving and closing the agreement. Thorsten is a key champion of desktop Java and he has been relentless in looking for opportunities to boost Java desktop adoption.
Slides for JavaOne Technical KeynotePosted by kgh on July 10, 2005 at 05:31 PM | Permalink | Comments (6)Here are the PDF slides for the JavaOne 2005 Technical Keynote (450 K). The Technical Keynote is our attempt to provide a high level overview of the roadmaps and big directions for the core Java platform. The rough agenda was:
The JavaTM ME roadmaps were covered in a special kickoff session for the Java ME track. (We had way too much material to fit into a single keynote session.) The Technical Keynote aims to provide a high level overview to help set direction at the start of the conference. But the real technical meat is, of course, in the individual technical sessions. The PDFs for all the technical sessions will be going on-line in a few weeks and those will provide much more detail on specific areas.
Goodbye "J2SE", Hello "Java SE"Posted by kgh on June 27, 2005 at 06:32 AM | Permalink | Comments (0)We've made some updates to the Java platform names. Here's what has happened, and why. What has changed? We're modifying the names of all three Java platform editions. First, we're dropping the "2" from the full edition names. They are now:
Second, we are emphasizing "Java" in the short-hand names:
Finally, we are using single digit version numbers where possible. So rather than saying "5.0" we will just say "5". These names will be applied to new releases. We won't change the names or numbers of existing releases. So Tiger will still be "J2SE 5.0" but Mustang will be "Java SE 6". So in the future expect to hear us talking about "Java SE 6" and "Java EE 5". Why the change? Well, I'm just a simple engineer and I definitely don't claim to understand the exciting world of Naming and Branding. However, the "2" was definitely starting to look out of place. We introduced the "2" back in 1998, and it seemed increasingly odd to have that "2" embedded in the platform name while also having a version number like "5.0" at the end of the name. We also wanted to add more emphasis on the unity of the three editions. They are all based on "Java" and it seemed worth making that "Java" more visible in the shorthand names. Finally, we got feedback from developers both inside and outside of Sun that they'd prefer to see versions like "5" rather than "5.0". That wasn't what we had expected, but we've made that change. We'd initially hoped to roll out the main name changes last year, for Tiger. However, we realized that we couldn't just make the change for standard edition, we also had to address micro edition and enterprise edition. And of course they needed to review the changes with licensees who would be impacted. So we decided we needed more time and Tiger stayed a "J2SE" release. A far as I know (fingers crossed) we are finished with naming and numbering changes and I'm not expecting any more anytime soon! There is a full official description of the changes at:
"Evolving the Java Platform"Posted by kgh on May 17, 2005 at 09:49 AM | Permalink | Comments (13)The kind folks at Software Development Times asked me to write an article on the future directions for the Java platform. This has now surfaced in their May 15th edition as Evolving the Java Platform. This includes some thoughts on the planned directions for Mustang, Dolphin, and J2EE 5.0. They also broke out a separate short article on Increasing Transparency: Project Peabody which discusses some of the things we are doing to simplify J2SE licensing and encourage community contributions into Mustang. We'll be talking in more detail about all these topics (and a lot more) at JavaOne 2005, June 27-30 in San Francisco.
J2SE 5.0 Update 3: the Third Tiger CubPosted by kgh on April 28, 2005 at 02:00 PM | Permalink | Comments (16)J2SE 5.0 Update 3 went out today, so I wanted to share a few notes on what is happening with the Tiger update releases. The Update Release Process The update releases are intended to each deliver a small number of important bugfixes between our major releases. We have now delivered three updates for Tiger: Update 1 had 124 fixes, Update 2 had 117 fixes and Update 3 has 79 fixes. For descriptions of the fixes see the 5.0 Update Release Notes. The update releases are intended to be very small and non-disruptive. So there are no API changes and the release teams are very conservative in which bug fixes they accept. We are very conscious that one customer's bug fix can easily turn into an unintended problem for another customer. As part of a release like Tiger or Mustang we have an extensive beta program with long bake periods. This allows us to make a larger volume of changes and also to make riskier changes which require significant public exposure and testing. The update releases are intended to provide fast relief for a small number of key issues. They do still get a lot of heavy-duty QA attention (including a full QA test cycle), but they don't get the long bake periods and enormous QA analysis associated with a major release. There won't be a 5.1 In case you have been wondering, there isn't going to be a 5.1 release. We will be going straight from Tiger to Mustang, with only small update releases in between. There won't be anything comparable to 1.4.1 or 1.4.2. Mark Reinhold provided a description of the New Release Model in his Tigers and Mustangs and Dolphins, Oh My! blog. The main goal is to increase the predictability of releases and to allow us to deliver new functionality in a shorter window than the fairly long gap between 1.4 and 5.0. We know some people like to wait for the ".1" release before moving to a major new software release. So we did consider renaming "5.0 Update 3" as "5.1" just for that reason. But that seemed like it might cause more confusion than it would solve. But if it makes you feel better, you can think of 5.0 Update 3 as the ".1" release of the Tiger family. So please don't wait for 5.1 to appear: it won't. Go straight to 5.0 Update 3! Java.com and auto-update We will not be releasing 5.0 Update 3 on java.com or via auto-update. Here's why. Our goal is that the update releases be boring. Seriously! They are intended to deliver fixes that will be important to some customers, but they aren't normally a "must-have" item for typical Java end users. So we don't necessarily want to push them all out to our mass consumer audience. Java.com and the java auto-update mechanism are primarily targeted at making it easy for home consumers to get the JRE. As part of that, we're trying to make sure that the latest version available via java.com is the same as the latest version available via auto-update. But this won't necessarily always be the same as the latest release that is available on java.sun.com. We will occasionally use auto-update to propagate a new version out to the consumer audience, but we want to do that sparingly. In March we enabled auto-update from 1.4.X to 5.0 Update 2 and as a result millions of consumers chose to do an auto-update to Tiger. We're glad they did that, but we don't want to bother them with another auto-update again too quickly. Or to say it slightly differently: developers and expert users who choose to do direct downloads from java.sun.com will sometimes have access to more recent update releases than the main consumer downloads available via java.com. Think of that as an extra benefit for using java.sun.com!
J2SE Compatibility Test Sources ReleasedPosted by kgh on December 13, 2004 at 09:01 PM | Permalink | Comments (23)We've just released the complete J2SE compatibility test sources under a read-only license, so that the community can see what's really going on with Java compatibility testing. See: http://jck.dev.java.net Background The core strength of the Java platform is compatibility. There can be all kinds of implementations from all kinds of vendors, but they all have to be compatible. This means developers can write portable Java applications that will reliably execute on any available run-time. And vendors can invest their energy in clever implementation techniques to build the best compatible implementations. The Java team at Sun takes compatibility really seriously. Personally, I'm happy to be a deranged lunatic on this issue. Other people have their own particular obsessions about software licensing, but our obsession is around preserving compatibility. This very strong focus on compatibility is partly driven by history. We've known since the very early days of Java that cross-platform compatibility is one of the most appreciated benefits of the Java platform. We're regularly told by developers that it really matters to them. So you would think it would "just happen" by market forces, right? Well, alas, no! Our experience has been that we have had to fight vigorously to preserve compatibility in the face of both accidental back-sliding and deliberate, hostile, forking. But right now the compatibility test program is working. We have very strong acceptance from the Java developer community and from the Java vendor community about the importance of compatibility, and we have an extremely strong testing and branding program. The core of the J2SE compatibility program is the Java technlology Compatibility Kit (the "JCK"). Right now it is roughly 2.5 million lines of source code and around 76,000 distinct test cases. Since the JCK is so important, we wanted to make it easier for developers to get their hands on it and see what it is really about. There aren't any tricks, or back-doors, or weird secrets here. Just zillions of details! What we've released We've released the complete J2SE technology Compatibility Kit (JCK) sources under a read-only license, including the sources for all the tests and the sources for the test harness. This is intended to let people read and evaluate the tests.
In order to keep the license simple, we have restricted it to be strictly "read only". I want to emphasize this. The license does not allow you to compile or run the tests (If you want to do that, you can get a different, more complicated, license, see below). We did this because otherwise the license would have blossomed into a twenty page legal document. But we have tried to make sure the license meets the reasonable needs of developers who want to evaluate the JCK sources:
The Tests If you study the JCK, you will find that test coverage varies by area. That reflects pragmatic choices about which areas need most testing. We tend to put more test energy into areas where (a) compatibility is most important and (b) where there is greater risk of incompatibility. So for example, you will find there is extremely detailed test coverage on the language specification and the core JVM specification. These are areas where tight convergence is very important for developers and where there are competing product variants, so more vigilance is needed. But there are other API areas where there seems comparatively little risk of accidental incompatibilities and these areas may get comparatively light JCK coverage. This is a continual balancing act and the JCK team adjusts depending on what is happening in the external world. We will start adding greater test coverage to an area if there starts to be evidence for more risk of actual incompatibilities. One last word on the tests: I want to emphasize that these are tests aimed at interface compatibility, not at traditional product quality assurance testing. In addition to the 2.5 million lines of JCK tests that we use for compatibility testing, we have an additional 10.4 million lines of SQA test code that we use inside of Sun for product level testing of Sun's J2SE implementation. SQA and JCK testing have some overlap, but they have very different goals. The Rules Now, passing the JCK means more than just passing the individual tests. You also need to satisfy the Rules. The Rules are defined in the JCK User's Guide, which is part of the download bundle. So what's going on here? Well, the tests can make sure that people are meeting the main positive requirements of the specifications, but it is impossible to write tests that can check for every possible violation of the specs. For example, we can write tests to make sure that a Java compiler supports every standard Java language keyword correctly, but it is is very hard to write a test that would detect a new keyword that some clever vendor has snuck in to their version of the language. (Not that anyone would ever do anything like that. No way. Inconceivable!) So the Rules are used to define some higher level standards for compatibility which may not currently be captured in explicit tests. One example is that there is a Rule that requires that a product be compatible in "all configurations". You can't have a special configuration that you use to pass the tests, but then encourage your customers to use other configurations that are actually subtly incompatible. Yes, someone tried that trick once. Nice try, but this kind of thing is why we have the Rules as well as the Tests. Getting a full JCK license If you want to move beyond reading the tests to actually compiling or running tests, you will need to move to one of the fancier and more complicated licenses such as SCSL or the upcoming J2SE Java Distribution License (JDL). These licenses are intended to support doing full-scale compatibility testing on your own J2SE implementation. These are serious commercial licenses and they cover all kinds of wonderful details about exactly what you can and cannot do with the tests, and what trademark rights and obligations you have, and support licensing agreements and much, much more. It's the kind of stuff that lawyers love. For commercial use, these licenses start at about $5OK, including some minimal support. If you are serious about using the J2SE JCK to do compatibility testing then you probably do need to understand all that stuff. And you will probably want to buy extra support, as full compatibility testing is complicated and most serious users find they do need help. But if all you want to do is look at the tests, these licenses are definitely total overkill, which is why we've created the new read-only license to allow simple evaluation access. Enjoy! We think the JCK is the greatest thing since sliced bread. It isn't necessarily perfect, but it's been a great vehicle for driving real compatibility. We hope you'll enjoy reading it! - Graham Multithreaded toolkits: A failed dream?Posted by kgh on October 19, 2004 at 08:43 AM | Permalink | Comments (17)The question came up recently of "should we make Swing truly multithreaded?" My personal answer would be "no", and here's why... The Failed Dream There are certain ideas in Computer Science that I think of as the "Failed Dreams" (borrowing a term from Vernor Vinge). The Failed Dreams seem like obvious good ideas. So they get periodically reinvented, and people put a lot of time and thought into them. They typically work well on a research scale and they have the intriguing attribute of almost working on a production scale. Except you can never quite get all the kinks ironed out... For me, multithreaded GUI toolkits seem to be one of the Failed Dreams. It seems like the obvious right thing to do in a multithreaded environment. Any random thread should be able to update the GUI state of buttons, text fields, etc, etc. Damned straight. It's just a matter of having a few locks, what can be so hard? OK, there are some bugs, but we can fix them, right? Unfortunately it turns out not to be so simple... From observation, there seems to be an amazing tendency towards deadlocks and race conditions in multithreaded GUIs. I first heard about this issue anecdotally from people who had worked with the Cedar GUI libraries at Xerox PARC in the early 80's. That was a community of extremely smart people who really understood threading, so the assertion that they were having regular deadlock issues within GUI code was intriguing. But maybe that was flawed data or an exceptional situation. Unfortunately that general pattern has been repeated regularly down the years. People often start off trying for multithreading and then slowly move to an event queue model. "It's best to let the event thread do the GUI work." We went through this with AWT. AWT was initially exposed as a normal multi-threaded Java library. But as the Java team looked at the experience with AWT and with the deadlocks and races that people had encountered, we began to realize that we were making a promise we couldn't keep. This analysis culminated in one of the design reviews for Swing in 1997, when we reviewed the state of play in AWT, and the overall industry experience, and we accepted the Swing team's recommendation that Swing should support only very limited multi-threading. With a few narrow exceptions all GUI toolkit work should occur on the event processing thread. Random threads should not try to directly manipulate the GUI state. Why is this so hard? John Ousterhout gave a great Usenix talk on Events versus Threads in 1995 that explores some of the tradeoffs between thread-driven and event-driven programming and he correctly points out many reasons why multi-threaded programming is hard and why event driven programming can be simpler. I don't necessarily agree with his analysis for all kinds of programs, but I do agree for GUI programs. The particular threading problems of GUI toolkits seem to me to arise from the combination of input event processing and abstraction. The problem of input event processing is that it tends to run in the opposite direction to most GUI activity. In general, GUI operations start at the top of a stack of library abstractions and go "down". I am operating on an abstract idea in my application that is expressed by some GUI objects, so I start off in my application and call into high-level GUI abstractions, that call into lower level GUI abstractions, that call into the ugly guts of the toolkit, and thence into the OS. In contrast, input events start of at the OS layer and are progressively dispatched "up" the abstraction layers, until they arrive in my application code. Now, since we are using abstractions, we will naturally be doing locking separately within each abstraction. And unfortunately we have the classic lock ordering nightmare: we have two different kinds of activities going on that want to acquire locks in opposite orders. So deadlock is almost inevitable. This problem will initially surface as a series of specific threading bugs. And people's first reaction is to try to adjust the locking behavior to resolve the specific bugs. Let's release that lock there and then lets use more clever locking over here. Well, that is kind of a fun activity, but it is trying to fight back an oceanic tidal force. The cleverer locking typically turns into a combination of subtle races (due to lack of locking) or clever and intricate deadlocks (due to the clever and intricate locking). We went through a bunch of that in 95-97. Notice that the problems extends beyond the GUI toolkit layers and also appears between the toolkit layer and the application level. With great difficult one might try to adopt a single lock for all activity within the GUI layer, but the same problem then resurfaces a level up. So what's the answer? Well, at some point you have to step back and observe that there is a fundamental conflict here between a thread wanting to go "up" and other threads wanting to go "down", and while you can fix individual point bugs, you can't fix the overall situation. This lead to the solution that the Swing team adopted and which is used by most leading GUI toolkits: run all GUI activity on a single event thread. This means that in some sense all GUI activity becomes event driven, and the "down" threads become just a new kind of event. This demonstrably works. It is possible to write complex GUI apps that work reliably. Hurrah! But it does make managing long running activities tougher. I wrote a smallish Swing program that I use periodically to selectively zap large boring attachments from my email archives. I don't want to hang the GUI while it reads tens of megabytes of emails, and I also want to display a progress monitor, so I ended up having to carefully balance handing off big activities to worker threads and handing GUI activities back to the event thread. It is probably more complicated than it would be if I had a magic multi-threaded library, but it has the significant saving grace that it actually seems to work reliably. Subtleties Are things really so black and white? Surely there have been people who have used multi-threaded toolkits successfully? Yes, but I think this demonstrates one of the characteristics of the Failed Dreams. I believe you can program successfully with multi-threaded GUI toolkits if the toolkit is very carefully designed; if the toolkit exposes its locking methodology in gory detail; if you are very smart, very careful, and have a global understanding of the whole structure of the toolkit. If you get one of these things slightly wrong, things will mostly work, but you will get occasional hangs (due to deadlocks) or glitches (due to races). This multithreaded approach works best for people who have been intimately involved in the design of the toolkit. Unfortunately I don't think this set of characteristics scale to widespread commercial use. What you tend to end up with is normal smart programmers building apps that don't quite work reliably for reasons that are not at all obvious. So the authors get very disgruntled and frustrated and use bad words on the poor innocent toolkit. (Like me when I first started using AWT. Sorry!) Another wrinkle: it is possible to have multiple simultaneous GUI activities within a Java VM by using multiple event threads. That works provided the different activities are almost entirely isolated, have their own distinct GUIs (no shared components or mixed hierarchies) and provided the very lowest toolkit level can correctly dispatch events to the right event thread with minimal locking. This is useful in (for example) running multiple applets within one JVM. But it isn't a very general solution - most applications need to live within the constraint of only a single event thread. In this note I've most been covering why Swing and other toolkits are essentially single-threaded. Chet recently blogged on some related topics around why multi-threading complicates user programs and normally won't help raw graphics performance. Also, before I forget, some people are probably remembering that "processes and monitors are duals". Well, yes, it's true. In some sense we are using the event thread to implement a global lock. We could invert things, and create a global lock that is equivalent to the event queue. This would be fairly ugly and would require wide coordination and undermine a lot of abstractions. But the larger problem is that Java developers tend to use multiple locks and if they are to preserve the equivalence with an event queue model, they will need to follow various non-obvious rules about how they interact with these other locks. The event queue model makes the central single lock much more visible and explicit, and on the whole that seems to help people to more reliably follow the model and thus construct GUI programs that work reliably. Conclusion I guess the bottom line is that like many others I would really like to see a flexible, powerful, truly multi-threaded GUI toolkit. But I don't know how to get there - at this point there is fairly strong experience that the obvious approaches for multi-threading don't work. Maybe in future years people will come up with a radically new and better approach, but for now the answer seems to be that events are our friends. J2SE 5.0 (Tiger) is out!Posted by kgh on September 30, 2004 at 01:25 AM | Permalink | Comments (15)J2SE 5.0 (Tiger) is out! The J2SE 5.0 final bits are now available at http://java.sun.com/j2se/5.0/download.jsp And there is a variety of news about the release on java.sun.com. The JCP Executive Committee approved the last 12 Tiger JSRs on September 14th. Less formally, but just as importantly, we then received our official blessing from the J2SE Quality Assurance team that we meet all the release criteria and are ready to go. Yesterday we did the final round of formal release approvals inside of Sun, including things like getting formal approval from the product support team that they believe the product is ready to ship and they are ready to support it. Overall release quality is looking extremely good. The QA team runs some heavy-duty stress tests, where the "pass" criteria is that the systems stay up for a certain number of days. Well, at this point all those tests systems have been running for five weeks and they look like staying up until we decide to pull the power cord. Happiness! Tiger has been a big release and it is great to see it ship. There have been hundreds of contributors, from across the world, and across the industry. Many many thanks to everyone who has contributed, either through helping to develop the new APIs in the JCP, or through contributing to the implementation, or through helping to test and stabilize the release. It has been a big effort but it has been well worth it. Now on to Mustang and Dolphin! For details on the release plans for J2SE post-tiger take a look at Mark Reinhold's blog on the New Release Model. - Graham Evolving the Java LanguagePosted by kgh on September 13, 2004 at 02:33 PM | Permalink | Comments (78)We're starting to think about potential language features for Dolphin (7.0). So I've been reflecting a little on the principles that James so brilliantly infused into the original Java language and which we've tried to preserve as it evolves. The big core principle is around making programs easy to understand. Java is focused on being a powerful but simple language, easy to read, with a consistent clear meaning. It is more important that Java programs be easy to read than to write. That may sound trivial, but it isn't. Lessons from C++ Looking back at C++ there were a whole set of factors at work that made reading source code difficult:
Many project teams working with C++ adopted conventions to create simpler subsets of C++. "We'll use this, but won't use that." This helped. However, it lead to the problem of language fragmentation, where different teams adopted different language subsets and then got cognitive dissonance when they read one another's source. The Java approach The Java language took a very different approach. Java tries to be an unobtrusive language. As a developer, you should be able to focus on what your application code is doing and on how it interacts with libraries. Code should do what it seems to do - people shouldn't need to worry about clever language side effects or about what "=" means this week. This focus on clarity and on readability has affected Java in many ways. It has led to a focus on keeping the language simple and clear. It has led to relatively conservative uses of syntax and minimized the places where user defined code can modify base semantics. As another part of this principle, there is also a strong focus on having "one standard language" which means the same thing everywhere. It should be possible for a Java developer to start reading a chunk of new Java source code and to be able to rely on a consistent set of language semantics. I shouldn't have to worry about different vendors implementing language features in different ways. And I really shouldn't have to read your compiler flags in order to understand what your source code will do. So part of our investment in the Java language includes a strong focus on both a very precise specification (currently driven by Sun's esteemed Computational Theologist, Gilad Bracha) and also an extensive language compatibility test suite. Language updates in Tiger Now principles are good, but so are pragmatics. If we stuck too rigorously to our principles, we'd probably never dare make any changes to the language. It is natural for things to evolve, and we want to be able to make developers more productive, within the spirit of the language. But we are also very conscious that adding individually useful features may slowly undermine the deep values of the language. A lot of thought went into the Tiger language features. We reviewed scores of potential language changes before settling on the small set that made it into Tiger. There is always a risk in any change, but I think the Tiger features will help developers without disrupting their ability to understand Java code.
For Dolphin, as for Tiger, a lot of people both inside and outside of Sun will be involved in reviewing any language change proposals. The detailed designs will be handled through the JCP. But my suspicion is that we'll probably continue to stay very conservative on changes, as each little change also carries its little wad of additional complexity. We're unlikely to add a macro preprocessor (sorry) or any general form of operator overloading, or full-blown AOP, or any other mechanism for redefining and obscuring core semantics. But we will look for new language ideas that help developers with common problems. For example, one area I'm personally interested in is some kind of "friends" import mechanism to make large multi-package projects easier to manage. One platform, many languages One last thought: the Java language is only one language for the Java Platform. It has one particular set of values, which seem to be particularly good for creating large, maintainable programs. But different developers want different things at different times. It's OK to have multiple languages, each of which is well designed for a specific kind of programming. When I'm doing a quick Sunday morning hack, sometimes I want something more scripty, and I don't want to have to track all those checked exceptions. So I'd like to see more use of alternate languages on top of the Java platform, with different goals and styles. For example, I was really pleased to see the "Groovy" language brought into the JCP. It is designed as a new Java platform language, but with its own goals and design center that are very different from the classic Java language. Happiness! My personal suspicion is that the Java language is good for at least another 20 to 30 years, if we are careful in managing its evolution. But I also expect that over time new research ideas will emerge and slowly gain acceptance and at some point we'll want a new synthesis that will create a great new simple language. And of course we'll want to make sure that sparkling new language runs on the Java Platform! - Graham Stabilizing the Tiger ReleasePosted by kgh on September 07, 2004 at 01:40 PM | Permalink | Comments (5)In response to my recent blog on the Tiger Release Candidate, I've had a few people follow-up on specific bugs they'd like fixed. Now, whenever I see any specific bug description I always have a quick surge of frustrated empathy and I want to rush out and make sure it gets fixed asap. But then I take a deep breath and think of the larger picture... Overall, we think Tiger is on track to be our highest quality release ever. Happiness! But unfortunately that doesn't mean (and can't mean) that it is bug free. There is an agonizing tension in getting to high quality. To achieve stability, you have to become really paranoid about change management, especially late in a release. Since beta1 we have been increasingly cautious in bug analysis. We've tried to make sure the key bugs get fixed, but we've also deferred some bugs, in order to manage the rate of change and to make sure we keep a high level of overall stability. Some of these may get addressed in the Tiger update releases (5.0_01, 5.0_02, etc.). In some of our early JDK releases we were aggressively fixing lots of bugs even very late in the release. Well, unfortunately, that didn't actually lead to high quality releases. Every bug fix is also a bug risk, even for those small fixes that "are clearly totally safe". Our history is that even heavily reviewed "totally safe" fixes sometimes aren't. I'm sorry that not every possible bug fix has gone into Tiger. But we are doing a balancing act and the engineering teams have been carefully assessing all the candidate bugs. I know priorities can look different from different angles (especially if a given bug is interfering with your app!) but we've been trying to be thoughtful and to balance for the overall community good. Tiger contains a lot of important new features and also a lot of significant bug fixes and we want to deliver it to the community in a safe and timely way. That requires a driving focus on stabilizing the release and thus on progressively clamping down on change. I know this is an imperfect process, but we try to make the best choices we can. Our main concern at the Release Candidate stage is to Not Break Anything(tm). The goal of RC is mostly to discover if we've had any significant "accidents" due to the fixes introduced since Beta2. Right now we are mostly seeing the RC status we expected. Overall we have extremely high quality, but with some previously diagnosed bugs. RC is suposed to be essentially the final bits. The Sept 30th target ship date leaves room for one last respin, in case we had introduced some major late-breaking problem in RC. But if there are no critical show stopppers we might skip the respin and ship a little sooner. - Graham Tiger Status: Release Candidate is outPosted by kgh on September 01, 2004 at 12:53 PM | Permalink | Comments (9)This is a quick update on where we are with Tiger (J2SE 5.0). We're now in the final haul, heading towards a target release date of September 30th. The Release Candidate went out today: http://java.sun.com/j2se/1.5.0/download.jsp This should be pretty much the final bits, barring any major show-stopper issues. Overall quality is looking good (I think Mark Reinhold will be blogging more about this soon). The Tiger JSRs are now in Java Community Process Final Ballot and we hope we'll get the JCP Executive Committee final approval on the 14th. Overall the release seems to be on track for final release on September 30th. We will be watching carefully for feedback on RC and we may do small schedule updates if needed, but we're hoping we'll be able to hit the 30th. Now on to Mustang and Dolphin! - Graham Tiger's ChildrenPosted by kgh on June 28, 2004 at 01:41 PM | Permalink | Comments (1)I'm up at JavaOne today. As usual, it's a blast. We brought a gorgous baby white tiger on stage to help us kick-off the "Tiger" section of this morning's general session. He was great fun and really mellow. He had got up really early to come to Moscone, so he was quite sleepy by the time he came on stage. He had been more active during our prep session when he was gently play-biting on my ankle through my jeans and trying to decide if he liked the flavor. (He's young enough that he's only just starting to figure out the whole teeth thing and he hasn't yet figured out that engineers are actually edible.) Anyway, we've been talking a lot today about the J2SE Tiger release (now J2SE 5.0) which will ship this fall. But we've also been discussing some of our initial thinking for Mustang (6.0) and Dolphin (7.0). Right now we're in early planning and we're talking to lots of Java partners, customers, and individual developers about what the priorities should be post-Tiger. We'll analyze and balance all that input and use it to help design our JSR proposals to the JCP. So right now, all of this is interim brain storming based on initial conversations and feedback. Our initial thinking is that we probably want to try to get back into a slight faster release cadence. Tiger is a great release and has a lot of big new features, but it will ship about two and a half years after Merlin (1.4). We'd like to go back to shipping slightly smaller releases slightly more frequently. So we want to deliver the same volume of new features over time, but delivered on an eighteen month cycle rather than a 30 month cycle. (We have to balance between some people wanting to see features more quickly and other people not wanting to have to deal with too many new releases.) So our current thinking is that the next two feature releases will be:
We typically like to define some driving themes for each releases. Right now the initial candidate themes for Mustang are:
We have lots of new feature ideas and we're accumulating many more as we talk with people. We'd like your input. If you are attending JavaOne, you can come to the "Tiger's Children" BOF on Tuesday at 7:30-9:30 pm in Moscone Room 105. This is intended to be an interactive session where we will mostly be in "listen" mode, to hear people's requirements. We'll also be having a Tiger's Children session at the "Ask-the-Experts" pod in the JavaOne Pavilion on Wednesday 4:30-7:30, if you want to talk one-on-one. For people not at JavaOne, we're putting up an online survey at http://java.sun.com/j2se/survey/index.jsp. The survey results will be tabulated and analyzed as part of the planning team's work. This is a great opportunity to provide input on the future of J2SE. Be pragmatic: tell us both what and why. We often find it easier to meet a feature request if we understand the real underlying need! - Graham
| |||||||||||||||||||||||||||||||
|
|