How does variable memory allocation work? - java

When I create new object for String builder and use that variable then how memory allocation work and what is result of my code snippet my sample code is
1)
String nextPoint=new StringBuilder().append("My").append("next").append("point").toString();
System.out.println(nextPoint);
2)
StringBuilder downPoint=new StringBuilder().append("My").append("next").append("point");
System.out.println(downPoint.toString());
Which variables/instance can consume memory?? which solution is better when i'm using "nextPoint" varaible or "downPoint" variable?

Which variables/instance can consume memory?
Every class occupies memory. How much depends on the class. Every object occupies heap memory. How much depends on its class. Many classes and objects also contain references to other objects, and those other objects occupy their own heap memory. Some objects also have associated native resources, which occupy an idiosyncratic amount of memory. Local variables occupy stack memory appropriate for their type, though under some circumstances certain local variables may share the same stack memory as others.
In your case (1):
String nextPoint=new StringBuilder().append("My").append("next").append("point").toString();
System.out.println(nextPoint);
variable nextPoint is a local reference variable, consuming stack memory (for a reference, not a whole String). It is initialized by creating a new StringBuilder object (on the heap) and appending three Strings to it (each one an object occupying heap memory), and then creating a new String object (also occupying heap memory), and storing a reference to it in nextPoint. The StringBuilder will have some kind of associated storage for the accumulated character data; this will not overlap that of any of the Strings involved.
Your case (2) differs only in that a reference to the StringBuilder is retained instead of a reference to the generated String. That may have implications for code that follows, but it makes no difference to which objects are created and what memory is needed.
which solution is better when i'm using "nextPoint" varaible or "downPoint" variable?
It depends on what you want to do afterward. If you're not going to use either of those variables again then the difference is purely stylistic.
what is result of my code snippet [?]
Put it in a class, run it, and find out for yourself. Or figure it out from the code. This one is not something you should need us to answer for you.

Both snippets do the same sequence of method calls, being
new StringBuilder().append("My").append("next").append("point").toString(),
so their memory usage is (mostly) the same. Only snippet (1) stores a reference to the StringBuilder in a variable, and (2) stores the resulting String reference. But as references are the same size, no matter what the refer to, that results in the same number of bytes occupied.

Related

When is memory allocated during instance creating or using new keyword for object creation?

As I read somewhere, memory is allocated when instances are created and a space is allocated from the heap. If it is right than when and how much exactly memory is allocated during instances and objects creation?
Variables declared within a method are stored within the stack, while the actual objects are stored on the heap. Consider
Integer a = new Integer(10);
In this example, an object of type Integer is created on the heap and a reference (either 32 or 64bits) is returned and stored within the methods stack as variable 'a'. The JVM is free to keep variables like this within the CPU registers if it prefers as an optimization.
Memory of an object is allocated when the new keyword is used. It is usually assigned within the TLAB (thread local allocation buffer) which is part of the eden heap reserved to the running thread. Thus reducing the overheads of object allocation to a simple 'bump of a pointer'. The two times when the TLAB is not used, is 1) when the object is too large for the space remaining, inwhich case it will be promoted straight to the old gen and 2) when a supporting JVM decides via escape analysis that it can avoid the object entirely and allocate directly on to the stack (or even break the object apart and only assign the fields required on the stack).
The amount of memory reserved consists of an object header, usually 2 words (3 for an array) and then space for each of the fields declared in the object and its parent classes. The total size of those fields depends on the JVM and the underlying platform (eg 32 bit or 64 bit) and JVM configuration such as compressed references.
------------------+------------------+------------------ +--------------------------
| mark word | klass pointer | array size (opt) | padding and fields |
------------------+------------------+-------------------+--------------------------
Asking the JVM for sizes is not officially supported, but EHCache sizeOf is a very good 'best guess' that uses knowledge of different JVMs and access to the underlying pointers via the use of Java Unsafe.
The starting place for understanding the size of each field is the size of primitives defined by the Java language, however this is only the minimum sizes as the JVM is designed to work with 32bits and so primitives smaller than this are often padded out to 32 bits. For example booleans.
The exact layout of the fields will vary by JVM, but they will tend to be grouped by the class that defines them starting from the root of the inheritence tree. For example, consider
and
The pictures above were taken from this very good blog post that describes the memory layout very well,
"create instance" has the same meaning as "use new to create new object".
In a normal case, heap memory will be allocated at the time you ask for a new object, but that is not set in stone: HotSpot can also determine that it is safe to allocate the object on the call stack (by the process of Escape Analysis). This is more efficient as it doesn't need any garbage collection.
How much memory is allocated is highly implementation-specific, only Java arrays are guaranteed to be "packed" (modulo a fixed overhead). Boolean arrays, though, are specified as occupying a byte per element.
I'm reading your question as: "Who actually allocates memory for an object - the new keyword or the constructor?" If that's the case, the answer is the new keyword.
Constructors are typically chained, meaning that at least two constructors will run when you're creating an instance. On the other hand, memory for an instance is allocated only once.
Also, the type of allocation is determined using analysis of the usage of the produced reference (escape analysis, for example). This means that the most obvious place for the allocation to happen is at the constructor call site (that is, the place of the new expression).
The size of the memory allocated is such that it can accomodate an instance of the type following the new keyword. That latter size (the size of an instance of a type) is
the aggregate size of the primitive types (int, float, double, etc) it consists of,
plus the aggregate size of the references to the reference types (class or interface instances) it consists of,
plus "secret" stuff embedded in instances so that Java features can work (like a virtual table pointer, to allow fast runtime resolution of virtual method calls)
plus possible padding between each of those (to align the various types to their optimal address number multiples in memory).
In any case, when you do T obj1 = new T(), where T is the name of a class:
Memory is allocated somewhere to accomodate a T instance.
The instance is constructed.
If the instance is successfully constructed, a reference to the instance is returned.
That reference is stored in the obj1 variable.
When you do R obj2 = new R(), a similar thing happens for the type R, and type R may have a different size than T.
But neither of these local variables contains the instance. They both contain a reference to their assigned object. (Thus, the variables themselves might even be of the same size, if all they have to do is store a memory address.)
As I read somewhere that memory is allocated when instances are created and a space is allocated from the heap.
yes you are right, until and unless new is called it's just a null reference that is pointing to nothing.
If it is right than when and how much exactly memory is allocated when instances and objects are created?
It depends on the size of the object.
Have a look at Primitive Data Types to know about their size.
In Java, what is the best way to determine the size of an object?
Read more...
Class Variables
When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables. In the case of the Bicycle class, the instance variables are cadence, gear, and speed. Each Bicycle object has its own values for these variables, stored in different memory locations.
Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

In Java, is a global variable always put on the heap?

Also, how does having a static variable affect things? (If at all) For example:
class MyClass{
static int[][] data;
static {
data = new int[some number][some number]; /*read data into array*/
}
static void run() {
/*now use data here*/
}
}
Is this put on the heap? Comparing that example with
class MyClass{
static void run() {
int[][] data = new int[some number][some number];
/*now use data here*/
}
}
How much difference is there between these two code examples? Please shed any insight.
Java has a concept of PermGen space - this is the space used to store all class definitions, static variables, interned strings, etc.
here is link
This Java heap memory is structured again into regions, called generations. The longer an object lives, the higher the chance it will be promoted to an older generation. Young generations(such as Eden on Sun JVM) are more garbage collected than older generations(survivor and tenured on Sun JVM). However, there is also some separate heap space called permanent generation. Since it is a separate region, it is not considered part of the Java Heap space. Objects in this space are relatively permanent. Class definitions are stored here, as are static instances.
A full description of PermGen space can also be found here, although note that this is changing with Java 8: here is link
Static variables are stored there, dynamically allocated things are stored in the regular heap.
(Note that even for the static array the things placed within the array are dynamically generated).
Your second example is better for this case though unless you really need to remember the contents of that array between calls. You are using up memory all the time to store an array that you only need while you are inside the method. Additionally by having the static data like that your method is not re-entrant. That means that if two threads call the method at the same time then they will interfere with each other and give bad results.
Every object, that you create while your program is running, is created in the heap space. I think this is the most important thing to understand, when you are asking for antyhing "better".
A variable can be a local variable inside a method (method parameters are also local in this sense), or they belong to an instance or to a class. Here is the difference. The memory for local variables is allocated on the thread's stack, the memory for instance and class variables reside in the corresponding object's space, which is in the heap.
Keep in mind, that variables only store references to objects. They do not store the object! Therefore the memory consumption of variables is very low.
There are just two places where data can reside in JVM: the heap and the stack (well, JNI tricks inclusive it can reside anywhere, but this is an exception). All local variables in methods are located on the stack, everything else - on the heap. In both your examples array data is allocated on the heap, though in the second example the reference maze is a method local variable so is itself located on the stack.
One thing you must carefully distinguish is the following:
placement of the reference-typed variable;
placement of the referent (the array in your case).
If I follow your thoughts correctly, you are not really interested in 1., which is just four bytes, but in 2.
If the variable which refers to the array is static, the array will be placed on the heap;
if the variable is local, and if the JIT compiler can prove that your array will definitely not be reachable when your solve method completes, then there is a chance that the whole array will be stack-allocated.
For arrays, which are quite large, but efficiently allocated objects, it will make very little difference where they are allocated—as long as they don't get tenured into the Old Generation. If they do get tenured regularly, then you will probably experience significant slowdowns due to frequent Full GC cycles.

Stack vs Heap in C/Java

Here's my understanding.
In C programming, if I do int a then that a is created on stack and thus the memory is taken from stack. Heap plays no part here.
But if I do something like
int *a;
a=(int*)malloc(sizeof(int));
and dynamically allocate the memory, then the reference variable will be placed on stack, but the memory it points to will be on the heap.
Am I correct with my understanding?
Now, I picked up this book on java that says
Whenever you need an object, you
simply write the code to create it by using new, and the storage is allocated on the
heap when that code is executed.
So there's no way of creating objects on Stack in Java?
I guess, the primitive data types can still be placed on stack, but I am concerned about the Objects.
There is no way to create objects on the stack in Java. Java also has automatic garbage collection, so you don't have any way of deleting objects. You just let all references to them go out of scope and eventually the garbage collector deals with them.
That is correct. Objects are stored on the heap. The stack contains primitive values like int and double (from local variables) and references to objects (again from local variables).
The whole premise of your question is false: in Java you don't have any control over where the objects will be allocated. Some are indeed stack-allocated, but you'll never notice the difference.
What is fundamentally different between Java and C is that in Java the value of a variable can never be the object itself, whereas in C the value can be the struct itself, with no indirection. You can pass such structs by value to other functions and there is no equivalent of that in Java.

Why are reference types stored in heap

I do know that in Java, (perhaps in .net too) , primitives are stored on stacks , where as reference types are stored on heaps.
My question was that I do not understand the proc/cons for this behavior. Why can't we reference a memory location inside our stacks instead? . I couldn't find a proper explanation as I googled ( maybe I suck at it) , but if you people can provide some insights I would be grateful
Thanks.
I do know that in Java, (perhaps in .net too) , primitives are stored on stacks , where as reference types are stored on heaps.
No. It does not depend on whether its a primitive or a reference. It depends on the scope whether the stack or the heap is used. Local variables are allocated on the stack, member variables are allocated on the heap when the object is instantiated.
See also Do Java primitives go on the Stack or the Heap?
My question was that I do not understand the proc/cons for this behavior.
Data stored on the stack only lives as long as your method is executing. Once the method is done, all data allocated on the stack is removed.
Data stored on the heap lives as long as it is not discarded (which, in case of Java, is done in the background by the garbage collector). In other languages as C/C++, you explicitly need to delete/free data which was allocated on the heap.
Consider the following code snippet:
String someMethod() {
int i = 0;
String result = "Hello";
i = i + 5;
return result;
}
Here, a primitive (int i) is created on the stack and some calculation is done on it. Once the method finishes, i cannot be accessed anymore, and its value is lost. The same is basically true for the result reference: the reference is allocated on the stack, but the Object (a String object in this case) is allocated on the Heap. By returning the reference as return value, the object it references can still be used outside the method.
You can't generally store reference types on stack because the stack frame is destroyed upon method return. If you saved a reference to an object so it can be dereferenced after the method completes, you'd be dereferencing a non-existent stack location.
The HotSpot JVM can perform escape analysis and, if it determines that an object cannot possibly escape the method scope, it will in fact allocate it on the stack.
where as reference types are stored on heaps.
I don't know what exactly you mean by that part, but remember that, only objects are stored on heap, whereas, references pointing to those objects are still on the stack. Probably this was the doubt you had.
Now, you should also note that, only local variables are stored on stack, whereas instance / member variables are stored on Heap.
For e.g.: -
String str = new String("Rohit"); // Local variable
In above case, str reference will be allocated memory on stack, if of course it is defined in some local scope. And it will point to a new string object created on Heap.
Why can't we reference a memory location inside our stacks instead?
You can but think of this decision as Memory Architecture decision.
By concept, ideally, any data can't be retrieved from stack if it is not on top of it. But in real world you require some location to be accessed from anywhere in the program. So, it can't be stack. and they named it heap.
This link may throw more light on it.

Does the reference variable in Java have any size?

In C++ we used sizeof() operator, which function can we use in Java to check the size of an object?
My basic doubt is that whether the reference variable in java has any size or not. Consider the following example:
SampleClass obj = new SampleClass();
Here, will obj have any size? If yes, How can we check it in Java?
obj is a variable, not an object. The value of obj is a reference - which is likely to be 4 or 8 bytes, depending on the JVM.
The size of the object that the value refers to is also JVM-dependent. As several objects can refer to each other, it's generally tricky to talk about the size of an object in Java in any particularly useful way... what usually matters is how much more memory would be potentially available if a particular object became eligible for garbage collection, and that depends on what other objects the first object refers to - and whether there are other objects that refer to those, too.
Obviously the "raw" size of an object is somewhat important too, and at least somewhat easier to predict (to an approximation, at least), but it's still VM-specific and can't easily be requested at execution time. (You could create millions of objects, prevent them from being garbage collected, and measure memory differences, but that's the closest I know of, at least outside a debugger API.)
Since you found my comment superb, I just had to post it as an answer, although it may be superflous to the already existing answers:
Rest assured that a reference variable (like obj) has a size, although there won't be a platform-independent answer on how large this size is, but there definitely should be a size. But due to this platform (or JVM) dependence, Java is not the language to mess with such low-level details.
Maybe the compiler can optimize some reference variables away as being just aliases for others, but in general obj has to have a size, as it has to somehow store the reference (whatever this is, it is something and not nothing).
obj is only the reference to an instance of SampleClass.
The size that the instance of SampleClass occupies in the memory depends on the elements the files of the object, and VM. But even a reference need some memory of course (like in c)
But the java memory model is much more complicated. If you are really interessted in how much memory the object need, then I strongly recommend to use a memory analyzer.
Anyway: because java is a VM and the Java VM has the garbage collector, there is no real 1:1 relation ship between the size of the memory you would expect by counting the (living) java objects and the memory the VM allocates from the Operation System.
You might try getting some insight on the "size" of the reference by using the freeMemory method of the Runtime class.
For example, allocate an array of 1000000 null references:
SampleClass[] array = new SampleClass[1000000];
Check the free memory before and after; the difference may give a hint on what you want to know (the array itself is an object, though its size is probably much less than 1000000, so the measurement must be pretty precise).

Categories

Resources