When I have a class like this:
class Test {
private int _id = 0 ; // 4 bytes
private int _age = 0 ; // 4 bytes
}
I'm sure that each instance of it will consume more than 8 bytes in memory because of the 2 integers.
But what about methods? If I have a class with a million methods, and 2 instances of it, are the methods going to take twice as much place in memory ?
How does it work?
Thank you.
No. Methods occur only once in memory1. They don't vary on a per instance basis, so they don't need storage on a per-instance basis.
An object in Java basically consists of some fixed-size "housekeeping" (a pointer to the type information including the vtable), potentially GC-related bits (think mark and sweep), information about the monitor for the instance etc - and then the fields.
1 This is a bit of a simplification. There may be various representations, such as bytecode, native code etc - but that's regardless of separate instances.
Having two instances of the same class does not duplicate the amount of space needed for the method code. That is to say, the methods reside in one place in memory and then each instance of the class has a pointer pointing to that place in memory. This is because otherwise memory would be wasted. The code that needs to be executed for each method is the same, regardless of which instance of the class calls it, so it would make no sense to duplicate it.
But to execute the methods like instance.method(), the local copy of the method will be made in stack per instance, where as the instance will be in the heap.
Related
As far as I know final tells the CPU that it can caches the variable/object (It anyway differs from CPU to CPU. I think x86 CPU-s are really doing a core cache L1)
My question is:
In the following example I have an object myObjectFinal set as final so the CPU can cache it and then it changes a value inside. Does this mean that myObject is not guaranteed to be also changed?
Does the reference gets broken if I set final and the CPU decide to cache it?
What if I change myObject, is the cached final guaranteed to get also changed?
// thread 1
volatile MyObject myObject = new MyObject();
// thread 2
final MyObject myObjectFinal = myObject;
myObjectFinal.setData(1);
// thread 1
myObject.setData(2);
Maybe the code does not tell exactly what I mean. So, the main question is: Does making a mutable object final or volatile have any repercussions to how the object is cached by the CPU. If it does then when I should use final or volatile on mutable objects?
Does the CPU ever caches a mutable object or final/volatile have absolutely no effect on them and are used only for coding consistency?
final means, that the value cannot be changed after initialization.
Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4
so unless you reassign myObjectFinal, nothing bad will happen,
However if you change the same object from multiple threads, you will need synchronization. (don't use volatile)
First of all, get rid of the object-orientation. An objects is a virtual construct. we are talking about low-level stuff like registers and caches - there are only primitives (every class can be reduced to a set of primitives)
The reason, why we need caches is simple.
The memory is just horrible slow. So the idea is to reduce the number of memory-accesses to a minimum.
consider the following code:
1. x=0;
2. if (x == 1)
3. x++
inside of your normal computer now happens something like this (without register-optimization)
1. write 0 into a register
write the register into the memory
2. read x from the memory into a CPU-register
compare it with 1 and go to 3 or 4
3. read x from the memory into a CPU-register
increment register
write the register into the memory
a lot of redundant memory operations ... but you can eliminate them
1. write 0 into a register
write the register into the memory
2. compare the register with 1 and go to 3 or 4
3. increment register
write the register into the memory
we keep the value of x in the register. So why not keep all variables in registers? first of all there arent that many registers available, so you cannot store everything there. Its more a temporary thing to hold a variable in a register. (inside a scope for example)
The other problem is, that no other core and/or device can read from the registers. then you need to reload/write-back the variable.
if you declare a variable as final, it will never be changed. So the variable could be stored in a register without having a problem with inconsistency. However this does not mean, that other threads cannot access the variable, since its also stored inside of the memory. Its guaranteed that the value in the memory is always valid. But all variables regardless of being final or not, can and will be stored for a short time in registers. thats why we need to use a synchronization-tool, which forces the write-back from the registers to the memory, if you want to guarantee the consistency on multiple threads/cores.
however the real CPU-cache, is a complete different topic. its a complete transparent system (executes on hardware-side!), which is only affected by the memory-access-pattern (unless you really do some crazy low-low level-stuff in assembly). To make it short here: The CPU-cache basically caches every byte, unless you explicit force it to not do it.
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?
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.
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)
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.
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.
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.
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.
I have a coding dilemma, and I don't know if there's a pattern or practice that deals with it. Whenever I have to pass some values to a method, most times I try to pass only the needed objects, instead of passing the objects which are being composed by them.
I was discussing with a friend about how Java manages heap and memory stuff and we didn't get anywhere.
Let me give two examples:
//Example 1:
private void method doSomething(String s, Car car, boolean isReal){...}
...
String s = myBigObject.getLabels.getMainName();
Car car = myBigObject.getCar();
boolean isReal = myBigObject.isRealCar();
doSomething(s, car, isReal);
//Example 2 - having in mind that BigObject is a really big object and I'll only use those 3 atributes:
private void method doSomething(BigObject bigObject){...}
...
doSomething(myBigObject);
In the 2nd example, it seems to me memory will be kind of wasted, passing a big object without really needing it.
Since Java passes only references to objects (and copies them, making it technically pass-by-value), there is no memory overhead for passing "big objects". Your Example 1 actually uses a little more memory.
However, there may still be good reason to do it that way: it removes a dependency and allows you to call doSomething on data that is not part of a BigObject. This may or may not be an advantage. If it gets called a lot with BigObject parameters, you'd have a lot of duplicate code extracting those values, which would not be good.
Note also that you don't have to assign return values to a local variable to pass them. You can also do it like this:
doSomething(myBigObject.getLabels().getMainName(),
myBigObject.getCar(),
myBigObject.isRealCar());
You're already only passing a reference to BigObject, not a full copy of BigObject. Java passes references by value.
Arguably, you're spending more memory the first way, not less, since you're now passing two references and a boolean instead of a single reference.
Java uses pass by value, when ever we pass an object to a method keep in mind that we are not going to pass all the values store in side the object we just pass the bits( some thing like this ab06789c) which is the value of the address on which the object is stored in memory(Heap Memory). So you are wasting more memory in first case rather than the 2nd one. Refer to JAVA pass-by-reference or pass-by-memory
All references are the same size, so how could it use more memory? It doesn't.
There are cases when one needs a memory efficient to store lots of objects. To do that in Java you are forced to use several primitive arrays (see below why) or a big byte array which produces a bit CPU overhead for converting.
Example: you have a class Point { float x; float y;}. Now you want to store N points in an array which would take at least N * 8 bytes for the floats and N * 4 bytes for the reference on a 32bit JVM. So at least 1/3 is garbage (not counting in the normal object overhead here). But if you would store this in two float arrays all would be fine.
My question: Why does Java not optimize the memory usage for arrays of references? I mean why not directly embed the object in the array like it is done in C++?
E.g. marking the class Point final should be sufficient for the JVM to see the maximum length of the data for the Point class. Or where would this be against the specification? Also this would save a lot of memory when handling large n-dimensional matrices etc
Update:
I would like to know wether the JVM could theoretically optimize it (e.g. behind the scene) and under which conditions - not wether I can force the JVM somehow. I think the second point of the conclusion is the reason it cannot be done easily if at all.
Conclusions what the JVM would need to know:
The class needs to be final to let the JVM guess the length of one array entry
The array needs to be read only. Of course you can change the values like Point p = arr[i]; p.setX(i) but you cannot write to the array via inlineArr[i] = new Point(). Or the JVM would have to introduce copy semantics which would be against the "Java way". See aroth's answer
How to initialize the array (calling default constructor or leaving the members intialized to their default values)
Java doesn't provide a way to do this because it's not a language-level choice to make. C, C++, and the like expose ways to do this because they are system-level programming languages where you are expected to know system-level features and make decisions based on the specific architecture that you are using.
In Java, you are targeting the JVM. The JVM doesn't specify whether or not this is permissible (I'm making an assumption that this is true; I haven't combed the JLS thoroughly to prove that I'm right here). The idea is that when you write Java code, you trust the JIT to make intelligent decisions. That is where the reference types could be folded into an array or the like. So the "Java way" here would be that you cannot specify if it happens or not, but if the JIT can make that optimization and improve performance it could and should.
I am not sure whether this optimization in particular is implemented, but I do know that similar ones are: for example, objects allocated with new are conceptually on the "heap", but if the JVM notices (through a technique called escape analysis) that the object is method-local it can allocate the fields of the object on the stack or even directly in CPU registers, removing the "heap allocation" overhead entirely with no language change.
Update for updated question
If the question is "can this be done at all", I think the answer is yes. There are a few corner cases (such as null pointers) but you should be able to work around them. For null references, the JVM could convince itself that there will never be null elements, or keep a bit vector as mentioned previously. Both of these techniques would likely be predicated on escape analysis showing that the array reference never leaves the method, as I can see the bookkeeping becoming tricky if you try to e.g. store it in an object field.
The scenario you describe might save on memory (though in practice I'm not sure it would even do that), but it probably would add a fair bit of computational overhead when actually placing an object into an array. Consider that when you do new Point() the object you create is dynamically allocated on the heap. So if you allocate 100 Point instances by calling new Point() there is no guarantee that their locations will be contiguous in memory (and in fact they will most likely not be allocated to a contiguous block of memory).
So how would a Point instance actually make it into the "compressed" array? It seems to me that Java would have to explicitly copy every field in Point into the contiguous block of memory that was allocated for the array. That could become costly for object types that have many fields. Not only that, but the original Point instance is still taking up space on the heap, as well as inside of the array. So unless it gets immediately garbage-collected (I suppose any references could be rewritten to point at the copy that was placed in the array, thereby theoretically allowing immediate garbage-collection of the original instance) you're actually using more storage than you would be if you had just stored the reference in the array.
Moreover, what if you have multiple "compressed" arrays and a mutable object type? Inserting an object into an array necessarily copies that object's fields into the array. So if you do something like:
Point p = new Point(0, 0);
Point[] compressedA = {p}; //assuming 'p' is "optimally" stored as {0,0}
Point[] compressedB = {p}; //assuming 'p' is "optimally" stored as {0,0}
compressedA[0].setX(5)
compressedB[0].setX(1)
System.out.println(p.x);
System.out.println(compressedA[0].x);
System.out.println(compressedB[0].x);
...you would get:
0
5
1
...even though logically there should only be a single instance of Point. Storing references avoids this kind of problem, and also means that in any case where a nontrivial object is being shared between multiple arrays your total storage usage is probably lower than it would be if each array stored a copy of all of that object's fields.
Isn't this tantamount to providing trivial classes such as the following?
class Fixed {
float hiddenArr[];
Point pointArray(int position) {
return new Point(hiddenArr[position*2], hiddenArr[position*2+1]);
}
}
Also, it's possible to implement this without making the programmer explicitly state that they'd like it; the JVM is already aware of "value types" (POD types in C++); ones with only other plain-old-data types inside them. I believe HotSpot uses this information during stack elision, no reason it couldn't do it for arrays too?
We have a big class with 68 int, 22 double members, and there are also 4 members as class.
e.g
Class A{
public int i1
public int i2
public int i3
....
public Order order1
public Order order2
...
public double..
}
1: Is the memory of i1,i2,i3 is continually physically?
2: For class A, does it store the pointer to order1 & order 2, or it stores the content of order 1 & order 2?
There is another class B which has a member as an array of A, there are 365 A. So the memory for B could be very large. My concern is if the size of B is too huge, we can get lots of cache level 2 missing and degrade the performance. We mainly will sum the value of i1, and sum the value of i2, and sum the value of i3 etc.
e.g if sum i1 for all 365 A, then the i1 for all these 365A will not sit continually in the memory. So we could hit some cache missing and get not good performance.
I am thinking of using class B but remove the class A, and move all the elements inside A to B, so we can get
Class B {
public array_of_i1
public array_of_i2
..
}
In this way, when I calculate the sum of i1 or i2, then all the i1 or i2 are sitting together, so maybe we could get performance improvement?
As the class is huge, I'd like to look for your opinions before the change.
It's generally consecutive but it depends on which JVM you are using.
One complication is that runtime in
memory structure of Java objects is
not enforced by the virtual machine
specification, which means that
virtual machine providers can
implement them as they please. The
consequence is that you can write a
class, and instances of that class in
one VM can occupy a different amount
of memory than instances of that same
class when run in another VM.
As for the specific layout,
In order to save some memory, the Sun
VM doesn't lay out object's attributes
in the same order they are declared.
Instead, the attributes are organized
in memory in the following order:
doubles and longs
ints and floats
shorts and chars
booleans and bytes
references
(from http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html)
He also includes how inherited classes are handled.
The JLS doesn't strongly specify the exact sizes of objects, so this can vary between JVM implementations (though you can infer some lower bounds, i.e. an integer must be at least 32 bits).
In Sun's JVM however, integers take 32 bits, doubles take 64 bits and object references take 32 bits (unless you're running on a 64-bit JVM and pointer compression is disabled). Then the object itself has a 2 word header, and the overall memory size is aligned to a multiple of 8 bytes.
So overall this object should take 8 * ceil((8 + 68 * 4 + 22 * 8 + 4 * 4) / 8) = 10448 bytes, if I haven't forgotten to account for something (which is entirely possible), and if you're running on a 32-bit machine.
But - as stated above, you shouldn't really rely too strongly on this as it's not specified anywhere, and will vary between implementations and on different platforms. As always with performance-related metrics, the key is to write clean code, measure the impact (in this case use a profiler to look at memory usage, and execution time) and then optimise as required.
Performance only really matters from the macro perspective; worrying about L2 cache misses when designing your object model is really the wrong way round to do it.
(And a class with 94 fields is almost certainly not a clean design, so you're right to consider refactoring it...)
Firstly, before you embark on any work, have you profiled your application? Are cache misses causing a bottleneck?
What are your performance requirements? (Note: 'As fast as possible' isnt a requirement*)
That would be implementation dependent.
Yes, it stores pointers. The objects will reside elsewhere.
In general, yes. But I don't think you necessarily want to depend on it. Wrong language for that low-level type stuff.
Pointers, but I'm not sure why that matters.
Profile before making significant changes for performance reasons. I think the second is cleaner though. Wouldn't you rather do a simple array loop for your summing?
Or you could change the structure to use a smaller class, keeping the stuff that runs in a tight loop together will tend to improve cache hits (iff that is your performance bottleneck).