LostOracle
LostOracle

Reputation: 75

Using "Constant" Objects in Java

From my research, I know that you can get an almost C-like constant value in Java using the static final modifiers. i.e. static final int my_const_int = 5;.

By experiment, I discovered you can create constant objects in the same fashion, but it required use of the new keyword i.e. static final Color c = new Color(100,100,100,255);

My question is this: using this method will the Color object c be allocated on the heap at run time, allocated on the stack at run time (does Java even use the stack?), or will it be somehow evaluated at compile time to reduce the memory footprint?

I'm a recently converted C programmer, so while I understand memory fairly well, I have very little idea about how Java uses it. Any insights would be greatly appreciated.

Upvotes: 1

Views: 1067

Answers (3)

RalphChapin
RalphChapin

Reputation: 3158

From when I switched from C to Java:

The first trick is to forget all you know about memory, particularly about the most efficient way to store constants. Java's so simple you don't need to bother about that. The second trick is to learn to willfully do all those simple things you'd never dare do in C. Create objects and forget about them: don't worry who's got a pointer to them, don't worry if they've been freed, don't worry that you're allocating and freeing space repeatedly in million-cycle loop.

Three things about Java memory:

You can't speed it up. Java puts each thing in a separatly allocated bit of memory and tracks it with a reference. In C you can arrange sets of nested structures all in one continuous block of memory. No matter what you do, in Java the same thing is going to be a set of pointers ("references") to other blocks of memory, many of which are still more sets of pointers. Accept it.

You can't slow it down. Java optimizers will do anything to make your code run faster, and the JVM optimizers will do it while your code is running. Putting an object on the stack (as mentioned elsewhere) is typical.

(This is not something you normally need to think about, but it can do odd things to benchmark tests. The JVM can ingeniously notice, while the loop is running, that you're not actually looking at more than 5 elements in the million number array you're filling, and jiggle the loop so it only runs 5 times to fill those 5 elements.)

And the big one:

You cannot screw it up! If you have a variable with a (non-null) reference in it, it's good. The object is there. It's the same object it was when the reference was set. Most surprisingly, when you stop using something--and only when you stop using it--the space is freed. Null the one reference to an extensive graph of millions of objects and...poof! All gone! You can build up something just as big without using more memory. A key (maybe the key) to Java is to milk this for all it's worth.

(Disclaimer: large arrays and things that use them--ArrayList, HashTable--can annoy the garbage collector and cause it to need more memory than it ought to. But worry about that later.)

In general, use words like "static" and "final" to control what your program does rather than to try to improve speed or memory usage. It's your job to specify the algorithm. It's Java's job to run it fast.

(Disclaimer again: if you keep too many objects of too large a size, you will run out of memory. Doing this unwittingly gives a sort of Java "memory leak"--very different from a C memory leak. But if you are going to reduce memory usage, you have to do this by redesigning your classes, not with reworking how the data primitives are stored in a class.)

Upvotes: 2

Brian
Brian

Reputation: 17299

All objects are allocated on the heap in Java. The only time you have variable allocation on the stack is for locally declared primitives and locally declared references to objects on the heap (think "pointers", but without pointer arithmetic, dereferencing, etc.).

Also worth noting that since arrays are objects, they are also allocated in the heap, and you maintain a reference to the pointer in your thread's stack, even if it's a primitive array like int[].

Edit: Thanks to Marko for this edit. The Hotspot JVM (and presumably others) can perform optimizations based on whether or not an object reference can "escape" a method or stack frame. If the object's reference is not passed between stack frames (i.e. it is published to other threads) nor passed to a parent stack frame (i.e. returned by the method) then the object is considered to be "unescapable" and is allocated within the stack frame itself, similar to how you allocate objects on the stack in C++. Here's the reference.

Upvotes: 1

Jeffrey
Jeffrey

Reputation: 44798

All objects are stored on the heap, even static final ones. As far as the compiler knows, the object could be mutable.

Only primitives and references are stored on the stack.

On a related note, the compiler will inline primitive constants where they are used.

Upvotes: 3

Related Questions