The relevant section is 2.17.5 "Detailed Initialization Procedure":
...
8. Next, execute either the class variable initializers and static initializers of
the class or the field initializers of the interface, in textual order, as
-> though they were a single block, *except* that final static variables and fields
of interfaces whose values are compile-time constants are initialized first.
...
So, you would be possibly changing the initialization order of fields. Now, is that
an important thing? I do not have an answer, but I really dislike replacing a
constant value by executable code. I already feel that the class file format lacks
"constant" arrays and pre-initialized non-constant variables and arrays.
Now, if you take into account "further" compilation of a class ClassA against a
Soot-optimized class ClassOpt, then an important issue arises: If the
compile-time constant fields (e.g. final public static [primitive-type]) of
ClassOpt do not have a ConstantValue attribute, then ClassA will compile accesses to
constants of ClassOpt as GET_STATIC, instead of simply doing an ICONST or LDC. This
is an important consequence, which violates the Java Language Specification.
I don't have at habd the exact section, but the JLS says that:
class ClassA { ... if (ClassOpt.DEBUG) { /* then_code */ } else { /* else_code */ } ... }
will be compiled to bytecode that DOES NOT contain any conditional; only one of then_code
or else_code will be included in the class file, depending on the value of ClassA.DEBUG.
So, I really think Soot should not move constant values into <clinit>; it should instead
preserve ConstantValue attributes.
Etienne
Feng Qian wrote:
The constant field represented by the |field_info| structure is assigned the value referenced by its |ConstantValue| attribute as part of the initialization of the class or interface declaring the constant field (§2.17.4) <http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#19075>. This occurs immediately prior to the invocation of the class or interface initialization method (§3.9) <http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html#12174> of that class or interface.
Probably it is not as worse as you may think ;-) .
Cheers, Feng
Etienne Gagnon wrote:
Hi Feng,
Feng Qian wrote:
...
testconstA.java modified
public class testconstA {
public static final z = 7;
}
The solution is to assign the value of ConstantValue attribute to a static field in <clinit> explicitly (create one if no <clinit> exists) before any other real code in original <clinit>...
So, you are saying that you want to change such a class into:
testconstA.java modified again public class testconstA { public static final z; static { z = 7; } }
I would really prefer that the ConstantValue attribute be preserved
instead of adding an assignment statement. Execution of static blocks
happen at a later time than initialization of fields with ConstantValue
attributes, according to the JVM spec. [In other words, constant fields
are initialized with their value before <clinit>() is called].
Etienne