How to overflow the heap? - java

I know that object references are created on the stack, and the objects themselves are created on the heap. In the code below, I try to fill the heap by creating a large number of Main objects, using recursion in the constructor; However, instead of an OutOfMemoryError, I get a StackOverflowError
public class Main {
public Main() {
new Main();
}
public static void main(String[] args) {
new Main();
}
}
Why does this happen?

When you create an object with new, it invokes the object's constructor. The constructor is a method. Each method invocation results in the creation of another stack frame, each of which is using a portion of your available stack space. Once you run out of stack space, you will get a StackOverflowError. An unlimited recursion will quickly exhaust the available stack space. With your code, there is a race between which will exhaust first, stack space or heap space; however, with most default limits, the stack is going to be much smaller than the heap.
To cause an OutOfMemoryError create lots of objects inside a while(true) loop, and ensure that the objects aren't collectible by the garbage collector. For example:
public class MyObject {
int[] array = new int[1024*256];
static List<MyObject> myList = new LinkedList<>();
public static void main(String[] args) throws Exception {
while(true){
myList.add(new MyObject());
}
}
}

Related

Where the instance variables and instance methods are stored in java?

In the below program, does it mean that 3 instance variables and 3 instance methods are created and memory is allocated to them ?
class Foo{
String name = "";
public void greet(String name){
this.name = name;
}
}
class Greetings {
public static void main (String[] args) {
Foo ob = new Foo();
Foo ob1 = new Foo();
Foo ob2 = new Foo();
ob.greet("hello friends");
ob1.greet("welcome to java");
ob2.greet("let us learn");
System.out.println(ob.name);
System.out.println(ob1.name);
System.out.println(ob2.name);
}
}
The Java Language Specification does not say anything about how memory is organized, or how objects, methods, and classes are represented.
So, the answer is: you can't and shouldn't know.
All the 3 objects are stored in a heap memory. The size of the heap increases decreases as the application runs. The new operator here allocates memory to the object in the heap. Which means each time you say new in the statement a separate memory space is allocated to that object in the heap The methods are stored in JVM internal heap.
you can find a simple example of how memory is managed for objects in java here

In Java why is the New instance of a class not assigned to a variable

Total beginner in Java. I have seen the line below several times and cannot understand it ... new TestCode() - it SEEMS to be an instatiation but not assigned to anything - So how can it be referred to ?
class TestCode
{
public TestCode()
{
System.out.println();
System.out.println( "Welcome to the Program");
}
public static void main( String args[] ){new TestCode();}
}
It cannot be referred to.
The new instance is created and immediately discarded.
However its constructor code gets invoked, therefore side-effects (if there are such - and in your example there are - it's printing to stdout) do occur. Doing stuff like this is however a bad practice.
See Zaki's answer about assigning it to variable though. Then you can refer to it, and do stuff.
When you instantiate an object via the new codeword, space on the heap (the part of the system memory used to store objects and their fields) is allocated, and the constructor gets executed. In this case, the constructor writes on the standard output, and this gets executed regardless whether a reference is created to the object or not.
Afterwards, you're right, the object can not be accessed as no references to it exist. Therefore the garbage collector eventually deallocates the memory space.
Just as Adam said, this is generally discouraged though, as it messes up your expectation that a constructor should initialize the object, and interactions with the outside world should be possible via its methods.
So, even if it is a bit longer, better structured code could for example look like this:
class TestCode {
public TestCode() {}
public void welcome() {
System.out.println();
System.out.println("Welcome to the Program");
}
public static void main( String args[] ){
TestCode tc = new TestCode();
tc.welcome();
}
}
P.S. Of course, there are cases where you might want to do operations outside the instance upon every instantiation anyway, for example like keeping a static list of all the instances of the class, and therefore adding the particular instance to it each time it is constructed. Even then though, it is probably best to create a private init() method and invoke it from the constructor, as to better separate elements with different function.
As another example, here is a different, functionally identical way your code could be reformulated:
class TestCode {
public TestCode() {
init();
}
private void init() {
System.out.println();
System.out.println("Welcome to the Program");
}
public static void main( String args[] ){
TestCode tc = new TestCode();
// Or simply: new TestCode();
}
}

Instance var referring to an object

Instance variables go on stack and objects go on heap and object references go on stack. Right? But what if an instance variable was a reference to an object? Like var c:
class clony implements Cloneable {
clony c = new clony();
#Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class tst2 {
public static void main(String[] args) throws CloneNotSupportedException {
clony j1 = new clony();
}
}
And if it goes on heap why it throws and stack overflow error?
Your reference c is a field of the class clony. That means the reference will be stored on the heap inside the memory region that is allocated for the clony object.
And your program throws a stack overflow exception since clony infinitely constructs itself: Inside the constructor of clony you create a new clony object and assign it to field c: Which will then do the same thing again and again.
This is because the stack is also used to keep track of method calls. Every time you call a method (the class's default constructor, in this case), certain information is added to the stack for that purpose. When you have infinite recursion (as you have with your constructor), that fills up the stack PDQ.
I think this:
clony c = new clony();
Gives you the exception.
new clony() also has clony c = new clony()
inside... and it goes to infinity.
By the way, classes should be named with capital letter at the beginning.

What happens when multiple calls are placed using new-operator call to Class() in heap?

When we make calls like below :-
class Class{
int x;
public Class(int a){
x = a;
}
public void display(){
System.out.println(x);
}
}
And in main method, then we use the class' object to display data :-
new Class(5).display(); // object 1
new Class(7).display(); // object 2
Now, my question is :-
Whether what I've represented from object 1 and object 2 will be equal or
distinct(in terms of memory locations in heap)? Whether two separate
memory locations will be created in heap(dynamic memory allocator) OR
whether the same object(memory location in heap) will be used?
I am having this confusion since a long time. Also I am merely a noob in Java.
Please elaborate with respect to the heap section/dynamic memory allocation to Class object using new call.
When you create two objects with new operator they will look for you as different objects in the heap. So if you compare then with == they won't much. However if your code is JIT-compiled, heap allocation will not occur at all as JIT-compiler is smart enough to inline the constructor and display() method and conclude that it can be just rewritten to
System.out.println(5);
System.out.println(7);
But if you actually compare them with ==, then probably this optimization will be turned off and two distinct objects will be allocated on the heap.
It will be Two distict objects in the heap,every time you use the new operator
public class Test {
int x;
public Test(int a){
x = a;
}
public void display(){
System.out.println(x);
}
public static void main(String args[]){
Test firstInstance = new Test(5);
Test secondInstance = new Test(5);
if(firstInstance == secondInstance)
System.out.println("same");
else
{
System.out.println("firstInstance"+firstInstance);
System.out.println("secondInstance"+secondInstance);
}
}
}

An object inside its own class

So let's say:
public class Sample { //main() class
public static void main(String[] args) {
A a = new A();
}
}
public class A {
A aa = new A();
}
So...when I run it ...it gives : java.lang.StackOverflowError.
So, my explanation is that object a generation at line 1, furthers creates object aa generation at line 2...and then it enters a recursion .... which keeps creating object after object, until the heap memory is full.
If the objects are created on Heap...then why does it say StackOverflowError ??
Well, it's using both heap and stack. The stack space is because you're in the constructor for A, recursively. It would be simpler to see this if you put the initialization in the body of the constructor:
public class A {
A aa;
public A() {
aa = new A();
}
}
So the A constructor calls itself, then calls itself, etc. There's generally rather more heap space available than stack space, hence why you're running out of stack space first. If your class had a lot of fields, you would conceivably run out of heap space first - although usually the heap is pretty huge in modern machines.
The reason for a stack overflow is simply that the stack runs out of space before the (small) As can fill up the heap.
You have correctly recognized the recursion. So!

Categories