Assertions in static blocks ?

David Schlosnagle schlosna at gmail.com
Sat Mar 6 11:55:33 PST 2010


Ulf,

The behavior you're encountering is consistent with JLS §4.12.4 [1] which
states:
    We call a variable, of primitive type or type String, that is final and
    initialized with a compile-time constant expression (§15.28) a constant
    variable. Whether a variable is a constant variable or not may have
    implications with respect to class initialization (§12.4.1), binary
    compatibility (§13.1, §13.4.9) and definite assignment (§16).

Later in JLS §13.1 [2] it states:
    References to fields that are constant variables (§4.12.4)  are resolved at
    compile time to the constant value that is denoted. No reference to such a
    constant field should be present in the code in a binary file (except in
    the class or interface containing the constant field, which will have code
    to initialize it), and such constant fields must always appear to have been
    initialized; the default initial value for the type of such a field must
    never be observed. See §13.4.8 for a discussion.

Check out Java Puzzler 93: Class Warfare [3] which gives an example of this and
how it impacts binary compatibility. Josh and Neal also covered this in the
2009 JavaOne Puzzler talk, see #7 "When Words Collide" [4].

Based on that, anywhere that PL0_5_B2C_RANGE or PLANE_B2C_RANGE are used the
actual values will be inlined into the referencing class file at compile time
as "sipush  8960" or "sipush 7936" respectively, and therefore do not reference
the class EUC_TWMapping3 or cause it to be initialized.

If you do want to ensure the assertions are run when at class initialization,
I'd recommend something like the following which will ensure that the value is
not inlined at compile time:

class EUC_TWMapping3 extends EUC_TWMapping {
    static final short PL0_5_B2C_RANGE = planeZeroFiveB2CRange(); //
plane 0, 5 b2c range
    static final short PLANE_B2C_RANGE = planeB2CRange(); // plane
2..4, 6..15 b2c range

    private static final short planeZeroFiveB2CRange() {
        short range = 0x2300; // plane 0, 5 b2c range
        assert range >= b2c.length; // assert by values from EUC_TWMapping
        return range;
    }

    private static final short planeB2CRange() {
        short range = 0x1f00; // plane 2..4, 6..15 b2c range
        assert range <= b2c.length; // assert by values from EUC_TWMapping
        return range;
    }
}

[1]: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.4
[2]: http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#13.1
[3]: http://www.javapuzzlers.com
[4]: http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5186&yr=2009&track=javase

- Dave



On Sat, Mar 6, 2010 at 6:35 AM, Ulf Zibis <Ulf.Zibis at gmx.de> wrote:
> Am 06.03.2010 02:28, schrieb Keith McGuigan:
>>
>> Ulf Zibis wrote:
>>>
>>> Neal, Keith, thanks for your answer.
>>>
>>> ... but shouldn't javac claim, that there the code in the static block
>>> will be *never reached*, if there is no trigger to run it?
>>
>> Not really.  That would be like claiming that the code in a method will
>> never be reached if no one calls the method.  javac can't know that you're
>> not going to take that class and deploy it somewhere else with other code
>> that will end up calling the method (or initializing the class, etc.).
>
> But javac can know about the risk, because running Class.forName() is "not
> very common", especially if there is nothing but constants in that class.
> The minimum, javac could do is to throw a warning.
>
> On the other hand, javac throws errors, even if the stated problem never
> occurs:
>            char c1 = 12345;
>            char c2 = c1 % 100;
> would result in ERROR: "possible loss of precision", but
>            c1 *= 12345;
> compiles without problem.
>
> Do you know, if following static initializer will be guaranteed to run, when
> accessing the static value? :
>
> class EUC_TWMapping3 extends EUC_TWMapping {
>    static final short PL0_5_B2C_RANGE; // plane 0, 5 b2c range
>    static final short PLANE_B2C_RANGE; // plane 2..4, 6..15 b2c range
>    static {
>        PL0_5_B2C_RANGE = 0x2300; // initialized here to force the
> assertions!
>        PLANE_B2C_RANGE = 0x1f00; //      "             "            "
>        // assert by values from EUC_TWMapping
>        assert PL0_5_B2C_RANGE >= b2c.length;
>        assert PLANE_B2C_RANGE <= b2c.length;
>    }
> }
>
> -Ulf
>
>
>
>



More information about the compiler-dev mailing list