Discussions

News: Avoiding Checked Exceptions: Another Unsafe option

  1. Avoiding Checked Exceptions: Another Unsafe option (23 messages)

    We get deja vu when we see anything on the merits, or limits, of unchecked exceptions. Don Schwarz has brought it up again, adding a sneaky/hack option. He discusses the public class sun.misc.Unsafe (which may or may not be around in other JVMs!). It turns out that Sun uses this class in places such as Class.newInstance().

    Conclusion
    I'm not necessarily advocating the use of this method to avoid compile-time checking of exceptions, but I think it's important to know that you have this option. It's a bit of a hack, but hey -- if it's good enough for Sun it must be good enough for us, right?

    There is one place in particular where I can see this method being useful. Some Aspect Oriented Programming (AOP) frameworks, such as AspectJ, have support for automatically "softening" exceptions by wrapping them with an unchecked exception. However, this suffers from the same problem that we highlighted above -- the identity of the exception changes after it is wrapped, and therefore it is more difficult to catch the exception at a higher level. It may be interesting to give these frameworks support for using Unsafe.throwException instead.

    Another interesting idea is to implement an annotation that softens exceptions in this manner. Using either source-code instrumentation (via apt) or bytecode instrumentation (as I described in my Peeking Inside the Box articles), code could be inserted that would use Unsafe.throwException to soften the exceptions. Unlike the AOP approach, this would make it clear from the source code what is happening.

    @Softens{SQLException.class}
    public void loadData (int objId)
    {
        // ...code that throws an SQLException...
    }
    Avoiding Checked Exceptions

    Threaded Messages (23)

  2. Using either source-code instrumentation (via apt) or bytecode instrumentation (as I described in my Peeking Inside the Box articles), code could be inserted that would use Unsafe.throwException to soften the exceptions. Unlike the AOP approach, this would make it clear from the source code what is happening. @Softens{SQLException.class}public void loadData (int objId){ // ...code that throws an SQLException...}
    I like the annotation usage, but bytecode instrumentation wouldn't work because the code would never compile.
  3. Checked exception is a useless feature, but it must be possible to solve this problem without hacks ( compiler option to ignore, warn or report error if exception doe's not extend RuntimeException )
  4. as well as its return value.

    Since I can ignore the return value of a method, I do't really understand, why there are Exceptions I am not allowed to ignore.

    I don't have to write: Object dummy = myMethod(); I can simply write myMethod(); if I don't care what the result of the method is.

    Why am I forced to wrap (checked) exceptions, when the only way I can handle them is to pass them to next one in the call stack?
  5. Declared Exception is NOT a part of method's signature for runtime, it is a part only for compiler.
    Quick experiment:
    set side by side two projects mod1 with
    public class Callee {

      public void printMessage(String msg) [throws Exception] {
        System.out.println( "msg = " + msg );
      }
    }
    and mod2 with
    public class Caller{

      public static void main( String[] args ){
        Callee c = new Callee();
        c.printMessage( "Hi!");
      }
    }


    1st complile Callee without declaring Exception into mod1/classes and Caller into mod2/classes.

    now lets cd mod2 and run
    java -cp classes:../mod1/classes com.kgionline.exception.test.Caller
    it prints: msg = Hi!

    2nd now recompile Callee only with throws Exception in the signature
    java -cp classes:../mod1/classes com.kgionline.exception.test.Caller
    it prints: msg = Hi!

    So: Java _runtime_ does not consider exception declarations to be part of method signature, or it fails to check such a thing.
    Tested on Linux Suse 9.1
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
    Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)
  6. Yes, JVM specification has no Checked Exceptions and this declaration is used by compiler only. There is no technical problems to make this stuff configurable.
  7. Declared Exception is NOT a part of method's signature for runtime, it is a part only for compiler.
    Ever encountered UndeclaredThrowableException? Write a java.lang.reflect.InvocationHandler that throws an IOException, and try creating a Proxy for java.util.List withat that handler, and then call a List method on it.

    The JVM does pay attention to the declared exceptions; just look at the output of javap:


    $ javap java.io.Writer
    Compiled from "Writer.java"
    public abstract class java.io.Writer extends java.lang.Object{
        protected java.lang.Object lock;
        protected java.io.Writer();
        public abstract void close();
           throws java/io/IOException
        public abstract void flush();
           throws java/io/IOException
        public void write(int);
           throws java/io/IOException
        public void write(char[]);
           throws java/io/IOException
        public abstract void write(char[],int,int);
           throws java/io/IOException
        protected java.io.Writer(java.lang.Object);
        public void write(java.lang.String);
           throws java/io/IOException
        public void write(java.lang.String,int,int);
           throws java/io/IOException
    }
  8. From Javadoc:
    If the invoke method throws a checked exception that is not assignable to any of the exception types declared by the method in one of the the proxy interfaces that it can be invoked through, then an unchecked UndeclaredThrowableException will be thrown by the invocation on the proxy instance. This restriction means that not all of the exception types returned by invoking getExceptionTypes on the Method object passed to the invoke method can necessarily be thrown successfully by the invoke method.
    So, UndeclaredThrowableException is caused but proxy implementation and has nothing to do with JVM, which does provide information but does not use it.

    Have you repeated my experiment? Can you explain it differently than :Declared Exception is NOT a part of method's signature for runtime ?
  9. as well as its return value.Since I can ignore the return value of a method, I do't really understand, why there are Exceptions I am not allowed to ignore.I don't have to write: Object dummy = myMethod(); I can simply write myMethod(); if I don't care what the result of the method is. Why am I forced to wrap (checked) exceptions, when the only way I can handle them is to pass them to next one in the call stack?
    I'm sympathetic to this argument to a degree but IMO most problems caused by checked exceptions are because they are used inapropriately. An example are the various exceptions thrown in the EJB API - these almost always indicate a fatal configuration problem and should really be runtime exceptions.

    Paul C.
  10. in the end...[ Go to top ]

    ...it all comes down to the same point over and over again, after reading quite a bunch of articles on the Ecpetion-Handling-Topic: make a good design of you application, think about what you are doing, and enforce all on your team to stick to the conventions made.
    i know, this does not help or avoid commonly made human mistakes, but that's an inevidable side-effect of technology: imperfectness...
  11. in the end...[ Go to top ]

    ...it all comes down to the same point over and over again, after reading quite a bunch of articles on the Ecpetion-Handling-Topic: make a good design of you application, think about what you are doing, and enforce all on your team to stick to the conventions made.i know, this does not help or avoid commonly made human mistakes, but that's an inevidable side-effect of technology: imperfectness...
    Yeap, however, certain tricks help avoiding mistakes.
    I am big time supporter of checked exceptions and exception wrapping and chaining, but sometimes it is necessary not to chain: one place would be a remotely called method that throws a MyBusineessTierException. If the exception hold remote cause of type MyLowLevelImplementationLayerException than most likely it will cause additional RMI deserialization exception on client side because client has no knowledge of MyLowLevelImplementationLayerException ( and should not). So, on system boundaries it might be necessary to rethrow only known to upper layers exception(s) and log and throw away all others.

    Another trick to employ: use autogenerated Proxy classes or system aspectization, that allows much cleaner code: see example at http://kgionline.com/xflow2/doc/xflow2/code_tricks.html and an article that compares Proxy based approaches with AspectWerkz AOP and does some performance comparisons at: http://kgionline.com/articles/aop_1/aop1.jsp#aspectwerkz
    So my advice: avoid unchecked exceptions and take full advantage of checked exceptions.

    However, I do understand that there are people who does not like checked exceptions. I think there is a better solution that will pacify two camps: have compiler flag that will tell compiler not to enforce exception checking. It looks like Java runtime itself does not care about exception type and does not seem to consider exceptions as part of method signature, so one camp will compile with the flag and another without.
    It is as simple as that.
  12. Konstantin:

    I think there is a better solution that will pacify two camps: have compiler flag that will tell compiler not to enforce exception checking.
    Just like you I am also a strong proponent for checked exceptions.

    However, I am failing to see how you can make exception checking configurable. 3rd party libraries compiled without checked exceptions will become inherently useless if your code does intend to check exceptions. How do you plan on catching exceptions thrown by external libraries in your code if library's method signature does not declare them?

    Is the proposed solution somewhere in the lines of "rely on non-existent documentation"?

    Regards,
    --Dmitriy.
  13. Konstantin:I think there is a better solution that will pacify two camps: have compiler flag that will tell compiler not to enforce exception checking.
    Just like you I am also a strong proponent for checked exceptions.However, I am failing to see how you can make exception checking configurable. 3rd party libraries compiled without checked exceptions will become inherently useless if your code does intend to check exceptions. How do you plan on catching exceptions thrown by external libraries in your code if library's method signature does not declare them?Is the proposed solution somewhere in the lines of "rely on non-existent documentation"?Regards,--Dmitriy.
    I understand and share your concerns... but there is no defense against libraries and frameworks if their developers decided to use unchecked exceptions.
    Well, we are always free not to use such libraries...
    At least my proposed solution does not enforce [unnecessary] requirements on people with different mindset: they have rights to exist and enjoy convenience as they understand it.
  14. It is trivial " 3rd party" problem doe's not exist, all exceptions are "runtime" exceptions in JVM. This flag doe's not need to change any compiled code, compiler can produce the same code with this flag and without it. I think the best way is to drop this error prone feature, but compiler flag is a good compromise too.
  15. This flag doe's not need to change any compiled code, compiler can produce the same code with this flag and without it. I think the best way is to drop this error prone feature, but compiler flag is a good compromise too.
    Such flag would allow not to declare possible exceptions in the method signature.
    Although compiller can catch undeclared checked/unchecked exceptions on demand and display warnings/errors which could be configurable too. I mean it is possible to say that I would like to ignore non-declarations in package org.springfamework.* but please tell me about anything else. Even more, compiler can display list of possible RuntimeExceptions for my calls to a library...
    I guess I am heading towards declaring all Exceptions as checked and make checking configurable at compiler level: what exceptions to ignore, what packages are exempt, where to enforce exception checking…. something like that.
  16. I have to agree with the subject line (though the hacker in me likes the neat hack of the original article).
    I know that is lecturing but nobody has pointed it out yet:
    The ONLY source of checked exceptions is where the author of the method has deliberately CHOSEN to throw them. In some cases the author was writing system libraries so we have no choice about using their code, but the story is the same - checked exceptions are not something that just 'happens' (excepting all of those droll little programs composed entirely of public void method() throws Exception).

    By declaring checked exceptions you specify exception handling as mandatory for the caller - ie the exception is a expected, integral part of the operation logic [not that I am entirely guiltless on the 'catch (Exception e) {}' pattern].
    If you don't think you method should declare throwing an exception then you should have caught it and translated it in a way that is appropriate to your interface - simple as that.

    It's harsh, and a pest for simple programs, but Java is a software engineering language - concise definition of interface logic is essential in this context. If you are ignoring part of the declared method contract you are not writing a application or library you are writing a hack, and hacks are allowed to be messy

    I have to admit that the reality checked exceptions and exception handling are a bit messy, but the principles are sound.
  17. I know that is lecturing but nobody has pointed it out yet:The ONLY source of checked exceptions is where the author of the method has deliberately CHOSEN to throw them. ..... If you don't think you method should declare throwing an exception then you should have caught it and translated it in a way that is appropriate to your interface - simple as that.
    It likes that you totally divert practice of ever rethrowing errors as RuntimeExceptions. What you then counsil to do with such exceptions as IO- or Naming- which are unlikely to occur at runtime in enterprise apps - instead, these usually indicate that system wasn't correctly deployed?

    Why to bother on declaration in cases when no meanignful reaction from your app or end-ser could exist?

    --
    Mike Skorik
    http://www.100kSolutions.com
  18. Why to bother on declaration in cases when no meanignful reaction from your app or end-ser could exist?--Mike Skorik
    Easy reasons:
      because the author of the method doesn't know whether the end-user/application can do anything with the Exception

      so that the end-user is made aware that a specific problem can occur, and that they have to deal with it whether or not they like it (even if that is only to crumple gracefully in a heap).

    This is particularly important when the end-user invokes a method in one (visible) library, which then invokes a method in another (invisible) library (etc) that the end-user knows nothing about.

    Sure it is a pain. But forcing people to think about errors leads to more robust systems.
  19. But forcing people to think about errors leads to more robust robust .
    Design by exception leads to systems with side effects, robust systems produce core dump and die on error without side effect.
  20. |
    |robust systems produce core dump and die
    |

    Que?

    Robust systems handle errors *properly*, and keep running.

    In tune with the above post: Checked exceptions on an interface force you to think about the errors that the author of the method chose for you to handle -and you can handle them appropriately.
    If the author of said method thought there was an error that you couldnt handle (ie fatal), then its likely it would have been an unchecked exception.

    Ultimately, checked exceptions force developers to do work "up-front" in working out where and how to handle erros.

    As peoples' experience in .net (and past experience in C++) is showing, the alternative to the "up-front" worrying about error handling is "in-production".

    Modern IDE's like Eclipse and IntelliJ (esp IntelliJ) have taken most of the dog-work out of checked exception handling.

    Sadly, the *thinking* required for error handling (regardless of checked/unchecked) is still down to the developer...
  21. This thread has started me musing. When I started coding in Java from VB background about 7 or 8 years ago I hated checked exceptions. I found them a pain to work with, and thought they were unnecessary. Then I put my first major J2EE app into production and it was rock solid. I had second thoughts.

    If Hejlsberg had come up with a better alternative for C# (and ’m sure someday someone will for whatever language it is that eventually takes over from Java) then all well and good, but as it is I think that his decision to not include checked exceptions in C# was a mistake. Here’s why. I worked on a .NET project last year and the problems we had with error handling where dramatic, to say the least. Now some of this came down to the very immature nature of the .NET libraries themselves (things like the array library catching every exception and always throwing an array out of bounds exception without setting the inner exception property so you never knew what error had actually occurred, or system.io.file and system.io.directory types returning false to the caller whenever anything goes wrong; so does the file not exist, do I have a permissions problem, has a stack overflow or out of memory exception occurred? - The sorts of things that Java used to suffer from 8 or 9 years ago). There were other reasons: most of the development team had lots of experience of building Visual Basic/ASP apps but little Java or .NET experience, and the MSDN documentation was awful. But the lack of checked exceptions also meant that errors frequently went unhanded at a local level (a problem compounded by the documentation’s reluctance to tell you what exceptions a particular method could generate). This made problems difficult to diagnose, particularly when the project went to pilot and we could no longer attach debuggers to it. It means that after almost a year of testing and debugging it still isn’t in full production. It also means that .NET is no longer the strategic technology platform for that client.

    The great thing about checked exceptions is that they force you to think about error handling. You can still ignore them if you want, but you can’t do it without knowing that is what you’re doing (a major difference from the on error goto generic_error handler of VB and C#.) – I find having an empty catch block is a great reminder that I have work to do – it makes me feel uncomfortable until I sort it out. And I’m a firm believer in handling exceptions as locally as possible because of the level of diagnostic information that it gives you (as anyone who has to work out what when wrong on a crucial set of transactions at 3 in the morning can testify). I’ve seen a lot of counter arguments to this like “you end up with hundreds of exceptions to handle and it all balloons out of control” but I’ve actually never found this to be the case in practice and I’ve now worked on several very large Java applications. I’d go as far as to say if exceptions aren’t checked then what is the point of them?
  22. The problem with wrapped exceptions[ Go to top ]

    I subscribe to the idea of having a fallback exception handler but have some reservations about wrapped exceptions [at least the way I understand it]. The implementation assumes a certain deployment scenario. What happens if you have a tiered architecture and no two tiers are co-located? How do you lookup the root cause exception if those libraries do not exist in your tier?
  23. Hacks[ Go to top ]

    The whole annotation thing looks to me like just a big hack.

    I think this all came up when people started using Java heavily for online transaction processing, and since OO languages don't fit OLTP that well, we ended up with this ugly annotation thing. It would have been better to design a new language which plays well with Java.

    I don't usually think nice things about Microsoft, but with the CLI and multiple language thing they definitely had the right idea.

    I guess every language eventually gets ruined when it gets old enough. I just didn't realize that for Java we were already there.

    Guglielmo
  24. ... support for automatically "softening" exceptions by wrapping them with an unchecked exception. However, this suffers from the same problem that we highlighted above -- the identity of the exception changes after it is wrapped, and therefore it is more difficult to catch the exception at a higher level.
    Wrapping exception as Unchecked means that you want throw it onto highest possible level isn't it? Where's discrepancy?

    As to me - I usually just configure 'System Error, please contact the vendor.' page in web.xml for it.

    --
    Mike Skorik
    http://www.100kSolutions.com