Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Exploring Static Init

Reply
Thread Tools

Exploring Static Init

 
 
Roedy Green
Guest
Posts: n/a
 
      08-26-2005
After Thomas surprised me with the enum decompilation, I thought I
would have a look at a static init decompilation to see I what I
thought was true was indeed true.

Here is my little test program:

// experiment to see order of initialisation
public class Init2
{
static {
// define m multiple times
m = 1;
}
static final int inlined = 2;
static final int notInlined = Math.min( 3 , 4 );
static int m = 5;
static
{
m = inlined + 6; // effectively 8
m = notInlined + 7; // effectively 10
}
}


DJ compiles it like this:
public class Init2
{

public Init2()
{
}

static final int inlined = 2;
static final int notInlined;
static int m = 1;

static
{
notInlined = Math.min(3, 4);
m = 5;
m = 8;
m = notInlined + 7;
}


Javap decompiles it like this:


javap -c Init2

Compiled from "Init2.java"
public class Init2 extends java.lang.Object{
static final int inlined;

static final int notInlined;

static int m;

public Init2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>")V
4: return

static {};
Code:
0: iconst_1
1: putstatic #2; //Field m:I
4: iconst_3
5: iconst_4
6: invokestatic #3; //Method java/lang/Math.minII)I
9: putstatic #4; //Field notInlined:I
12: iconst_5
13: putstatic #2; //Field m:I
16: bipush 8
18: putstatic #2; //Field m:I
21: getstatic #4; //Field notInlined:I
24: bipush 7
26: iadd
27: putstatic #2; //Field m:I
30: return

}


So what do we discover? Probably nothing new to the old timers.

1. static final int inlined = 2; gets inlined. It is treated like a
literal. The line m = inlined + 6; is effectively turned to m = 2+ 6;
which is collapsed further to m = 8;.

This is why you have to recompile the classes that use constants in
some other class when that base class changes the constant values. The
dependent code has to be re-inlined. The original source of the
constant value is lost in the class file.

2. The initialisations are done in strict order, whether they are
attached to a single line or are part of a static block. You might
reasonably have expected all the one liners to have been done first,
but that is not so.

This is why you have to be careful with field-ordering IDEs like
Eclipse. Changing the field order can change the dependency order
during initialization. There is no clever spreadsheet-like discovery
of dependencies. Initialisation proceeds mindlessly top to bottom.

3. You are allowed to initialise variables not defined yet in static
blocks, but you are not allowed to refer to variables not initialised
yet. This is because the definition and initialisation, though mixed
together in Java source, are separate in the class file. Note the m=1.

4. JavaC is not doing even the most rudimentary optimisation of
discarding a save to a variable immediately followed by a save of a
different value to that same variable.





















































































































































--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
 
Reply With Quote
 
 
 
 
Mike Schilling
Guest
Posts: n/a
 
      08-27-2005

"Roedy Green" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> 2. The initialisations are done in strict order, whether they are
> attached to a single line or are part of a static block. You might
> reasonably have expected all the one liners to have been done first,
> but that is not so.


That is to say, the order is predictable. This is a good thing. (By the
way, the same is true of instance initialization: top to bottom.)
>
> This is why you have to be careful with field-ordering IDEs like
> Eclipse. Changing the field order can change the dependency order
> during initialization.


Very true.

> There is no clever spreadsheet-like discovery
> of dependencies. Initialisation proceeds mindlessly top to bottom.


Again "predictably from top to bottom", and again, unless you want subtle
bugs introduced by the compiler's attempt to make sense out of code that
doesn't have an obvious single meaning, that's desirable..


 
Reply With Quote
 
 
 
 
Thomas Hawtin
Guest
Posts: n/a
 
      08-27-2005
Roedy Green wrote:
>
> 3. You are allowed to initialise variables not defined yet in static
> blocks, but you are not allowed to refer to variables not initialised
> yet. This is because the definition and initialisation, though mixed
> together in Java source, are separate in the class file. Note the m=1.


This will be definite assignment/unassignment, which presumably works
the same way as for locals and instance variables. The JLS has a rather
dull chapter on the subject.

> 4. JavaC is not doing even the most rudimentary optimisation of
> discarding a save to a variable immediately followed by a save of a
> different value to that same variable.


IIRC, javac used to do more optimisation. You can easily see how class
file size and number of byte code instructions can go down. Great for
J2ME. However byte code optimisation can, apparently, make it more
difficult for HotSpot to optimise its intermediate representations.
Indeed, javac does some pessimisation, duplicating small finally blocks
for exception and normal cases.

Tom Hawtin
--
Unemployed English Java programmer
http://jroller.com/page/tackline/
 
Reply With Quote
 
Thomas G. Marshall
Guest
Posts: n/a
 
      08-27-2005
Roedy Green coughed up:
> After Thomas


please *always* supply a last name if you can when the first name is a
common one.


> surprised me with the enum decompilation, I thought I
> would have a look at a static init decompilation to see I what I
> thought was true was indeed true.
>
> Here is my little test program:


....[rip]...

> So what do we discover? Probably nothing new to the old timers.
>
> 1. static final int inlined = 2; gets inlined. It is treated like a
> literal. The line m = inlined + 6; is effectively turned to m = 2+ 6;
> which is collapsed further to m = 8;.
>
> This is why you have to recompile the classes that use constants in
> some other class when that base class changes the constant values. The
> dependent code has to be re-inlined. The original source of the
> constant value is lost in the class file.


Yep. Hence the need for intelligent make{rs} able to garner such
dependencies out of source.


> 2. The initialisations are done in strict order, whether they are
> attached to a single line or are part of a static block. You might
> reasonably have expected all the one liners to have been done first,
> but that is not so.
>
> This is why you have to be careful with field-ordering IDEs like
> Eclipse. Changing the field order can change the dependency order
> during initialization. There is no clever spreadsheet-like discovery
> of dependencies. Initialisation proceeds mindlessly top to bottom.


Correct, but I seem to remember eclipse not mucking with field orders when
there are explicit initializers. Am I wrong here? Seems to ring a bell....


> 3. You are allowed to initialise variables not defined yet in static
> blocks, but you are not allowed to refer to variables not initialised
> yet. This is because the definition and initialisation, though mixed
> together in Java source, are separate in the class file. Note the m=1.


Interesting. I'm going to think on this---it doesn't seem right. By the
way, over time it seems that in the universe "definition" and "declaration"
are being used interchangeably. Oh well...


> 4. JavaC is not doing even the most rudimentary optimisation of
> discarding a save to a variable immediately followed by a save of a
> different value to that same variable.


I don't believe that it /strictly/ can, if I understand you correctly. The
static initializers happen at class load time which can occur at any point
in the runtime, which might occur at the same time some other thread is
attempting reading and mucking with those values.

This is my question then: Does access to variables mid-static initialization
get blocked until the initialization of the class is complete? If a static
block does this:

public static int a = 5;
static { a = 6; a = 7; }

is access to "a" disallowed from outside until the static initialization
period is over?




--
Whyowhydidn'tsunmakejavarequireanuppercaseletterto startclassnames....


 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      08-27-2005
On Sat, 27 Aug 2005 10:46:16 +0100, Thomas Hawtin
<(E-Mail Removed)> wrote or quoted :

>IIRC, javac used to do more optimisation. You can easily see how class
>file size and number of byte code instructions can go down. Great for
>J2ME. However byte code optimisation can, apparently, make it more
>difficult for HotSpot to optimise its intermediate representations.
>Indeed, javac does some pessimisation, duplicating small finally blocks
>for exception and normal cases.


This is opening the door for byte code optimisers where the code will
eventually be interpreted. The save x save x optimisation is safe,
simple to find, and I would think unlikely to confuse a hotspot
optimiser. Perhaps it does in some special case so they turn it off
generally.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
 
Reply With Quote
 
Mike Schilling
Guest
Posts: n/a
 
      08-27-2005

"Roedy Green" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)...
> On Sat, 27 Aug 2005 10:46:16 +0100, Thomas Hawtin
> <(E-Mail Removed)> wrote or quoted :
>
>>IIRC, javac used to do more optimisation. You can easily see how class
>>file size and number of byte code instructions can go down. Great for
>>J2ME. However byte code optimisation can, apparently, make it more
>>difficult for HotSpot to optimise its intermediate representations.
>>Indeed, javac does some pessimisation, duplicating small finally blocks
>>for exception and normal cases.

>
> This is opening the door for byte code optimisers where the code will
> eventually be interpreted. The save x save x optimisation is safe,
> simple to find, and I would think unlikely to confuse a hotspot
> optimiser. Perhaps it does in some special case so they turn it off
> generally.


Or pehrpas bytecode optimization is considered of little importance in the
scheme of things, so little or no resources are devoted to it.


 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      08-28-2005
On Sat, 27 Aug 2005 23:44:32 GMT, "Mike Schilling"
<(E-Mail Removed)> wrote or quoted :

>Or pehrpas bytecode optimization is considered of little importance in the
>scheme of things, so little or no resources are devoted to it.


When Hotspot gets hold of it, the problem is solved. The problem only
exists when you run the code elsewhere, e.g. in a cellphone.

There you fight for every byte. I'm surprised at Sun being so
cavalier. Perhaps they are trusting some third party will step in.

The tools to do it may be masking as obfuscators which also try to
reduce footprint.



--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      08-28-2005
On Sat, 27 Aug 2005 14:52:12 GMT, "Thomas G. Marshall"
<(E-Mail Removed). com> wrote or quoted
:

>Correct, but I seem to remember eclipse not mucking with field orders when
>there are explicit initializers. Am I wrong here? Seems to ring a bell....


Eclipse has a tidying feature to put code in some order you specify,
e.g. collecting publics together alphabetically. You have to be aware
that if you use this feature, you can disturb delicate ordering that
static init depends on.

If you want to make your code robust to survive such tidying, put
tricky initialisation in a static { } block where it won't be
reordered.

ditto for instance init.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
init of class members : mem(0) vs. mem() vs. not-init at all news.aon.at C++ 11 01-29-2011 07:30 PM
questions about object initialization, default-init and value-init Jess C++ 4 05-04-2007 02:47 AM
Exploring the open sessions, manually connecting one Pavils Jurjans ASP .Net 0 05-09-2006 11:46 AM
Sequence Order between Page Init and User Control Init Tony Cheng ASP .Net 1 02-24-2006 01:56 PM
Compiler/Linker Error undefined reference to 'std::ios_base::Init::Init[in-charge]() clusardi2k@aol.com C++ 1 08-18-2005 07:11 PM



Advertisments