Arguably the worst decision in Java was to have checked exceptions. I've never been thrilled by Java as a language (after Smalltalk all other languages seem, well, just not something to get excited about) but checked exceptions seem to get to me every time. I just had an another bad experience with this exceptionally bad idea.
I recently had to work on some open source code, the code was about a specific servlet. After working around some of the limitations I decide to just fork it. The servlet was not working very reliable and I could not really pinpoint where the problem was. So I decided to just remove all low level exception handling and handle all exceptions in the service method of the servlet. The authors had done the traditional way. This is making APIs without general throw clauses so you have to catch all the bad stuff and then turn it into some specific exception. It was amazing how readable the code became, and, even better how easy it was now to diagnose because anything that went wrong always ended up in the catch block of the service method. Easy to set break points, and easy to handle. The other improvement was that I now could get rid of all of the messy logging code that also cluttered the code. Virtually all code was logging exceptions and this logging could now be done in one place. Removing checked exceptions this way is imho the cheapest and most effective way to improve your code.
So how do I handle exceptions? Well, for me a function all has two exits: a normal return and an exception. I do not believe exception types matter, only badly designed APIs where exceptions are abused for normal behavior require their types. By having this simplified model, any API can throw any exception and I usually declare "throws Exception" on my API methods so I do not have to catch any lower level exceptions. This model makes it easy for an exception to bubble up to the top level method that knows what to do with an exception. Obviously intermediate functions must use the finally block to ensure that any any resources are properly closed.
For the OSGi APIs we've not followed this model because lots of people still need to get used to ignoring checked exceptions. However, if I see how far we've come since the early days then I think we can one day expect this style to be common.