In C, scoping rules aside, the following are pretty much the same:
static int x[] = { /* ... */ };
int foo()
{
/* do something with x */
}
and
int bar()
{
static int x[] = { /* ... */ };
/* do something with x */
}
The static array x
will go into the .data section of the executable. When the OS loads the executable into memory, it will ensure that the values for x
are set in the appropriate place (e.g. by mapping its disk page to the virtual address in the ELF headers). In the second case, x
is given some alias to avoid symbol conflicts.
There seems to be no way to do the second version in Java. Here’s how I tried:
static int xyzzy()
{
final int x[] = { /* ... */ };
/* do something with x */
}
This doesn’t do what you might think it does. While x
cannot be changed, it is the reference to an array; the array elements themselves can be changed at will. Thus javac is unlikely to do anything smart here.
Indeed, in the above case, javac will initialize x
with stack pushes every time xyzzy()
is called. I had a real method like this, and making x
a static member variable gave me an easy 2x speedup.
2x speed up, hmm… interesting tagging of ‘java-hate’!
Any time I use java it inspires hate; unfortunately I probably use it more than anything else 🙂
It saddens me somewhat that array initialization on the stack is so inefficient. It compiles to something like 4 bytecode ops per array element (but I didn’t actually try to see what the JIT does with it). Since I am just using the array as a read-only look up table, it would be nice to be able to hint that to the compiler somehow.
C gives a little more flexibility in this regard, but some would argue that being able to declare function-scope variables static is a defect in the C spec. Anyway, using a static member variable isn’t a bad solution.