Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Friday, April 15, 2011

Ceylon: Interesting for the Wrong Reasons

A couple of days ago, Gavin King announced that he is leading a team at RedHat that’s creating a new JVM language called Ceylon. See here for most of what is known so far. The stated motivation, in a nutshell is that they like Java very much, but it has deficiencies that are preventing progress in key areas, and they are generally feeling “frustrated”. They don’t have a complete compiler yet, but they’re working on it, and I get the impression RedHat is pretty serious about it.

Gavin King’s slides provide a fascinating insight into the kind of thinking that remains so dominant in the Java community. Gavin King is well known in the Java world as the inventor/leader of Hibernate and various other JBoss projects. He certainly knows Java inside out, and his list of “frustrations” is astute, if incomplete. While I haven’t dug into all the details so far revealed about Ceylon, but it seems likely that they’ll succeed in their goal of creating “a better Java”. If given the choice between using Java and Ceylon, I could certainly see myself choosing Ceylon. But Ceylon is a terrible idea. The problem is that they are treating the symptoms, not the disease; and they’re repeating exactly the same mistakes that resulted in them finally hitting a dead-end with Java.

Possibly the best outcome of Ceylon is that it emphatically refutes the argument that “Java is all we need”. Few have put more hard labour into trying to make Java feasible than Gavin King and the JBoss folks. They and a few others have spent the last decade or so producing a staggering number of bloated tools, libraries and frameworks in order to keep Java going. Don’t get me wrong, there’s a lot of extremely useful Java libraries out there, but there’s also a huge amount of guff that exists solely to compensate for the impracticality of the Java language. Ceylon is the “main-stream” admitting, finally, that not all problems can be solved the Java way: more frameworks, more libraries, more tools, more code.

So Mr King and friends have finally hit the wall with Java. They’re a bit late to the party, but we should welcome them none the less. So why do I say Ceylon is a terrible idea? The short answer is: Scala. The long answer is, well, longer. My biased summary of the situation is this: after years of having to build more and more layers of increasingly baroque frameworks in order to make progress, they realise that they can no longer keep up with their competitors (cough_C#cough_) because Java the language is an unavoidable “bottleneck”. They identify certain essential abstractions that are needed to solve their immediate problems, and proceed to design a new language that provides those essential abstractions, while remaining as “familiar” as possible.

In other words, Ceylon is all about making “a better Java”. There is certainly support for a evolutionary approach like this. Some argue that Java itself was (in language terms) “a better C++”, so why not follow that successful approach now? Well, if that worked so well for Java, why are even its greatest fans now trying to replace it? I’m reminded of Linus Torvalds' reaction to “Subversion is a better CVS”. The problem with Subversion isn’t that is poorly designed or built; it isn’t. The problem with Subversion is that the goal itself just isn’t very useful.

This is how it’s going to go: Ceylon will be built, they’ll make a SDK library, then there will be Hibernate-Ceylon, Spring-Ceylon, WebFrameworks-Ceylon 1 through 63,854, Logging4Ceylon, Ceylon.util.logging, commons-logging-ceylon and Simple Logging Facade 4 Ceylon. All these will be an improvement over their Java equivalents. Then, in another five or so years they’ll hit some new pain points and realise that some of those other “academic” abstractions are actually useful in the real world after all. For example, Ceylon supports higher-order functions (but, inexplicably, not lambda expressions). If we could go back in time 5 years and ask Gavin King “how important do you think higher-order functions are?”, what would he say? My guess is “they’re not essential for Real Work™”.

But it’s still an improvement, so why not embrace it? Because we have an already have a much better option that’s already doing the job in the real world: Scala. Or look at the interesting stuff going on in .NET land. Ceylon’s goals look positively narrow and uninspiring by comparison. Of course, Gavin King was immediately asked “why not Scala?”. It is my sincere hope that this question will continue to be asked of him. His answer consists of the same misconceptions that Scala advocates have been trying to dispel since forever. Take this statement from Mr King, from an interview in InfoQ:

One important force that helped make Java so successful was the things Java left out. But you need to be very smart here: Java’s decision to leave out higher-order function support was enormously harmful. Now, obviously the Scala team have gone down a very different path here and have created a very feature-rich type system. As a general rule I would prefer to solve my problems with fewer, more general constructs, than with more, less powerful constructs.

This is the exact inverse of the truth. No one who has made a serious effort to understand Scala could make such a statement. “Fewer, more general constructs” is exactly what Scala is all about! My summary of Scala’s mission statement would be as follows:

  • Scala aims to maximise the potential for useful abstractions, whilst:
    • giving assurance that your abstractions are correct (static typing)
    • allowing you to do what is necessary to get the performance you need
    • maintaining seamless interoperability with Java

Scala aims to be compatible with Java, but it’s about much more than just “a better Java”. Ironically, it seems as though Ceylon will not interoperate with Java as seamlessly as Scala does (e.g. Scala keeps null and type erasure). It’ll be interesting to see how that works out. To get an idea of how serious the Scala team is about powerful but practical abstractions, look at how they handle the tensions that crop up between abstraction and performance. Great examples of this are how Scala handles the unpleasantness of arrays on the JVM, and also the @specialized annotation.

Scala is by no means perfect. The trade-offs it makes will not suit everyone fully. But I cannot help but scratch my head over statements like this (Gavin King, again):

But I guess I should mention that the number one technical problem that we simply can’t solve to our satisfaction in Java – or in any other existing JVM language – is the problem of defining user interfaces and structured data using a typesafe, hierarchical syntax.

I could very well be missing something, but this would seem like a problem that is right in Scala’s wheelhouse. Perhaps it may not be solved satisfactorily today, but it could done with far less effort than creating a whole new language (and new standard library, and new tool chain…). It is depressing to think of what these guys could achieve working with Scala instead of pouring resources into Ceylon.

You may wonder, “if you think Scala is so good, then use it and be happy, why worry about Ceylon?” Well, I worry because I think Ceylon is worse than Scala, but it could win anyway. That actually seems to be the more common outcome in these situations. I would much prefer a world with Scala jobs in demand than one with Ceylon jobs in demand. So, yes, it’s all about me being selfish. I would say to all Scala fans: don’t be afraid to be a little selfish and evangelise for the better outcome.

Posted via email from lockster's posterous

Wednesday, October 27, 2010

Some more thoughts on Apple

A few more points that occurred to me, following up on my last post.

Whither the mouse?

Since its inception in 1984, the Mac user interface has obviously been designed for desktop computers with a mouse and a keyboard. When notebook computers came along and we wanted to be able to use them without carrying a mouse everywhere, or without even a flat, stable surface to put the mouse on, they had to emulate the mouse as best they could. This may now be reversing.

In the announcement of Mac OS X Lion, there was great emphasis placed on the use of multitouch gestures as a means of control. I think Lion will be the first OS designed for notebooks with multitouch trackpads, with the desktop Macs left to emulate the MacBooks as best they can. If you consider that a sizeable majority of the hardware Apple sells today is mobile and primarily operated via some form of multitouch instead of a mouse, this move seems sensible. And all new desktop Macs ship with the multitouch-capable Magic Mouse as standard now.

The Costs of Supporting Java

With regard to Java, there's been a few comments along the lines of "all the hardware Apple sells to Java developers must more than cover the cost of the handful of engineers needed to keep maintaining Java". I think this underestimates the costs involved. Supporting Java means, in addition to the engineers, that:
  • Java must be accounted for in development plans
  • Java must be accounted for in QA plans
  • Customer support needs to deal with it
  • Security vulnerabilities need to be investigated and fixed
The true cost isn't so much the money, it's that it unavoidably diverts some of the company's attention from things it would rather focus on. While continuing with Java support wouldn't be hugely onerous for Apple, eliminating distractions that aren't bringing much benefit can really help competitiveness.

Also, as the vast majority of Java work (since the switch to Intel) has been on the GUI, I'd expect the Java team knows the guts of the Mac GUI pretty well by now. Engineering talent isn't exactly a fungible resource. There's probably a development manager somewhere in Apple salivating at the thought of having the Java people on her team.

Apple and the Server Side

Folks have pointed out that Apple is a heavy user of server-side Java in their web services. I can think of many ways they can deal with that, and have no idea which option they'll take. But I think we can be sure they've got a plan and aren't leaving it to chance. And despite everyone (including me) getting very animated over "Apple dropping Java", it's worth remembering that their Java team isn't going to be shutting down tomorrow.

More generally, Apple's plans for the cloud are completely opaque to me right now. We're all assuming they have big plans for cloud services: they built that huge new data centre, and their hardware strategy seems to imply more reliance on cloud services in the future. The iPad's greatest weakness is that so much of its functionality, including just initialising it, requires USB synchronisation with a PC or Mac. MobileMe syncing is great, but it only works for a few things.

The new MacBook Air models were just announced, including one with an 11" screen, which I think is a first for Apple notebooks. When making the announcement, Steve Jobs said something like "we think this is the future of MacBooks". With their emphasis on mobile, wireless use and limited storage, these too are crying out for more cloud services.

And I think this could be Apple's greatest weakness. If I were Steve Jobs, the thing that would worry me most about Android isn't its "openness" (however you care to define it), or the temporary situation of shelf-space in U.S. phone outlets, but the fact it is backed up by the world's best cloud services. And they're only going to get better. Obstacles remain, but the movement towards doing more and more in the cloud is inexorable. Where Google has no rival, Apple's track record is not that great. The iTunes store is a huge success, obviously, but it's not really all that "cloudy", as you need a Mac with enough hard drive to hold all your content. MobileMe is expensive, and often unreliable and slow; it really only survives due to the first class client support on Mac and iOS. The iWork service is not bad, but lacks Google's killer feature of collaborative editing. Apple has its work cut out for it when it comes to the cloud.

Flash, Core Animation and Multitouch

In my last post I claimed Flash didn't support Core Animation or Multitouch. Well, @johnyanarella set me right on that. Flash does support both of these. I haven't used that many Flash apps, so now I'm wondering to what extent the multitouch support is actually used in apps.

Friday, October 22, 2010

Java and the Mac

So Apple has quietly announced that it is deprecating its support for Java on the Mac. The wording was (not uncharacteristically for situations like this) a bit vague on the details of what this means. I think two things are definite: 1) Apple will continue to support Java 6 on Snow Leopard until it reaches end of life; which I think happens when the OS after Lion is publicly released. 2) Apple will not port Java 7+ to the Mac. The main unresolved question is whether Java 6 will be supported on Lion. My guess is that it will be offered as an optional download, similar to Rosetta in Snow Leopard. Apple won't make any promises though, as they will want to have the option to drop it if it's too much effort.

As a Mac user who has been working on the Java platform for many years, this is a fairly big deal for me. I think it's an interesting event that provides a chance to examine both Java's position and Apple's plans for the Mac. People in the Mac Java community are speculating about the deeper meaning behind this move, especially when combined with Apple effectively banning Java platform applications from the new Mac App Store. So time for me to add my speculation to the noise.

Is Apple trying to force the use of their platform and tools?

No. True, Apple has made it crystal clear on numerous occasions (the Mac App store requirements are just the latest case) that they want developers targeting their OS platforms to use their development platform (Objective-C, Cocoa, Xcode). But I don't think they are deprecating Java in an attempt to force the issue. After all, Lion will come with Perl, Python and Ruby all pre-installed.

Does Apple want to kill cross-platform desktop apps?

No. I think it's true that, strategically speaking, Apple has no interest at all in cross-platform apps (outside of the browser). But along with announcing the deprecation, the latest Apple Java release also includes brand-new support for installing multiple versions of the Java platform, explicitly mentioning support for third-party versions. It's clear that Apple has no problem at all with Java running on Macs. I think they want Oracle to take it over, but I doubt they bothered to make any sort of deal with Oracle before making this move. Update: as I was drafting this, news came through that Steve Jobs has replied to a question about this, which basically confirms that he thinks Oracle should be responsible for Java on the Mac.

Then why did Apple do this?

The reason isn't that complicated: Apple no longer needs Java. If you make a list of what Steve Jobs sees as the critical objectives for Apple, it becomes immediately obvious that maintaining a Mac port of Java is not helping to advance any of them. Of course, neither does maintaining, say, Apple's port of Python. But Python takes very little effort to port and maintain. The Java port requires a team of engineers permanently dedicated to it. Also, the huge success of iOS has given Apple the confidence that their approach to working with third-party developers is working out great for everyone. The prospect of Java developers and applications abandoning the Mac is no longer remotely scary for them. Apple have decided they'd rather pay the costs of dropping Java than keep maintaining it.

But what are Apple's critical objectives?

The main theme of the "Back to the Mac" event on October 20 was the idea of moving iPad software and hardware features into the Mac, in a way that made sense for the Mac. My theory is that Apple has now oriented its entire strategy around the iPad. I think Steve Jobs probably regards the iPad has the best thing Apple has ever made. This is because the iPad provides the "purest" user experience: you hold it in your hands, rotate it, move it, directly manipulate the information you're working with via touch, and it dedicates itself to the task at hand. Of course, the iPhone has these characteristics too, but if will forever be limited by the (obviously worthwhile) trade-off of fitting in your pocket. The larger screen size of the iPad allows the touch interface to reach its full potential.

Slight diversion: in the recent financial call, Jobs said that 7" was a lousy form-factor for a tablet. You had better believe that he meant it. I will bet that Apple will never release an iPad with a different form factor. Going smaller puts to many constraints on the options for touch UI, so you end up with a bulky iPhone. Going larger would be nice, but it rapidly becomes unwieldy (the fact the iPad can be easily held and moved around is a critical part of the "experience"). The dimensions were chosen to balance the needs of video with those of e-books. Believe me, Apple chose the form-factor it did very carefully.

And yes, something else Jobs likes about the iPad is that Apple has more control over it. While many ascribe this to cynical motives, I believe Jobs honestly sees this as being good for the customer, and part of the reason for the success of iOS devices. Whether this view is correct will, in the end, be decided in the marketplace.

What is the future for the Mac?

So Apple sees the iPad as the future. But while it might be a "pure" experience, there's obviously a large number of important things that the iPad simply cannot do1. So Macs aren't going anywhere, but Jobs wants to make them more iPad-like. In the Mac event, Jobs called out what this meant: curated App Store, full screen apps, app "Launchpad", autosave/resume. What is equally interesting is what this implies they are leaving behind. During Craig Federighi's demo of Lion on the 20th, he showed the use of swipe to switch between a) full screen apps b) dashboard c) "the desktop". Perhaps I'm reading too much into this, but what today constitutes "the Mac Desktop experience" seems, in Lion, to be just another full-screen app you can switch to. A Rosetta-like box to run "the legacy stuff". I think Lion could be Apple's first step in really redesigning the Mac from first principles.

This iPad-like approach also reinforces other trends already underway. The traditional document-centric Mac app is basically dead. Most apps will be one-window, "content-centric", and abstract the filesystem completely. And they'll be made with Apple's tools. In other words, iPhoto '11 is the model. It's going to be fascinating to see how far Apple can take this. There have been people saying, literally for decades, that the fundamental desktop concept of movable, resizable, overlapping windows was the worst idea in the history of user interfaces. Will they be proven right? I have no idea. The best part is, as others have pointed out, Windows cannot easily copy what Mac OS X is doing. Greater distinction between the keyboard/pointer OS platforms will be a great thing, in my opinion.

Where does Java fit in all this?

It doesn't. Regardless of whether you think Apple's plans for the Mac are great or terrible, it's clear that heavy-weight "cross-platform platforms" like Java and Flash, which are controlled by others, could hardly be more useless to Apple. They don't interfere with Apple's plans, but they don't help them either. Java and Flash apps don't use compelling OS X technologies like Core Animation. They're completely clueless when it comes to multitouch. Apple only cares about one "cross-platform platform": the light-weight and mobile-friendly HTML5, which they can also influence.

Will Oracle Provide Java on Mac?

I'm not sure, but I think yes. The answer to this question will also answer many questions about what Oracle really has planned for Java and JavaFX. In my opinion, JavaFX has already lost the cross-platform war to HTML5 (I like JavaFX a lot, and would love Oracle to prove me wrong here). Oracle claims to be committed to developing and promoting JavaFX, so it apparently believes it can turn things around. But there's one thing I'm certain about: JavaFX cannot succeed as a credible platform without first-class support on the Mac. If Oracle is actually serious about JavaFX (which is client-side Java now) then it needs to very soon announce that it will be adding Mac as a fully supported platform, by Java 8 at the latest. Bringing Mac support online in a Java 7 update would be better. If Oracle lets Java on the Mac rot, then the death of client-side Java will be certain and final.

Where did it all go wrong for Java?

A few people have pointed out that just 10 short years ago Steve Jobs was proudly proclaiming that the Mac would be the premier platform for Java, and now after years of disinterest Apple is finally giving up on Java altogether. How times have changed. In 2000, Apple desperately needed apps on the Mac - any apps, and of course developers. Now, it's Sun/Oracle that really needs Java on the Mac, and Apple can afford to be indifferent.

Even if Oracle produces a brilliant implementation of JavaFX for the Mac, things do not look great for Java on the client. I won't make this post even longer by discussing the reasons for client Java's failure, but it's not because Apple didn't give Java a fair chance. Speaking as someone who really believed in and supported the "write once, run anywhere" ideal of Java, the fact has to be faced: the dream is well and truly finished. Where Java has failed, HTML5 has succeeded, primarily by keeping its goals modest and being ruthlessly pragmatic.

1 But I think that we haven't even scratched the surface of what the iPad is capable of. Many of its limitations are "a simple matter of software". I think iOS 4.2 is going to give a big boost to the iPad's utility, as will iOS 5 and beyond. Having said that, there'll always be some jobs that just need a mouse pointer and a keyboard.

Tuesday, October 17, 2006

Logging vs String Construction

A classic logging problem in Java is this:

logger.finest(expensiveStringConstruction());

The problem with this is that even when the logger's level is above FINEST and the message is not logged, the message string must still be constructed. In cases where constructing the string involves a lot of work, your code can be slowed down significantly even when logging is off. The standard solution is like so:

if (logger.isLoggable(Level.FINEST))
{
  logger.finest(expensiveStringConstruction());
}

By adding the if statement around the logging, the expensive string construction is only done if the message is actually going to be used. The problem with this is that if you have a lot of logging statements, your code soon ends up littered with these ifs that just obscure what is really happening. Not to mention that you have to type it all in.

This problem could have been tackled in a different way. It was a mistake for the logging methods to take String objects as parameters. This mandates that the messages must be constructed before passing them to the logger. A better approach is to delay creating the message string until the last possible moment, when we know it will be needed. One option would be to have an interface called, say, LogMessageFactory with a method String createLogMessage() and have the log methods accept the interface instead of String. But a new interface isn't necessarily needed, as good old Object already has a toString method. If loggers took Object's instead of String's, then they could just call toString when logging actually takes place.

Well, the logging API actually does let you do this. LogRecord objects can store a message string and an arbitrary set of parameter objects. The standard formatters will use MessageFormat to construct the string that is finally logged. Here's an example:

public final class TestLog
{

    public static final Logger logger =
        Logger.getLogger("test");

    public static void main(final String[] args)
    {
        final TestLog testLog = new TestLog();
        logger.finest(testLog.toString());     // 1
        logger.log(Level.FINEST, "{0}", testLog);   // 2
    }

    public String toString()
    {
        try
        {
            // expensive string construction here
            Thread.sleep(5000L);
        }
        catch (InterruptedException e)
        {
            assert false;
        }
        return "Hello, world";
    }

}

If the logger is configured to log at FINEST or below, the lines marked 1 and 2 behave identically and the message is logged. However, if the logger's level is above FINEST, then line 1 will take 5 seconds to do nothing and line 2 will just check the level and exit, without calling toString at all.

The advantage of logging this way is that you don't have to put all those ifs statements in. But there are disadvantages. You can't use the convenience logging methods like severe and info, etc. You have to use one of the log methods that accept Object parameters. Unfortunate, but not too egregious.

The bigger disadvantage is that the string generation has to be inside a toString method. While this can be done inside an anonymous inner class, the syntax for that isn't exactly convenient. If you have a bunch of log messages that are generated completely differently, then using anonymous inner classes everywhere will be far worse than just using the if statements. Where it would make sense is if you have a bunch of log statements where the expensive portion of the message creation is the same.

For example, you could replace this:

if (logger.isLoggable(Level.FINEST))
{
   logger.finest("Stuff happened " + expensiveStringCreation());
}
if (logger.isLoggable(Level.FINEST))
{
   logger.finest("Foo happened " + expensiveStringCreation());
}
if (logger.isLoggable(Level.FINEST))
{
   logger.finest("Bar happened " + expensiveStringCreation());
}

with:

final Object msgFactory = new Object()
{
    public String toString()
    {
        return expensiveStringCreation();
    }
};
logger.log(Level.FINEST, "Stuff happened {0}", msgFactory);
logger.log(Level.FINEST, "Foo happened {0}", msgFactory);
logger.log(Level.FINEST, "Bar happened {0}", msgFactory);

I'm assuming here that there's code in between these log calls that changes the state and hence the string returned by expensiveStringCreation.

There's a lot of talk at the moment about adding closures to Java. Whatever ends up being adopted, this is definitely one of the scenarios it should assist with (although what I'm describing only requires the most basic capabilities of closures). I'm a fan of the CICE proposal, although some of the objections raised seem valid. The CICE proposal requires an interface with a single method, so if we did have the LogMessageFactory interface I proposed above, we could just do:

logger.finest(LogMessageFactory()
    { return "Stuff happened " + expensiveStringCreation(); });

Friday, December 23, 2005

Handling InvocationTargetException

A quick hint on handling java.lang.reflect.InvocationTargetException.

This sucker is thrown whenever you invoke a method via reflection (typically via Method.invoke), and that method throws any sort of exception. So it doesn't indicate a problem with the reflection mechanism, it is simply how the reflection mechanism notifies you of exceptions thrown by the method you called.

Whenever you catch this exception (and you will have to catch it at some level), the first thing you should do is call getCause(). This returns the exception thrown from the method that was invoked via reflection, and that's what you care about. So whenever you need to log or report an occurrence of InvocationTargetException, always use the cause object rather than the InvocationTargetException itself.

Thursday, December 22, 2005

How not to catch Exceptions

When it comes to bad Java practices, top of my list would have to be catching exceptions like this:

try
{
   // stuff - anything really
}
catch (Exception e)
{
   // maybe log it if you're lucky
}

This is usually done because the "stuff" throws more than one kind of checked exception, and the code to handle each case is the same. So what's wrong with it? The biggest problem is that this not only catches the checked exceptions you're interested in, but also all RuntimeExceptions. The vast majority of RuntimeExceptions are only thrown from buggy code, and catching them is rarely a good idea. The above catch handles all kinds of exceptions the same way, regardless of whether it was caused by a bug or an ordinary failure that can happen from time to time when a program is running (e.g. a network failure). This only obscures bugs.

Consider the case where a bug causes a NullPointerException to be thrown - perhaps the most common type of bug in Java. If the catch clause simply logs the exception message (not uncommon), then you have to check the log to have any idea why your app is misbehaving. And if you don't log the stack trace (again, not uncommon), you still won't have a clue what caused it. A much better option is to simply let RuntimeExceptions go, which produces a screeching halt in your app and, in most cases, an immediate stack trace dump telling you exactly what happened. The details of what happens when you don't catch a RuntimeException at all will vary depending on the environment you're running in, but it's always safe to do so. For example, servlet containers usually output the stack trace in the HTTP response when a servlet throws a RuntimeException.

A good principle of catching exceptions is to only catch the those specific exceptions that you can actually deal with. E.g.

try
{
   // stuff that throws AException
   // stuff that throws BException
}
catch (AException e)
{
    // deal
}
catch (BException e)
{
    // deal
}

This way just deals with the exceptions that you can sensibly recover from and lets any RuntimeExceptions that indicate bugs to be thrown to the caller. If the code to handle both AException and BException is the same, you could always move it to a method.

"But what if the code throws, like, 10 different kinds of checked exceptions?". I've found it's actually pretty rare to have a block of code that throws more than about 4 unrelated checked exceptions. Some of the reflection APIs are pretty bad with this, however. It can be a pain to enter basically identical catch clauses for every one. A good alternative is:

try
{
   // stuff that throws AException
   // stuff that throws BException
   // stuff that throws CException
   // stuff that throws DException
}
catch (RuntimeException e)
{
   throw e;
}
catch (Exception e)
{
   // deal with all checked exceptions in the same way
}

This is actually not a bad way to get the best of both worlds (although I usually find it clearer to just handle each checked exception individually).

I think in hindsight, the inheritance hierarchy of exceptions is backwards. Instead of the RuntimeException extends Exception extends Throwable hierarchy, it should have been CheckedException extends UncheckedException extends Throwable. That would allow catching all checked exceptions in a single catch clause, while not obscuring unchecked exceptions thrown by buggy code.

In a similar vein, you almost never want to declare a method with throws Exception. This is basically throwing away the whole checked exception system and saying "this method can throw any kind of exception". This tends to make exception handling in the caller painful, and may give the caller no good option but to declare throws Exception itself. Before long, you end up with all your methods declared as throwing Exception and you have little indication of what exceptions you might actually have to deal with at runtime. (There is an argument to made that checked exceptions are a bad idea altogether, but that subject will have to wait for another day.)

There are a few cases where you might have a legitimate reason to catch Exception, or Error, or Throwable. Here are some of them:

  • When implementing Runnable. Reporting RuntimeExceptions thrown from Runnable.run is a bit of a pain in Java versions 1.4 and earlier. It's often easier just to catch them yourself and log the entire stack trace somewhere it can't be missed. Java 5 has a nicer mechanism for doing this, however.
  • When calling some sort of plug-in module. In this case, a bug in the plug-in doesn't mean the whole application needs to abort. You can catch the exception, notify the user, unload the plug-in and move on.
  • When dealing with poorly designed APIs that throw Exception.