Assertions in static blocks ?

David Holmes - Sun Microsystems David.Holmes at Sun.COM
Sat Mar 6 16:34:26 PST 2010


David, Ulf,

Note that in Ulf's example:

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;
     }
}

the fields are _NOT_ initialized with compile-time constant expressions 
and so access to them will be via a getstatic bytecode which will result 
in class initialization.

David Holmes
------------

David Schlosnagle said the following on 03/07/10 05:55:
> 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 hotspot-dev mailing list