DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How To Create a Stub in 5 Minutes
  • Ways To Reduce JVM Docker Image Size
  • Java: A Time-Tested Programming Language Still Going Strong
  • Java Code Review Solution

Trending

  • Unlocking AI Coding Assistants Part 1: Real-World Use Cases
  • Java's Quiet Revolution: Thriving in the Serverless Kubernetes Era
  • Evolution of Cloud Services for MCP/A2A Protocols in AI Agents
  • Event-Driven Architectures: Designing Scalable and Resilient Cloud Solutions
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Throwing Undeclared Checked Exceptions

Throwing Undeclared Checked Exceptions

By 
Luigi Viggiano user avatar
Luigi Viggiano
·
Sep. 15, 10 · Interview
Likes (0)
Comment
Save
Tweet
Share
25.8K Views

Join the DZone community and get the full member experience.

Join For Free

Sometimes checked exceptions can be a problem. For instance, recently I tried to implement some common logic to retry failing network operations and it resulted in a kind of command pattern on which, as usual, the execute() method throws java.lang.Exception. That complicated the caller code which has to catch and handle java.lang.Exception instead of the more specific exceptions...

I knew that checked exceptions are enforced by the compiler, while in the virtual machine there is nothing preventing a checked exception to be thrown by a method not declaring it, so I started to check on internet how to implement this.
I found two posts on Anders Noras's blog (#1 #2) on how to perform this magic.

Method #1: the sun.misc.Unsafe class

import java.lang.reflect.Field;
import sun.misc.Unsafe;

public class UnsafeSample {
    public void methodWithNoDeclaredExceptions( ) {
        Unsafe unsafe = getUnsafe();
        unsafe.throwException( new Exception( "this should be checked" ) );
    }

    private Unsafe getUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main( String[] args ) {
        new UnsafeSample().methodWithNoDeclaredExceptions();
    }
}

This makes use of internal Sun JRE libraries implementation classes. It could not work if you use a non Sun VM. And in fact it doesn't if you use GCJ (The GNU compiler for Java).
The getUnsafe() method exposed above does some tricks to access a private field in the Unsafe class, because Unsafe.getUnsafe() can only be called by classes loaded by the bootstrap ClassLoader.

See also the article Avoiding Checked Exceptions by Don Schwarz.

Method #2: the Thread.stop(Exception)

public class ThreadStopExample {

    @SuppressWarnings("deprecation")
    public void methodWithNoDeclaredExceptions( ) {
        Thread.currentThread().stop(new Exception( "this should be checked" ));
    }

    public static void main( String[] args ) {
        new ThreadStopExample().methodWithNoDeclaredExceptions();
    }
}

This uses a deprecated method, but works. No portability issue, until the Java specification guys decide to remove the method.
It could have some side effects on the current thread as we are calling stop(). I'm not sure.

Method #3: using Class.newInstance()

Look at the signature of java.lang.Class.newInstance() and compare it to Constructor.newInstance()

public final class Class  ... {
    public T newInstance()
        throws InstantiationException, IllegalAccessException
}

public final class Constructor ... {
    public T newInstance(Object ... initargs)
    throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
}

You see it? no InvocationTargetException!
If you call SomeObject.class.newInstance() and the constructor throws an exception, the exception doesn't get wrapped into the InvocationTargetException (that is a checked exception).
So you can write an utility class like this, to throw checked exceptions without needing to declare them on the method signature.

public class Exceptions {
    private static Throwable throwable;

    private Exceptions() throws Throwable {
        throw throwable;
    }

    public static synchronized void spit(Throwable throwable) {
        Exceptions.throwable = throwable;
        try {
            Exceptions.class.newInstance();
        } catch(InstantiationException e) {
        } catch(IllegalAccessException e) {
        } finally {
            Exceptions.throwable = null;
        }
    }
}

public class TestExceptionSpit {
    public static void main(String[] args) {
        Exceptions.spit(new Exception( "this should be checked" ));
    }
}

Internally the Class.newInstance() uses the sun.misc.Unsafe class, but in this case this technique is fully portable because you are not using any deprecated or internal method. In fact it works also with GCJ JVM.
I tried to remove the synchronization stuff and the static field using an inner class, but it seems that the compiler does some strange trick translating the empty constructor in something else preventing Class.newInstace() to be used on that inner class.

The behavior of the Class.newInstance() is also documented:

"Note that this method propagates any exception thrown by the nullary
constructor, including a checked exception. Use of this method
effectively bypasses the compile-time exception checking that would
otherwise be performed by the compiler."

So your code is fully safe and compliant to the rules :)

Method #4: the sun.corba.Bridge

import java.rmi.RemoteException;

public class Bridge {
    public void methodWithNoDeclaredExceptions( ) {
        sun.corba.Bridge.get().throwException(new RemoteException("bang!"));
    }

    public static void main( String[] args ) {
        new Bridge().methodWithNoDeclaredExceptions();
    }
}

This is more or less the same as using the Unsafe.class. The difference is that in this case you don't need to do the reflection stuff to access the private field "theUnsafe", because the Bridge class is doing that for you. Still using an internal JRE class with same portability issues.

Method #5: Generics

The following example takes advantage of the fact that the compiler does not type check generics...

import java.rmi.RemoteException;

class Thrower {
    public static void spit(final Throwable exception) {
        class EvilThrower<T extends Throwable> {
            @SuppressWarnings("unchecked")
            private void sneakyThrow(Throwable exception) throws T {
                throw (T) exception;
            }
        }
        new EvilThrower().sneakyThrow(exception);
    }
}

public class ThrowerSample {
    public static void main( String[] args ) {
        Thrower.spit(new RemoteException("go unchecked!"));
    }
}

Credits to "Harald" that posted a comment on Johannes Brodwall's blog.
I personally think this last one is the best solution: it uses a feature of the compiler against itself.

Conclusions

I think that having checked exception in Java is better than not having it. I already expressed why I am in favor of checked exceptions here. It's a design decision, you can choose to make your exceptions checked or unchecked, if you want to force your client to handle them or not; you can't do that on .NET, where checked exceptions simply do not exist.

Sometimes you have (or you have to write) methods throwing java.lang.Exception, and you get into the trap. So you may like to know that there is a dirty escape, and you can decide to use it or not... we saw that Sun is throwing undeclared checked exceptions in Class.newInstace(), ask yourself: if this is good for the JRE code, could it be good also for yours?

Usually you can wrap checked exception into RuntimeExceptions but this doesn't simplify the client code, because the caller in case of needing has to catch the RuntimeException, unwrap the cause and deal with it. Maybe a new Java keyword to throw checked exception without requiring the caller to handle them could help: I recommend reading post on Ricky Clarkson's about checked exceptions.

Finally I come to the decision to not use those tricks in my object doing the retry logic, and keep the messy catch logic on the caller code. In case of needing I will evaluate to use a Dynamic Proxy doing the retry logic and keeping its behavior transparent to the client.

To those who wants unchecked exceptions in Java... well, there is the way to have it: the example with Generics is a clean way to have it. Use it if you want, at your own risk.
Personally I would choose to use libraries with checked exceptions...

Other related articles

Friday Free Stuff by Chris Nokleberg, uses bytecode manipulation.
Don't Try This at Home by Bob Lee, exposes some methods also covered above.

 

From: http://en.newinstance.it/2008/11/17/throwing-undeclared-checked-exceptions/

Virtual Machine code style Java (programming language) Command pattern Common Logic JRE POST (HTTP) Blog

Opinions expressed by DZone contributors are their own.

Related

  • How To Create a Stub in 5 Minutes
  • Ways To Reduce JVM Docker Image Size
  • Java: A Time-Tested Programming Language Still Going Strong
  • Java Code Review Solution

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!