How to programmatically enable assert?

11,554

Solution 1

This was a comment to @bala's good answer, but it got too long.

If you just enable assertions then call your main class--your main class will be loaded before assertions are enabled so you will probably need a loader that doesn't reference anything else in your code directly. It can set the assertions on then load the rest of the code via reflection.

If assertions aren't enabled when the class is loaded then they should be "Compiled Out" immediately so you are not going to be able to toggle them on and off. If you want to toggle them then you don't want assertions at all.

Due to runtime compiling, something like this:

public myAssertNotNull(Object o) {
    if(checkArguments) 
        if(o == null)
            throw new IllegalArgumentException("Assertion Failed");
}

Should work nearly as fast as assertions because if the code is executed a lot and checkArguments is false and doesn't change then the entire method call could be compiled out at runtime which will have the same basic effect as an assertion (This performance depends on the VM).

Solution 2

Try

ClassLoader loader = getClass().getClassLoader();
setDefaultAssertionStatus(true);

or

ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);

EDIT:

based on the comments

    ClassLoader loader = ClassLoader.getSystemClassLoader();
    loader.setDefaultAssertionStatus(true);
    Class<?> c = loader.loadClass("MyClass");
    MyClass myObj = (MyClass) c.newInstance();


public class MyClass {

    private static final int foo[] = new int[]{4,5,67};
    MyClass()
    {
        assert foo.length == 10;
    }
}

Solution 3

You can enable/disable assertions programmatically too:
http://download.oracle.com/docs/cd/E19683-01/806-7930/assert-5/index.html

Solution 4

The simplest & best way can be:

public static void assertion(boolean condition, String conditionFailureMessage)
{
    if(!condition)
        throw new AssertionError(conditionFailureMessage);
}

No need to set -ea as VM argument .

call the function like :

assertion(sum>=n,"sum cannot be less than n");

If assertion fails, code will give AssertionError, else code will run safely.

Solution 5

It is possible to enable or disable assertions using reflection. As usual with reflection, the solution is fragile and may not be appropriate for all usage scenarios. However, if applicable and acceptable, it is more flexible than setClassAssertionStatus because it allows to enable/disable assertions checks at various points in the execution, even after the class is initialized.

This technique requires a compiler that generates a synthetic static field to indicate whether assertions are enabled or not. For example, both javac and the Eclipse compiler generate field $assertionsDisabled for any class that contains an assert statement.

This can be verified as follows:

public class A {
    public static void main(String[] args) {
        assert false;
        System.out.println(Arrays.toString(A.class.getDeclaredFields()));
    }
}

Setting the desired assertion status just comes down to setting this field (note the inverted boolean value):

// Helper method in any class
public static void setAssertionsEnabled(Class<?> clazz, boolean value) 
    throws ReflectiveOperationException
{
    Field field = clazz.getDeclaredField("$assertionsDisabled");
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(Test.class, !value);
}
Share:
11,554
Saideira
Author by

Saideira

Contract developer, worked on everything from MIPS assembly to financial J2EE systems. I wish to go work on Mars. Or Australia.

Updated on June 17, 2022

Comments

  • Saideira
    Saideira almost 2 years

    How can I programmatically enable assert for particular classes, instead of specifying command line param "-ea"?

    public class TestAssert {
    
        private static final int foo[] = new int[]{4,5,67};
    
    
        public static void main(String []args) {
            assert foo.length == 10;
        }
    }