Why doesn't Java allow to throw a checked exception from static initialization block?

JavaExceptionStatic Initializer

Java Problem Overview


Why doesn't Java allow to throw a checked exception from a static initialization block? What was the reason behind this design decision?

Java Solutions


Solution 1 - Java

Because it is not possible to handle these checked exceptions in your source. You do not have any control over the initialization process and static{} blocks cannot be called from your source so that you could surround them with try-catch.

Because you cannot handle any error indicated by a checked exception, it was decided to disallow throwing of checked exceptions static blocks.

The static block must not throw checked exceptions but still allows unchecked/runtime-exceptions to be thrown. But according to above reasons you would be unable to handle these either.

To summarize, this restriction prevents (or at least makes it harder for) the developer from building something which can result in errors from which the application would be unable to recover.

Solution 2 - Java

You can work around the problem by catching any checked exception and rethrowing it as an unchecked exception. This unchecked exception class works well as a wrapper: java.lang.ExceptionInInitializerError.

Sample code:

protected static class _YieldCurveConfigHelperSingleton {
	
	public static YieldCurveConfigHelper _staticInstance;
	
	static {
		try {
			_staticInstance = new YieldCurveConfigHelper();
		}
		catch (IOException | SAXException | JAXBException e) {
			throw new ExceptionInInitializerError(e);
		}
	}
}

Solution 3 - Java

It would have to look like this (this is not valid Java code)

// Not a valid Java Code
static throws SomeCheckedException {
  throw new SomeCheckedException();
}

but how would ad where you catch it? Checked exceptions require catching. Imagine some examples that may initialize the class (or may not because it is already initialized), and just to draw the attention of the complexity of that it would introduce, I put the examples in another static initalizer:

static {
  try {
     ClassA a = new ClassA();
     Class<ClassB> clazz = Class.forName(ClassB.class);
     String something = ClassC.SOME_STATIC_FIELD;
  } catch (Exception oops) {
     // anybody knows which type might occur?
  }
}

And another nasty thing -

interface MyInterface {
  final static ClassA a = new ClassA();
}

Imagine ClassA had a static initializer throwing a checked exception: In this case MyInterface (which is an interface with a 'hidden' static initializer) would have to throw the exception or handle it - exception handling at an interface? Better leave it as it is.

Solution 4 - Java

> Why doesn't Java allow to throw a checked exception from a static initialization block?

Technically, you can do this. However, the checked exception must be caught within the block.

The actual Java restriction is that a checked exception is not allowed to propagate out of the block.

Technically, it is also possible to allow an unchecked exception to propagate out of a static initializer block1. But it is a really bad idea to do this deliberately! The problem is that the JVM itself catches the unchecked exception, and wraps it and rethrows it as a ExceptionInInitializerError.

NB: that ExceptionInInitializerError is an Error not a regular exception. You should not attempt to recover from it.

In most cases, the exception cannot be caught:

public class Test {
    static {
        int i = 1;
        if (i == 1) {
            throw new RuntimeException("Bang!");
        }
    }
    
    public static void main(String[] args) {
        try {
            // stuff
        } catch (Throwable ex) {
            // This won't be executed.
            System.out.println("Caught " + ex);
        }
    }
}

$ java Test
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: Bang!
    at Test.<clinit>(Test.java:5)

There is nowhere you can place a try ... catch in the above to catch the ExceptionInInitializerError2.

In some cases you can catch it. For example, if you triggered the class initialization by calling Class.forName(...), you can enclose the call in a try and catch either the ExceptionInInitializerError or a subsequent NoClassDefFoundError.

However, if you attempt to recover from an ExceptionInInitializerError you are liable to run into a roadblock. The problem is that before throwing the error, the JVM marks the class that caused the problem as "failed". You simply won't be able to use it. Furthermore, any other classes that depend on the failed class will also go into failed state if they attempt to initialize. The only way forward is to unload all of the failed classes. That might be feasible for dynamically loaded code3, but in general it isn't.

1 - It is a compilation error if a static block unconditionally throws an unchecked exception.
2 - You might be able to intercept it by registering a default uncaught exception handler, but that won't allow you to recover, because your "main" thread can't start.
3 - If you wanted to recover the failed classes, you would need to get rid of the classloader that loaded them.


> What was the reason behind this design decision?

It is to protect the programmer from writing code that throws exceptions that cannot be handled ... because there is no way for the programmer to write a handler.

As we have seen, an exception in a static initializer turns a typical application into a brick. The best thing that the language designers can do help the the programmer is to specified that the checked case 1s a compilation error. Unfortunately, it is not practical to do this for unchecked exceptions as well.


OK, so what should you do if your code "needs" to throw exceptions in a static initializer. Basically, there are two alternatives:

  • If (full!) recovery from the exception within the block is possible, then do that.

  • Otherwise, restructure your code so that the initialization doesn't happen in a static initialization block (or in the initializers of static variables). Put it in a method or constructor that can be called from a regular thread.

Solution 5 - Java

Take a look at the Java Language Specifications: it is stated that it is a compile time error if static initializer fails is able to complete abruptly with a checked exception.

Solution 6 - Java

Since no code you write can call static initialization block, it is not useful to throw checked exceptions. If it were possible, what would the jvm do when a checked exceptions are thrown? Runtimeexceptions are propagated up.

Solution 7 - Java

For example: Spring's DispatcherServlet (org.springframework.web.servlet.DispatcherServlet) handles the scenario which catches a checked exception and throws another unchecked exception.

static {
	// Load default strategy implementations from properties file.
	// This is currently strictly internal and not meant to be customized
	// by application developers.
	try {
		ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
		defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
	}
	catch (IOException ex) {
		throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
	}

Solution 8 - Java

I am able to compile throwing a checked Exception Also....

static {
	try {
		throw new IOException();
	} catch (Exception e) {
         // Do Something
	}
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmissingfaktorView Question on Stackoverflow
Solution 1 - JavaKosi2801View Answer on Stackoverflow
Solution 2 - JavakevinarpeView Answer on Stackoverflow
Solution 3 - JavaAndreas DolkView Answer on Stackoverflow
Solution 4 - JavaStephen CView Answer on Stackoverflow
Solution 5 - JavaLaurent EtiembleView Answer on Stackoverflow
Solution 6 - JavafastcodejavaView Answer on Stackoverflow
Solution 7 - JavapcdhanView Answer on Stackoverflow
Solution 8 - Javauser2775569View Answer on Stackoverflow