Forbidden Java actions: not declaring a checked exception; avoiding a constructor while creating an object

by Mikhail Vorontsov

This is the last article in the series of “Forbidden Java actions” articles. The two previous articles are Forbidden Java actions: object assignments, type conversions etc on the low level in Java and Forbidden Java actions: updating final and static final fields.

In this article we will see how to throw a checked exception in Java without declaring it in the method throws clause and how to create an object without calling any of its constructors.

Throwing a checked exception without letting know about it in the method signature

In Java you have to declare all checked exceptions in the throws clause of your method signature. This is a Java language requirement, JVM does not need this information. Let us prove it by finding a few ways to throw a checked exception while avoiding to declare it.

Thread.stop( Throwable )

The first way to throw a checked exception is to use a deprecated Thread.stop( Throwable ) method, which throws a given exception in the given thread. Don’t use this method in the production code! The following method will print “test” followed by “99”, which proves that thread won’t actually die 🙂

1
2
3
4
5
6
7
8
9
10
11
12
private static void threadStop()
{
    try
    {
        Thread.currentThread().stop( new IOException( "test" ) );
    }
    catch ( Exception ex )
    {
        System.out.println( ex.getMessage() );
    }
    System.out.println( 99 );
}
private static void threadStop()
{
    try
    {
        Thread.currentThread().stop( new IOException( "test" ) );
    }
    catch ( Exception ex )
    {
        System.out.println( ex.getMessage() );
    }
    System.out.println( 99 );
}

Class.newInstance

The next library method which could throw a checked exception but does not declare it is Class.newInstance. Another reflection API method with a similar functionality, Constructor.newInstance wraps such exceptions in a checked InvocationTargetException.

In order to use Class.newInstance flaw, we need to define a static exception field, which will be used by our own class constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static void reflectionThrow( final Exception ex )
{
    ReflectionThrow.m_exc = ex;
    try {
        ReflectionThrow.class.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } finally {
        ReflectionThrow.m_exc = null; //avoid memory leak
    }
}
 
private static final class ReflectionThrow
{
    public static Throwable m_exc;
 
    public ReflectionThrow() throws Throwable {
        throw m_exc;
    }
}
private static void reflectionThrow( final Exception ex )
{
    ReflectionThrow.m_exc = ex;
    try {
        ReflectionThrow.class.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } finally {
        ReflectionThrow.m_exc = null; //avoid memory leak
    }
}

private static final class ReflectionThrow
{
    public static Throwable m_exc;

    public ReflectionThrow() throws Throwable {
        throw m_exc;
    }
}

Unfortunately, we can’t make ths code shorter by defining a ReflectionThrow class inside reflectionThrow method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static void reflectionThrowInner( final Exception ex )
{
    class ReflectionThrowInner
    {
        public ReflectionThrowInner() throws Exception {
            throw ex;
        }
    }
 
    try {
        ReflectionThrowInner.class.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
private static void reflectionThrowInner( final Exception ex )
{
    class ReflectionThrowInner
    {
        public ReflectionThrowInner() throws Exception {
            throw ex;
        }
    }

    try {
        ReflectionThrowInner.class.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

If you’ll try to execute reflectionThrowInner method, you will get the following exception:

java.lang.InstantiationException: com.mvorontsov.javaperf.tricks.illegal.Exceptions$1ReflectionThrowInner
at java.lang.Class.newInstance0(Class.java:359)
at java.lang.Class.newInstance(Class.java:327)
at com.mvorontsov.javaperf.tricks.illegal.Exceptions.reflectionThrowInner(Exceptions.java:69)

It is thrown because an inner class has a hidden constructor parameter – a reference of enclosing class. Unfortunately, we can’t pass it via parameterless Class.newInstance method.

Generic type erasure

The next way to throw a checked exception is based on generics. You need to remember that a type parameter is checked only at a compile time. At runtime you may pass any exception because there is no actual type checking is happening at runtime

1
2
3
4
5
6
7
8
9
10
11
12
13
private static class ThrowEx<T extends Throwable>
{
    public static void genericThrow( final Throwable ex )
    {
        //throwGeneric throws a RuntimeException at compile time, so there is not need
        //to declare it on genericThrow. At runtime type is erased and we can pass any Throwable.
        new ThrowEx<RuntimeException>().throwGeneric( ex );
    }
 
    private void throwGeneric( final Throwable ex ) throws T {
        throw (T)ex; //unchecked cast here
    }
}
private static class ThrowEx<T extends Throwable>
{
    public static void genericThrow( final Throwable ex )
    {
        //throwGeneric throws a RuntimeException at compile time, so there is not need
        //to declare it on genericThrow. At runtime type is erased and we can pass any Throwable.
        new ThrowEx<RuntimeException>().throwGeneric( ex );
    }

    private void throwGeneric( final Throwable ex ) throws T {
        throw (T)ex; //unchecked cast here
    }
}


The ideas of the three previous sections were taken from J. Bloch and N. Gafter fantastic “Java Puzzlers: Traps, Pitfalls, and Corner Cases” book. You can find a lot more Java corner cases described in that book.

sun.misc.Unsafe

The last way to throw a checked exception is to use sun.misc.Unsafe method, which is called surprisingly predictable – throwException:

1
2
3
4
private static void unsafeThrow( final Exception ex )
{
    unsafe.throwException( ex );
}
private static void unsafeThrow( final Exception ex )
{
    unsafe.throwException( ex );
}

Using sun.misc.Unsafe requires the following static block in your class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static final Unsafe unsafe;
static
{
    try
    {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        unsafe = (Unsafe)field.get(null);
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
}
private static final Unsafe unsafe;
static
{
    try
    {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        unsafe = (Unsafe)field.get(null);
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
}

Creating an object without calling its constructor

Now let’s review how to create an object without calling an object constructor.

Cloning an object

The first way to avoid a constructor call while creating an object is to use Object.clone method: it makes a shallow copy of an object: all primitive values are copied by value, all objects (including arrays) are copied by reference – only a top level reference is copied, no deep copy occurs. As a result, in order to properly implement a clone method, you need:

  1. Mark your class as Cloneable – this market interface will allow your class users to call clone method.
  2. Inside clone call super.clone first – it will return you an object of an appropriate type with all fields shallow copied. Before returning this object you may need to make a defensive copies of mutable fields as well as any collections.

The following code shows a possible clone implementation. It does not make a defensive copy of an array in order to show that a cloned array uses the same reference as an original array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private static void testClone() throws CloneNotSupportedException {
    final TestClass test = new TestClass();
    test.init();
    if ( !test.isValid() )
        System.out.println( "Not valid original!" );
    final TestClass copy = (TestClass) test.clone();
    if ( !copy.isValid() )
        System.out.println( "Copy not valid!" );
    if ( test.ar != copy.ar )
        System.out.println( "Not shared Integer");
}
 
private static final class TestClass implements Cloneable
{
    public String s;
    public Integer intFirst;
    private int intSecond;
    private boolean bool;
    private double dbl;
    public Long[] ar = new Long[ 2 ];
 
    public TestClass()
    {
        System.out.println( "Constructor" );
    }
 
    public void init()
    {
        s = "test";
        intFirst = 73;
        intSecond = 12;
        bool = true;
        dbl = 0.75;
        ar[ 0 ] = 10L;
        ar[ 1 ] = 11L;
        System.out.println( "init method called" );
    }
 
    public boolean isValid()
    {
        System.out.println( "isValid method called" );
        return s.equals( "test" ) && intFirst == 73 && intSecond == 12 && bool && dbl == 0.75 && ar[ 0 ] == 10L &&
                ar[ 1 ] == 11L;
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //TestClass.ar should be copied defensively, but we won't do it on purpose
        return super.clone();
    }
}
private static void testClone() throws CloneNotSupportedException {
    final TestClass test = new TestClass();
    test.init();
    if ( !test.isValid() )
        System.out.println( "Not valid original!" );
    final TestClass copy = (TestClass) test.clone();
    if ( !copy.isValid() )
        System.out.println( "Copy not valid!" );
    if ( test.ar != copy.ar )
        System.out.println( "Not shared Integer");
}

private static final class TestClass implements Cloneable
{
    public String s;
    public Integer intFirst;
    private int intSecond;
    private boolean bool;
    private double dbl;
    public Long[] ar = new Long[ 2 ];

    public TestClass()
    {
        System.out.println( "Constructor" );
    }

    public void init()
    {
        s = "test";
        intFirst = 73;
        intSecond = 12;
        bool = true;
        dbl = 0.75;
        ar[ 0 ] = 10L;
        ar[ 1 ] = 11L;
        System.out.println( "init method called" );
    }

    public boolean isValid()
    {
        System.out.println( "isValid method called" );
        return s.equals( "test" ) && intFirst == 73 && intSecond == 12 && bool && dbl == 0.75 && ar[ 0 ] == 10L &&
                ar[ 1 ] == 11L;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //TestClass.ar should be copied defensively, but we won't do it on purpose
        return super.clone();
    }
}

After running this code, you will see that a constructor was called only once in this example:

Constructor
init method called
isValid method called
isValid method called

Serialization

The next way to avoid calling an object constructor is to use Java serialization. In order to make a class serializable, you need to mark it with Serializable marker interface. Remember that all fields of a class must be serializable as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private static void testSerialize() throws IOException, ClassNotFoundException {
    System.out.println( "testSerialize" );
    final TestClass test = new TestClass();
    test.init();
    if ( !test.isValid() )
        System.out.println( "Not valid original!" );
    //write an object
    final ByteArrayOutputStream bos = new ByteArrayOutputStream( 256 );
    final ObjectOutputStream os = new ObjectOutputStream( bos );
    os.writeObject( test );
 
    //read it back from a serialized form
    final ObjectInputStream is = new ObjectInputStream( new ByteArrayInputStream( bos.toByteArray() ) );
    final TestClass copy = (TestClass) is.readObject();
    if ( !copy.isValid() )
        System.out.println( "Copy not valid!" );
}
 
private static final class TestClass implements Cloneable, Serializable
{
    public String s;
    public Integer intFirst;
    private int intSecond;
    private boolean bool;
    private double dbl;
    public Long[] ar = new Long[ 2 ];
 
    public TestClass()
    {
        System.out.println( "Constructor" );
    }
    //and as in the previous example
private static void testSerialize() throws IOException, ClassNotFoundException {
    System.out.println( "testSerialize" );
    final TestClass test = new TestClass();
    test.init();
    if ( !test.isValid() )
        System.out.println( "Not valid original!" );
    //write an object
    final ByteArrayOutputStream bos = new ByteArrayOutputStream( 256 );
    final ObjectOutputStream os = new ObjectOutputStream( bos );
    os.writeObject( test );

    //read it back from a serialized form
    final ObjectInputStream is = new ObjectInputStream( new ByteArrayInputStream( bos.toByteArray() ) );
    final TestClass copy = (TestClass) is.readObject();
    if ( !copy.isValid() )
        System.out.println( "Copy not valid!" );
}

private static final class TestClass implements Cloneable, Serializable
{
    public String s;
    public Integer intFirst;
    private int intSecond;
    private boolean bool;
    private double dbl;
    public Long[] ar = new Long[ 2 ];

    public TestClass()
    {
        System.out.println( "Constructor" );
    }
    //and as in the previous example

This example will print the same output as a previous one. There is one difference between cloning and serializing – cloning makes a shallow copy, serialization makes a deep copy of an object. Cloning works inside the same instance of a JVM only, serialized object could be stored into persistent storage and could be reloaded later in a different JVM.

sun.misc.Unsafe initialization

The last way to create an object without calling its constructor is to use unsafe.allocateInstance(Class) method. It creates an instance of an object, but it leaves all fields in the uninitialized state (0, null, false), which corresponds to a memory block filled with zeroes in terms of C. This approach is a little limited – you can’t create a few system class instances with it – for example, you will get an access violation if you’ll try to allocate an instance of String.

Now we can implement an Unsafe version of our own cloning method. We will allocate an empty object using unsafe.allocateInstance(Class) and then populate all top level fields using Unsafe get/put methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static void copyField( final Object src, final Object dest, final Field fld )
{
    final long offset = unsafe.objectFieldOffset(fld);
    if ( fld.getType() == byte.class )
        unsafe.putByte( dest, offset, unsafe.getByte( src, offset ) );
    else if ( fld.getType() == boolean.class )
        unsafe.putBoolean( dest, offset, unsafe.getBoolean( src, offset ) );
    else if ( fld.getType() == short.class )
        unsafe.putShort( dest, offset, unsafe.getShort( src, offset ) );
    else if ( fld.getType() == char.class )
        unsafe.putChar( dest, offset, unsafe.getChar( src, offset ) );
    else if ( fld.getType() == int.class )
        unsafe.putInt( dest, offset, unsafe.getInt( src, offset ) );
    else if ( fld.getType() == long.class )
        unsafe.putLong( dest, offset, unsafe.getLong( src, offset ) );
    else if ( fld.getType() == float.class )
        unsafe.putFloat( dest, offset, unsafe.getFloat( src, offset ) );
    else if ( fld.getType() == double.class )
        unsafe.putDouble( dest, offset, unsafe.getDouble( src, offset ) );
    else
        unsafe.putObject( dest, offset, unsafe.getObject( src, offset ));
}
 
private static Object unsafeClone( final Object obj ) throws InstantiationException {
    final Object res = unsafe.allocateInstance( obj.getClass() );
    for ( final Field fld : obj.getClass().getDeclaredFields() )
        copyField( obj, res, fld );
    return res;
}
private static void copyField( final Object src, final Object dest, final Field fld )
{
    final long offset = unsafe.objectFieldOffset(fld);
    if ( fld.getType() == byte.class )
        unsafe.putByte( dest, offset, unsafe.getByte( src, offset ) );
    else if ( fld.getType() == boolean.class )
        unsafe.putBoolean( dest, offset, unsafe.getBoolean( src, offset ) );
    else if ( fld.getType() == short.class )
        unsafe.putShort( dest, offset, unsafe.getShort( src, offset ) );
    else if ( fld.getType() == char.class )
        unsafe.putChar( dest, offset, unsafe.getChar( src, offset ) );
    else if ( fld.getType() == int.class )
        unsafe.putInt( dest, offset, unsafe.getInt( src, offset ) );
    else if ( fld.getType() == long.class )
        unsafe.putLong( dest, offset, unsafe.getLong( src, offset ) );
    else if ( fld.getType() == float.class )
        unsafe.putFloat( dest, offset, unsafe.getFloat( src, offset ) );
    else if ( fld.getType() == double.class )
        unsafe.putDouble( dest, offset, unsafe.getDouble( src, offset ) );
    else
        unsafe.putObject( dest, offset, unsafe.getObject( src, offset ));
}

private static Object unsafeClone( final Object obj ) throws InstantiationException {
    final Object res = unsafe.allocateInstance( obj.getClass() );
    for ( final Field fld : obj.getClass().getDeclaredFields() )
        copyField( obj, res, fld );
    return res;
}

Summary

  • There are several ways to avoid declaring a checked exception in a method which throws it. You can use Thread.stop(Throwable), Class.newInstance (and throw an exception in the constructor), sun.misc.Unsafe.throwException or use generic type erasure in order to avoid a checked exception declaration in the throws clause. We do not recommend you to use any of these practices 🙂
  • In Java you may create an object without calling any of its constructors. There are 2 legal ways to do it – cloning and serializing. sun.misc.Unsafe allows you to create an uninitialized instance of an object bypassing its constructors using Unsafe.allocateInstance method.