43

In Java, does it cost memory to declare a class level instance variable without initializing it?
For example: Does int i; use any memory if I don't initialize it with i = 5;?

Details:

I have a huge super-class that many different (not different enough to have their own super classes) sub-classes extend. Some sub-classes don't use every single primitive declared by the super-class. Can I simply keep such primitives as uninitialized and only initialize them in necessary sub-classes to save memory?

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
WVrock
  • 1,725
  • 3
  • 22
  • 30
  • 2
    Regarding your last paragraph, take a look at [structural design patterns](http://en.wikipedia.org/wiki/Structural_pattern), maybe something can help you there. Depending on your use case, [flyweight pattern](http://en.wikipedia.org/wiki/Flyweight_pattern) might be something of interest. – Ibrahim Arief Oct 27 '14 at 10:58
  • Flyweight pattern is sharing the data to avoid creation of the same value for each use. What I'm trying to do is to avoid the creation of the values that will not be used. Thanks for the links. I will look into the other patterns. – WVrock Oct 27 '14 at 11:44
  • 4
    How is this not a duplicate more than 6 years after Stack Overflow was launched and after 733987 Java questions? – Peter Mortensen Oct 27 '14 at 20:43
  • I'm hesitant to close it although this question is already answered in the other question itself, but nevertheless very related: http://stackoverflow.com/questions/2430655/java-does-null-variable-require-space-in-memory – Jeroen Vannevel Oct 27 '14 at 22:54
  • @JeroenVannevel My question was specifically about primitives then got edited by others to include every class level instance variables. I've not only googled it but also searched Stack Overflow but couldn't find anything about primitives. The link you have given is about null values which primitives can't have. – WVrock Oct 28 '14 at 04:14
  • 3
    A huge super class is a design smell, especially if many of the derived classes do not use the members. You probably need to look at using composition rather than inheritance. – Raedwald Oct 28 '14 at 08:00
  • See also http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance – Raedwald Oct 28 '14 at 08:01
  • 1
    When you seem to need multiple inheritance in Java, [delegation](http://en.wikipedia.org/wiki/Delegation_pattern) can often be used to achieve similar results, though not quite as natural/elegant as inheritance. – JimmyB Oct 28 '14 at 10:15
  • @HannoBinder delegation is a good substitute for multiple inheritance but I have hesitations. There won't be any unnecessary variables and some memory would be freed but delegation objects have their own additional memory usage due to being objects. – WVrock Oct 28 '14 at 10:29

6 Answers6

72

All members defined in your classes have default values, even if you don't initialize them explicitly, so they do use memory.

For example, every int will be initialized by default to 0, and will occupy 4 bytes.

For class members :

int i;

is the same as :

int i = 0;

Here's what the JLS says about instance variables :

If a class T has a field a that is an instance variable, then a new instance variable a is created and initialized to a default value (§4.12.5) as part of each newly created object of class T or of any class that is a subclass of T (§8.1.4). The instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary finalization of the object (§12.6) has been completed.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • 2
    @Eran today I was reading about "Singleton" on Polish wikipedia (for Polish speaking users http://pl.wikipedia.org/wiki/Singleton_(wzorzec_projektowy)#Konsekwencje_stosowania ). One of pros of using singleton is, according to this article, "due to lazy initialization, if there is no component using singleton, no resources will be given to a singleton's instance". Singletons are not primitive types, I know, but don't they have some default values? Is it true, they don't use any memory before initialization? – spoko Oct 27 '14 at 15:01
  • 3
    @spoko Singletons are classes with a single instance. When using lazy initialization, the variable holding that instance contains a null reference. Only when the class is instantiated, the instance is allocated memory. – Eran Oct 27 '14 at 15:50
  • 3
    @spoko Primitives != Classes. Primitives allocates memory by default. But not for references. They hold a default value `null`. – Suresh Atta Oct 27 '14 at 16:23
  • 4
    @sᴜʀᴇsʜᴀᴛᴛᴀ A null-reference Object-Type attribute will take its share of 32/64 bit, even if it is null, so it is essentially the same as an int=0. And the reference will never take more space! Only the additional allocated space for the new object will be added.... But talking about this with java classloader and everything is in 99% premature optimization and will do noone any good... – Falco Oct 27 '14 at 17:24
  • The JLS (as you quote it) does not require that a JVM actually allocate memory for default values. A perfectly-compliant JVM might create instance as maps of field names to values (even though that would be absurd in practice) – nanofarad Oct 27 '14 at 22:52
  • I guess that the JIT compiler would be permitted to eliminate a field that was never used, as eliminating it would have no behavioral change. – Raedwald Oct 28 '14 at 08:08
  • @hexafraction - There's no practical way to have instance fields without allocating them as a part of the fixed-length instance storage. The only possible (though impractical) approach to do otherwise would turn the instance into a hashtable, but that approach would be a loser both in terms of storage and in terms of execution efficiency. – Hot Licks Oct 28 '14 at 16:21
  • 1
    @Raedwald - If a field that is used in some instances were to be eliminated in instances that do not use it, the JVM/JITC would have to maintain two versions of code for that class, since the offsets of other instance fields would be displaced by the missing field. – Hot Licks Oct 28 '14 at 16:24
17

Yes, memory allocates though you are not assigning any value to it.

int i;

That takes 32 bit memory (allocation). No matter you are using it or not.

Some sub-classes don't use every single primitive declared by the super-Class. Can I simply keep such primitives as uninitialized and only initialize them in necessary sub-classes to save memory?

Again, no matter where you initialized, the memory allocates.

Only thing you need to take care is, just find the unused primitives and remove them.

Edit: Adding one more point that unlike primitive's references by default value is null, which carries a a memory of

 4 bytes(32-bit) 
 8 bytes on (64-bit)
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    I can't remove them. Other subClasses use them. Extending multiple superClasses would solve my problem but it is not possible in java 7. – WVrock Oct 27 '14 at 10:34
  • 1
    @WVrock okay. just leave them as is. – Suresh Atta Oct 27 '14 at 10:39
  • 1
    @WVrock Or in any other version of Java. – Dave Newton Oct 27 '14 at 11:51
  • 1
    @DaveNewton I've heard that it is possible to use interfaces to achieve multiple inheritance in java 8. It still doesn't count as extending multiple super classes though. – WVrock Oct 27 '14 at 11:59
  • 1
    @WVrock Implementing multiple interfaces has been possible essentially forever; Java 8 adds only default method implementations. – Dave Newton Oct 27 '14 at 12:10
  • @DaveNewton multiple implementations was possible but in java 7 and below interfaces are very limited compared to super classes. They are too limited to be called multiple inheritence. All they can do is to add method names and finalized variables. Not even close to being as useful as super classes if you ask me. I am not sure if it can be called multiple inheritence in the java 8 either. For instance, they wouldn't solve my problem here even in java 8. – WVrock Oct 27 '14 at 13:17
11

The original question talks about class level variables and the answer is that they do use space, but it's interesting to look at method scoped ones too.

Let's take a small example:

public class MemTest {
    public void doSomething() {
        long i = 0;  // Line 3
        if(System.currentTimeMillis() > 0) {
            i = System.currentTimeMillis();
            System.out.println(i);
        }
        System.out.println(i);
    }
}

If we look at the bytecode generated:

  L0
    LINENUMBER 3 L0
    LCONST_0
    LSTORE 1

Ok, as expected we assign a value at line 3 in the code, now if we change line 3 to (and remove the second println due to a compiler error):

long i; // Line 3

... and check the bytecode then nothing is generated for line 3. So, the answer is that no memory is used at this point. In fact, the LSTORE occurs only on line 5 when we assign to the variable. So, declaring an unassigned method variable does not use any memory and, in fact, doesn't generate any bytecode. It's equivalent to making the declaration where you first assign to it.

BarrySW19
  • 3,759
  • 12
  • 26
  • That's a lot of lead-up material about something else. If nothing else it might be nice to answer the question first, *then* add additional information. – Dave Newton Oct 27 '14 at 11:53
  • 2
    The reason nothing is generated is because the compiler is smart enough to optimize that out. Otherwise, uninitialized (and unused) local variables take up memory. – async Oct 27 '14 at 21:55
  • Since this answer was posted, a follow-on question has been posted about method scope http://stackoverflow.com/q/26632799/397817 – Stephen Kennedy Nov 01 '14 at 10:18
  • @user16547 I don't think that's correct - you couldn't have a primitive which allocated memory but was uninitialised in Java because the memory location would have to contain some data. As the Java spec says that local variables are not initialised that has to mean they are also not memory allocated. – BarrySW19 Nov 01 '14 at 11:12
  • @BarrySW19 When the stack frame for that particular method is created, it allocates enough memory for local variables. If it weren't smart enough to realize a variable was unused & completely useless, it would have naively allocated enough memory for it in the stack frame. – async Nov 01 '14 at 13:30
6

Yes. In your class level variables will assign to its default value even if you don't initialize them.

In this case you int variables will assign to 0 and will occupied 4 bytes per each.

glglgl
  • 89,107
  • 13
  • 149
  • 217
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
4

Neither the Java Language Specification nor the Java Virtual Machine Specification specifies the answer to this because it's an implementation detail. In fact, JVMS §2.7 specifically says:

Representation of Objects

The Java Virtual Machine does not mandate any particular internal structure for objects.

In theory, a conformant virtual machine could implement objects which have a lot of fields using set of bit flags to mark which fields have been set to non-default values. Initially no fields would be allocated, the flag bits would be all 0, and the object would be small. When a field is first set, the corresponding flag bit would be set to 1 and the object would be resized to make space for it. [The garbage collector already provides the necessary machinery for momentarily pausing running code in order to relocate live objects around the heap, which would be necessary for resizing them.]

In practice, this is not a good idea because even if it saves memory it is complicated and slow. Access to fields would require temporarily locking the object to prevent corruption due to multithreading; then reading the current flag bits; and if the field exists then counting the set bits to calculate the current offset of the wanted field relative to the base of the object; then reading the field; and finally unlocking the object.

So, no general-purpose Java virtual machine does anything like this. Some objects with an exorbitant number of fields might benefit from it, but even they couldn't rely on it, because they might need to run on the common virtual machines which don't do that.

A flat layout which allocates space for all fields when an object is first instantiated is simple and fast, so that is the standard. Programmers assume that objects are allocated that way and thus design their programs accordingly to best take advantage of it. Likewise, virtual machine designers optimize to make that usage fast.

Ultimately the flat layout of fields is a convention, not a rule, although you can rely on it anyway.

Boann
  • 48,794
  • 16
  • 117
  • 146
2

In Java, when you declare a class attribute such as String str;, you are declaring a reference to an object, but it is not pointing yet to any object unless you affect a value to it str=value;. But as you may guess, the reference, even without pointing to a memory place, consumes itself some memory.