Message5992

Author irogers
Recipients alexey, draghuram, irogers
Date 2010-08-20.18:06:46
SpamBayes Score 9.462269e-09
Marked as misclassified No
Message-id <1282327609.92.0.37264397008.issue1611@psf.upfronthosting.co.za>
In-reply-to
Content
So the interpretation of the virtual machine specification doesn't say that static final fields must be written before instances of classes can be created. If this were so then it would be impossible to make singleton instances of classes. Also putstatic may write to a final field in the same class from any method - from the virtual machine specification. So from this Jython's code looks valid and passes bytecode verification (-Xverify in HotSpot).

The Java Language Specification:
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.5.1
details what the meaning of final is and here it can be seen why what jython is doing is buggy, although a discussion of class initializers isn't provided in this context - my discussion follows what happen in HotSpot (the reference Java implementation). A static final field is initialized by the class initializer. A freeze event occurs when the class initializer completes. Readers of the static final once a class is initialized can assume that it is constant, with some exceptions such as when the field is modified through a specialist mechanism such as reflection. The reader of the static final field (especially when -Xcomp is switched on) is the HotSpot compiler.

Consider jython generated code such as:

public sre_constants$py(java.lang.String);
  Code:
   Stack=13, Locals=3, Args_size=2
   0:   aload_0
   1:   invokespecial   #645; //Method org/python/core/PyFunctionTable."<init>":()V
   4:   aload_0
   5:   putstatic       #649; //Field self:Lsre_constants$py;
...
  1045:        iconst_1
   1046:        iconst_1
   1047:        anewarray       #543; //class java/lang/String
   1050:        astore_2
   1051:        aload_2
   1052:        iconst_0
   1053:        ldc_w   #858; //String a
   1056:        aastore
   1057:        aload_2
   1058:        aload_1
   1059:        ldc_w   #860; //String <lambda>
   1062:        sipush  222
   1065:        iconst_0
   1066:        iconst_0
   1067:        getstatic       #649; //Field self:Lsre_constants$py;
   1070:        iconst_4
   1071:        aconst_null
   1072:        aconst_null
   1073:        iconst_0
   1074:        sipush  4097
   1077:        invokestatic    #840; //Method org/python/core/Py.newCode:(I[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZLorg/python/core/PyFunctionTable;I[Ljava/lang/String;[Ljava/lang/String;II)Lorg/python/core/PyCode;
   1080:        putstatic       #538; //Field f$4:Lorg/python/core/PyCode;
   1083:        return

The:
   5:   putstatic       #649; //Field self:Lsre_constants$py;
occurs after the class initialization freeze event. The compiler compiles:
   1067:        getstatic       #649; //Field self:Lsre_constants$py;
And because the field is considered frozen the value NULL is loaded and passed through to the subsequent call. Eventually this results in a NullPointerException.
History
Date User Action Args
2010-08-20 18:06:49irogerssetmessageid: <1282327609.92.0.37264397008.issue1611@psf.upfronthosting.co.za>
2010-08-20 18:06:49irogerssetrecipients: + irogers, draghuram, alexey
2010-08-20 18:06:49irogerslinkissue1611 messages
2010-08-20 18:06:46irogerscreate