简体   繁体   中英

(Java) Does a variable of an object use memory space if declared but not initialised?

I have a Class which I want to use some ten to 100 thousands of. Therefor I don't unnecessarily wanna waste memory location for.

Only in a few (<100) of them I need 2 special variables. If I just declare them but don't initialise them, do I need the same disc usage as if I would initialise them?

And if yes, do I have another option (besides making them an own class) to reduce memory usage?

this is my code example ( name and propability I only need few times):

public class Neuron {

  private String name;
  private float propability;
  private float connection[];
  private float bias;

  public Neuron(float[] connection, float bias) {
    this.connection = connection;
    this.bias = bias;
  }

  public Neuron(int propability, String name, float[] connection, float bias) {
    this.name = name;
    this.propability = propability;
    this.connection = connection;
    this.bias = bias;
  }

    //more code

}

thanks in advance for any help!

Even if not used in the constructor :

public Neuron(float[] connection, float bias) {
    this.connection = connection;
    this.bias = bias;
}

all instance fields (so name and propability too) are initialized before that the constructor be executed. These are initialized with a default value :

private String name; // null
private float propability; // 0F

But these default values cost nothing ( null and 0 ).
So don't bother with that.


I have a Class which I want to use some ten to 100 thousands of. Therefor I don't unnecessarily wanna waste memory location for.

And if yes, do I have another option (besides making them an own class) to reduce memory usage?

If these objects have some common data, share these data between the instances.
The flightweight pattern that rely on immutability of shared data illustrates that practice.
The String objects use that.


Agreed completely with the remark of GhostCat : fields even not used consume memory. Not a lot but they consume. But that is right for many classes in Java.
For example we will not replace all lists by arrays because the arrays consume less in general. We will do that because in our specific case, the list memory occupation is a real worry.

To sum up, before optimizing and to change our design, I think that the first thing to do is measuring and to deem whether you want to optimize to gain gold or nuts.

With your actual code and that main() method that produces 1 millions of Neuron, I notice that about 131 Mo are consumed :

  public static void main(String[] args) {
    long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
    List<Neuron> neurons = new ArrayList<>();
    for (int i = 0; i < 1_000_000; i++) {
      neurons.add(new Neuron(new float[] { 0, 15.4F, 1.1F, 2.1F, 3.4F, 4.5F, 8.9F, 158.9F, 8648.9F, 80.9F, 10.9F, 1450.9F, 114.9F, 14.5F, 4444.4F }, 1.9F));
    }
    long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
    long actualMemUsed=(afterUsedMem-beforeUsedMem)/1_000_000;
    System.out.println(actualMemUsed + " Mo");
  }

Objectively, it is low.

By removing the unused fields, it drops about to 124 Mo (7 Mo in less) :

private String name;
private float propability;

131 Mo as 124 Mo are quite low values for so many created objects : 1 million.
If the class declared a dozen of unused fields, things would be different. A no negligible amount of memory would be wasted and overall the class would be not clear at all in terms of design : low cohesion.
But there that is not the case.

I have to disagree a bit:

private float connection[];
private float bias;

The first one (the array) is a reference type. In other words: a (potential) pointer to some memory area. Obviously : as long as that pointer points to null ("nowhere"), no extra memory is required.

But make no mistake, your object itself needs to fit into memory. Meaning: when you instantiate a new Neuron object, then the JVM requests exactly that amount of memory it needs to store a Neuron object. This means: there is a bit of memory allocated to fit that array reference into it, and of course: the memory for your float primitive values, they are all immediately allocated.

It doesn't matter whether you have 0 or 100.00 or 10394.283 stored in that member field: because the JVM made sure that you have enough memory to fit in the required bits and bytes.

Thus: when you really have millions of objects, each float field in your object adds 32 bits. No matter where the value within that field is coming from.

Sure, if your arrays will later hold 5 or 10 or 1000 entries, then that will make up most of your memory consumption. But initially, when you just create millions of "empty" Neuron objects, you have to "pay" for each and any field that exists in your class.

Meaning: when only 1 out of 100 Neuron object will ever need these two fields, then you could decide to have:

  • A BaseNeuron class that doesn't have all 4 fields
  • one or more classes deriving from that class, adding the fields they need

Also note that this can also be the better choice from a design perspective: "empty" values always mean: extra code to deal with that. Meaning: if that array can be null ... then of course, all code dealing with that field has to check whether the array is null before using it. Compare that to: a class not having that array, versus a class where you know that the array is always set and ready to use.

I am not saying that you absolutely must change your design, but as explained: you can reduce your memory footprint, and you could make your design more clear by doing so.

Well, yes they make a difference but how significant that different is debatable according to your use case/jvm implementation/hardware resources you have. If you're running your application on a server with 500mb of ram and 1 cpu and your application is creating those objects at high rate (number of object over time) and the garbage collector is not able to cleanup after that rate, then yes eventually you will run into memory issues. So technically and by Java Language Specs, they take memory but practically and based in your use case it might not be any issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM