Java memory questions about 'new' keyword - java

What happens if you run the following code..
while (true) {
String x = new String("ABC");
}
in terms of memory?
Is String x allocated on the stack or on the heap? Will the program eventually crash because of a memory overflow, or will garbage collection prevent that? Does the new keyword always create the object on the heap? When is an object created on the stack?
Thanks!

Is String x allocated on the stack or on the heap?
x isn't a String. It is a reference to a String. The reference is a local variable, and so goes on the stack. The String is an object, and so goes on the heap.
Will the program eventually crash because of a memory overflow
Probably not.
or will garbage collection prevent that?
It should.
Does the new keyword always create the object on the heap?
Yes.
When is an object created on the stack?
Never ... unless the JVM decides it cannot escape the current scope and so decides to do so.

Using new, yes, puts objects on the heap. Objects that are no longer accessible by any thread can be garbage collected. Whether you run out of memory or not depends on the size of data your program uses, and if you are good at 'releasing' objects you dont need any more (think: memory leaks are bad).
In your example, you will be running the garbage collector like crazy, which I think is what you are intending to demonstrate.
Local variables go on the stack.

In theory, new creates on the Heap, and non-objects (i.e., ints, chars and so on) are created on the stack. The only exception, afaik, are strings, created on the stack as well. In practice, the JIT compiler of many modern JVMs will see that, in some cases, objects created with new can be created on the stack (for example, local objects that are not referenced outside of the current function).
The garbage collector will take care of the deallocation for you, that's its purpose, but of course you can run out of memory if you create and keep references on too many objects at the same time (try creating a list with a billion strings, for example).

Related

declaring objects in C++ vs java

I have been using c++ for a while now and I am learning java,
declaring objects in java is confusing me,
In java we write
myclass myobject = new myclass();
myobject.mymethod();
Is it same as this code in c++ ?
myclass *myobject = new myclass();
myobject->mymethod();
i.e is the memory getting allocated on heap? If it is on heap why we never free the memory. I believe the new keyword is the same.
If so, how do we allocate memory on stack?
Is it same as this code in c++ ?
Yes. It's the same.
i.e is the memory getting allocated on heap?
Yes it.
If it is on heap why we never free the memory.
The object is allowed to garbage collector when it is no more reachable. i.e when there are no valid reference to that object or (de-referenced)
If so, how do we allocate memory on stack?
When the particular thread execution starts, variables related to that thread will be placed on stack and will be remove immediately once the job of that thread finished. Every thread has it's own stack.
As you thought, the new operator allocates a new object on the heap. Memory in Java is not freed explicitly - once an object has no more access roots, it is eligible for being freed. Periodically, a garbage collection thread will free this memory.
Whilst it is not inaccurate to say that this C++ code is equivalent:
myclass* myobject = new myclass();
myobject->mymethod();
It is also not exactly the same.
Java has a Garbage Collector and so, as you note, you do not have to free the object in Java.
So a closer approximation to the original Java might be this:
std::shared_ptr<myclass> myobject = std::make_shared<myclass>();
myobject->mymethod();
Now you do not have to deallocate myobject it gets garbage collected when there are no longer any references to it.
However it would be a mistake in C++ to use std::shared_ptr for every heap-allocated object because it really drags down the performance.
As a rule it is better to manage the heap allocated object in one place using a std::unique_ptr. If it is impossible to know which component will be the last to de-reference the object, a std::shared_ptr should be used in each place.
However when calling down to functions from the component that holds the smart pointer you should pass the raw pointer or a reference:
std::shared_ptr<myclass> myobject = std::make_shared<myclass>();
myobject->mymethod();
ptr_needing_func(myobject.get()); // pass raw pointer using get()
ref_needing_func(*mtobject.get()); // pass reference using *get()
This way you don't lose any efficiency while still maintaining the safety and convenience of garbage collecting smart pointers.
See: CppCoreGuidlines: R.23
After reading other answers to this question and some other articles, I understood that,
Both the c++ and java code are doing the very similar thing except the syntax is different and java is using references instead of pointers(Java doesn't have pointer).
Here,
myclass myobject; is a declaration of myobject,
Declarations simply notify the compiler that we will be using myobject to refer to a variable whose type is myclass. It is not allocating the memory.
new myclass(); is instantiating the object (allocating the memory in the heap) and returning the reference to it.
It is also initializing the object by calling the constructor myclass().
Clarification of a very basic doubt,
int i; ==> Declaring the object and allocating memory for it in stack.
myclass myobject;==> Only declaring the reference variable for the object(It also takes 4 bytes or 8 bytes depending on system). It does not allocate actual memory where the instance variables will be stored.
In other words, memory is allocated while declaring for the primitive data types but not for the non-primitive data type. For non-primitive data types we need to allocate them using new keyword.
Why we never free the memory?
Java has garbage collector that does it for us automatically.
How do we allocate memory for objects in stack?
We can't. Only primitive data types can be stored in stack.

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.

How to make sure String objects are garbage collected in Java

Here is the code snippet.
method(){
String s1="abc";
String s2 = new String ("abc");
s1=null;
s2=null;
--------
---------
}
At the end is s1 & s2 objects are exists? How you will make sure these objects are garbage collected ?
Objects referenced to by s1 and s2 are eligible for garbage collection once s1=null and s2=null provided that no other references to that Object exists or when the method exits, provided that the Objects were only referenced by the local variables.An object once created uses some memory and the memory remains allocated till there are references for the use of the object.When there are no references for an object, it is assumed to be no longer needed and the memory occupied by the object *can be reclaimed.*An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null.
There are methods like System.gc() and Runtime.gc() which is used to send request of Garbage collection to JVM but it’s not guaranteed that garbage collection will happen. Java programmers can not force Garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection. Forced GC is sign of bad coding.Once should in turn always look to minimize creation of unnecessary objects and references to those objects.
They get garbage Collected after they go out of scope.
Unless you're actually having serious performance issues, I'd stop worrying about it so much and let the garbage collector do it's thing.
You should be careful though, there are some kinds of elements such as file streams, open sockets, and such that are not managed like that. you have to close those.
If the question is how to make sure, the answer is fairly simple. You can never make sure that any object will be garbage collected. Read this to understand what garbage collection really is and how to reason about it.
If the question is how to hint for a collection, then set all the references of unwanted objects to null and call System.gc(), which will request (not force) a collection. Nothing is guaranteed to be released using this method, but often it's the closest thing you can get.
If you want to do this specifically for strings, because they may contain sensitive data or something along these lines, use a char[] to store that data instead of a String, because you can change the primitive values of the array at will and erase them when you're done.
Garbage collector runs periodically(time period is JVM dependent). Java maintains table of objects and its references when reference is broken (probably by assigning null to reference) then on next execution of GC (garbage collector) object's having no reference will be deleted (If something goes wrong with GC then object will not garbage collected - very very rare condition), which is totally dependent on JVM. You can send request to JVM to run GC by using following code (Processing your request is once again JVM dependent):
Runtime.getRuntime().gc();
or
System.gc();
Programmer don't have to worry about the running GC mostly JVM will handle execution of GC. There are lots of enhancements made to the garbage collectors. Java (latest version) comes with G1(Garbage First) collector which is a server-style garbage collector which runs more effectively. G1 is a great replacement for CMS (Concurrent Mark-Sweep Collector).
If you want to know more about garbage collector then you should read the pages:
[http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html][1]
[http://docs.oracle.com/javase/7/docs/technotes/guides/vm/cms-6.html][2]
[http://docs.oracle.com/javase/7/docs/technotes/guides/vm/par-compaction-6.html][3]
String s2 = new String ("abc");
Here 'abc' will be created in regular, garbage collectible heap area.
So as soon as you make S2 null, this string object is eligible for garbage collection.
This is assuming that your programm do not have any other reference to this particular string object "abc".
String s1="abc";
In this case, "abc" will be created in special area of heap called literal pool or string pool. Making "abc" null does not make "abc" eligible for garbage collection since JVM will try to reuse this "abc" in future.
Baseline in this case is, normal garbage collection rules won't apply here.
Hope this helped. :-)

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.

Java Assignment Memory Leaks

I have to assume that the following method doesn't leak memory:
public final void setData(final Integer p_iData)
{
data = p_iData;
}
Where data is a property of some class.
Every time the method gets called, a new Integer is replacing the currently existing data reference. So what's happening with the current/old data?
Java has to be doing something under the hood; otherwise we'd have to null-out any objects every time an object is assigned.
Simplistic explanation:
Periodically the garbage collector looks at all the objects in the system, and sees which aren't reachable any more from live references. It frees any objects which are no longer reachable.
Note that your method does not create a new Integer object at all. A reference to the same Integer object could be passed in time and time again, for example.
The reality of garbage collection is a lot more complicated than this:
Modern GCs tend to be generational, assuming that most objects are short-lived, so it doesn't need to check the whole (possibly large) heap as often; it can just check "recent" objects for liveness frequently
Objects can have finalizers - code to be run before they're garbage collected. This delays garbage collection of such objects by a cycle, and the object could even "resurrect" itself by making itself reachable
Modern GCs can collect in parallel, and have numerous tweaking options
Java is a garbage-collected language.
Once there are no more live references to an object, it becomes eligible for garbage collection. The collector runs from time to time and will reclaim the object's memory.
In a nutshell, your code is 100% correct and is not leaking memory.
It gets garbage collected eventually.
if there is no ther reference to data, the garbage collector of java will clean the old data up and free the memory
Actually, since Integer is an object not a primitive type, the line:
data = p_iData;
is updating a reference.
Now, the old object that this.data used to point to will be examined by the GC to determine if there are no more references to that object. If not, that object is destroyed and the memory is freed (at some later time)
If the object previously referenced by data is no longer referenced by any object structure that is referenced from any running thread it is eligible for garbage collecion. GC is performed by Java in the background to free the memory of unused objects.
i want to show one example to you
in some code :
int x;
x=10;
x=20;
initially i assigned x to 10
again x to 20
first reference memory will be handled by Java GC.
Java GC is a thread tht run continuously and checked unreferenced memory and clean it .

Categories

Resources