declaring objects in C++ vs java - 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.

Related

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.

management of the objects

I have a doubt with the management of the objects using java or c++.
The case is, in c++, when you want to create a dynamic object, one that survive more than the block scope on where it is created, you have to do a new and you will receive a pointer. Otherwise, if you just want to use this object in the block scope, you don't need to create it using new...
But in Java, you always have to create them using new, because if not, the object is null and you can use it.
Why is that? Is it just how it works?
Thanks
The best analogy I can think of, is that all types in C++ behave somewhat like primitives in Java. If you declare a primitive in Java, you don't have to use new, you can just use the variable right away. But such a primitive, much like most objects in C++, will only survive the current scope. In C++, if you want an object to exist outside of the current scope, you need to tell this to your compiler, because it will have to allocate memory on the heap instead of the stack. You can do this by using new. In Java, all objects (save primitives) are allocated on the heap, the only data on the stack are references to heap memory, and primitives. Therefor, in Java, all memory allocations are done using new.
The above is a simplification of the actual memory management in Java. For a more thorough discussion on stack/heap memory regarding primitives, take a look here.
This difference is becaase Java is using a garbage collector for memory management. Since the garbage collector automatically deallocates objects when their scope ends (and it has no reachable reference), there is no need to have two different methods for creating objects.
You can say that objects in Java automatically behaves like objects in C++ which are initialized without new, in that you don't have to think about deleting them.
Basically, that's just how it works. Once the new keyword is used then the Object is created and popped onto the heap. If you do not reference the object outside of a method then it will be automatically reclaimed by the garbage collector.
I suggest that you do some reading around the basics of the Java heap and garbage collection to get a better understanding. There are plenty of resources out there. I always recommend the head first books for new comers.
In C++, anything can be allocated on a stack (which is what happens when you say
ObjectType o;
in C++.
In Java, only primitives are really allocated on the stack. Objects are never on the stack (It's just how it is). When you say
ObjectType o;
in Java, no object is allocated, only a "variable". A variable can have a reference to an object, but at the moment it has none. In essence, it's the same thing as saying
ObjectType *o = NULL
in C++.
In order to actually allocate an object for this reference to refer to, you have to use new in Java.
The case is, in c++, when you want to create a dynamic object, one that survive more than the block scope on where it is created, you have to do a new and you will receive a pointer.
The new operator in C++ allocates space on the heap. The heap is where the larger part of the main memory is. If you do this, you are responsible for freeing that space when you're done with it using the free operator.
Otherwise, if you just want to use this object in the block scope, you don't need to create it using new...
When you declare variables in C++, memory is allocated on the stack. The stack is where local data is stored and everything you push(add) on it while executing a function will be automatically popped (removed) when the function returns. The stack is usually a lot smaller than the heap, but there are advantages to using it: you don't need to worry about memory management, it is faster, etc.
But in Java, you always have to create them using new, because if not, the object is null and you can use it.
When you declare variables in Java, they are again stored on the stack
As you know, you don't call new on primitive data types (e.g. int i = new int(3);). When you do something like Object x; you declare that x would be a reference to an object of type Object. However, you do not assign a value to it, so the reference is null (not the object, because there isn't one).
The new operator in Java, roughly speaking, allocates space on the heap, calls the constructor of the object that it is invoked on, and returns a reference to the constructed object. The difference with C++ is that you don't need to free the object yourself - there is a garbage collector. In essence, what it does is that it monitors how many references point to an object, and if they go down to zero it deletes the object automatically.
So when you do Object y = new Object();
x = y; you will get two references (x and y) pointing to the same object. When you have a function call like thisObject foo() {
Object y = new Object();
return y;
}
void bar() {
Object x = foo();
...
} in the ... part of bar() you would have the reference x, pointing to the object created in foo(). Since foo has returned, the y reference has been freed, thus there would be only one reference to this object in the ... part of the program. If you don't copy the x reference anywhere in bar and bar returns, then there would be 0 references to the object, and the garbage collector would collect it (although not immediately).
-Stan

Java memory questions about 'new' keyword

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).

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