views:

73

answers:

5

How much memory will JVM Allocate to 1) Static String 2) Static Integer

I am exploring this issue as I am getting Heap Memory Out of Memory Exception, I have in my application 8 constants file and each file has almost near to 300 Static Constants.

Is that a good practice to declare all the constants as a Static or any other practice can I Follow?

+3  A: 

2400 String constants will not run you out of memory. At a generous 10K each, that would be just 24MB. At the more usual rate of 100 bytes each, it is just 240K.

I would look for the memory hog somewhere else.

Thilo
@Thilo, can you please tell me how to check that? and any tools to analyse that?
harigm
Harigm, you can use any profiler to look into what is eating your memory. VisualVM ( https://visualvm.dev.java.net/ )is a free profiler that you can use to analyze the memory consumption of your application.
Ruben
+1  A: 

I assume these are both static and final since you are referring to them as constants.

If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. For primitive types no heap memory needs to be used. Strings are interned, and only one copy needs to be stored in heap.

Anyway I don't believe 8 x 300 strings are causing an out of memory condition. Your problem must be somewhere else.

Grodriguez
I know that the compiler does this for primitive types, but even for Strings? And at least one instance of the String must be in heap memory, even if everyone else shares it.
Thilo
I think the constant strings are interned, but take up heap space. Also, while compile time constants might not use any heap space, they definitely take up RAM.
Burleigh Bear
@Thilo, Burleigh Bear: You are right, the interned version is stored in heap memory. I'll update.
Grodriguez
A: 

How big are your constant strings?

The memory used by the strings is of the order of 8 * 300 * 2 * average-length = ~5k * average-length. It doesn't seem like enough to use all your memory.

It is indeed good practice to declare constants as static, and also final. e.g.

public static final String A_STRING = "this String is constant"; 

Note, it is the reference that is made constant by the 'final' modifier, not the object itself.

Burleigh Bear
Just a quick note to complement the above: It is the reference that is made constant by the final modifier, however when the compiler sees a final refernce to a string literal it will recognize it as a compile-time constant and intern the string. This is specified by the JLS: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313
Grodriguez
@Grodriguez - interning happens because the String **value** is a compile time constant, not because the variable is declared as `final`.
Stephen C
@Stephen C: Yes, you are correct. This is what I meant (the compiler recognizes the string literal as a compile-time constant), although the wording in my comment is probably misleading. Thanks for clarifying.
Grodriguez
+1  A: 

How much memory will JVM Allocate to 1) Static String 2) Static Integer

(To simplify things, I'll assume we are talking about a 32bit JVM. Also note that these numbers are approximate, and JVM specific.)

The easy one first - each static Integer variable occupies 4 bytes of memory for the reference plus 4 bytes + 1 object header (typically 8 bytes IIRC). Grand total - 16 bytes.

(And if you are talking about static int variables, it is 4 bytes total per int.)

A static String variable is a bit more complicated ... and more expensive:

  • The static reference variable is 4 bytes.
  • The String object has 4 x 4byte fields + 1 x 2 word object header: that's 24 bytes.
  • One of those fields refers to a char array which has a 3 word header and requires (string.length() + 3) / 4 bytes for the content - that's 12 + some multiple of 4 bytes.
  • If the String value is a compile time constant then the String will be interned, and that will add a few extra bytes overhead for the string pool hash table entry. (32 bytes would be a reasonable guess.)

Add that all up and you get (say) 80+ bytes per string, depending on string length. But nearly all of those bytes are the representation of the (interned) String itself. Only 4 bytes are due to the use of a static.

I am exploring this issue as I am getting Heap Memory Out of Memory Exception, I have in my application 8 constants file and each file has almost near to 300 Static Constants.

That's insignificant. The OOME is almost certainly due to something else.

Is that a good practice to declare all the constants as a Static or any other practice can I Follow?

It is good practice to declare real constants as statics, up to a point.

However, large numbers of constants in the source code gets unwieldy, and you eventually run into compilation errors due to limits in the format of a bytecode file. At that point (and probably well before then) you should move the constants out of your source code and into a database or configuration file.

You are likely to run into the bytecode-format-imposed limit well before memory usage becomes a significant issue.

Stephen C
+1  A: 

How much space a string object takes depends, of course, on the length of the string.

Besides the characters of the string itself, a string contains a few control fields, but I count them as 28 bytes plus another embedded object (ObjectStreamField), I'm not sure how big that is, but anyway it's maybe a few dozen bytes. Each character takes 2 bytes. You need, I think, 8 bytes for the handle. If you're strings are, what, maybe 20 characters or so each?, maybe you have as much as 100 bytes per string. So like Thilo says, 2400 strings may sound like a lot but it's going to take hundreds of kB. Unless you're talking about Java embedded in a wristwatch or some such highly constrained environment, it's hard to imagine that this is going to be a significant factor in blowing your memory.

Jay