课程: Java Memory Management: Values and References
Heap vs. stack
- [Instructor] The Stack and the Heap memory are very different. Stack only contains references and primitive values, and Heap contains Objects. While we're talking about accessibility, we can say that Stack can only be accessed on a last and first out base, meaning we can only touch the top of the step, the metadata we're in. Heap is accessible whenever you have the address of the object on Heap. When we consider size and deallocation, the Stack memory is smaller than the Heap, and a memory gets deallocated automatically for the Stack. Whereas the Heap is larger, and the memory needs to be deallocated by the garbage collector. In terms of speed, we can say that it's actually faster to access the Stack memory than it is to access the Heap memory. And lifetime, we can actually say that the Stack has a shorter lifetime typically, than the Heap, because the Heap exists for the time this application runs, whereas the part of the Stack containing the methods, only exist while this method is being executed. Let's go ahead and look at officialization of some code under Stack and Heap memory. Let's first activate Stack memory. So I'm going to say that'll go into some Stack memory stuff here, meaning I'm going to have some primitives going on. So for example an x with value of five, a double y with the value of three, and a boolean b with the value of say false, and a final int xy with the value of three. So this is all purely the Stack memory, but we can actually also have something that's combining both, so this is Stack and Heap. So let's create a person object p, and I've made a person class here, let me show you. So here's the person class, it just has a bunch of properties. That's the name, year of birth, whether or not it loves Java, and it has a Object address. And I've also made an address object containing some entrance properties such as street name, numbers, zip code, city, country. All right, so let's go back to our main and continue creating our Person p, and I'm also going to be creating our Address a, here. So right now, I have some references on the Stack and the actual objects on the Heap. So let's work with the Heap memory for a bit. So what I'm going to do, I'm going to be modifying the actual objects on the Heap memory. So I'm going to be exiting the Heap memory, and in order to do so, I'm going to call the setter methods on our objects. And as you might know, as soon as I call these setters, I'm calling new methods, and when I'm calling new methods, I'm actually adding onsteg memory, but this is so tiny that I'm not going to use it right now, 'cause it won't really show anyway. So here I'm going to say a.setCity, and this will actually make a new string Utrecht, which is my city, on the Heap memory, and it's going to refer from a, to this memory object Utrecht, on the Heap memory. All right, so let's do the same thing for country. I'm from the Netherlands, it should maybe able to hear, and I'm going to say set number, and I'm going to set the number, and then I'm going to set the street name, and of course I'm living in Java Street. And I'm going to be setting like zip code, which is a Dutch zip code, so it has a Dutch format which looks something like this, all right. And right now I have created some elements on my address on the Heap, and it's actually created the bunch of strings, and my object is referring to these other objects from the Heap. So just referring to the references in the block of the address object, and it has created all these new string objects on the Heap. To be honest, these string objects actually contain other objects because these are array of characters, but let's not make it too difficult for right now. Instead, let's also work with our person objects, so I'm going to say set loves Java to all true clearly, all right, and let's set year of birth as well. And let's set a name, let's set my name here too, and I'm going to say Maaike, like this. So right now I have added a bunch of things on the Heap, but what I can actually also do, I can connect our person and our address object, and I can do so by actually setting the address on the person. Let me show you, so I'm going to say p.setAddress, and then I'm going to insert our Object a, that we've created, and right now they are both connected on the Heap because the person is referring to the address of address. Okay, so that's a bit weird. So the reference that p is holding for address is actually the address of our address object on the Heap. Still with me? This is actually most that there is to this whole Stack-Heap kind of thing, so the Stack is connected to the Heap, and as soon as you create a new object, you're creating new objects on the Heap, and you're holding the reference on your Stack or on your other objects on the Heap. And that's all there is to it so to say. So this is a very good fundament for continuing with some more in-depth knowledge in the next chapter. There's actually one more difference of the Heap and the Stack that I would like to show you. And that is the way they are crushing when memory is full. So the Stack is going to be throwing a StackOverflowError, and when the memory on the Heap is full, it's going to throw an OutOfMemoryError. So let me show two code examples that are going to be doing just this and explain you why both are happening. So here we're having an example of a StackOverflow. So why is this going to be causing the StackOverflow? Well, because it's going to be creating new blocks of memory on the Stack every time we call the constructor. Because the constructor is calling itself. So as you can imagine, based on officialization that we have just seen, it would just be adding new blocks on the Stack memory every time it's going to be calling this new ExampleStackOverflowError on line five, and then as soon as it calls it, it's going to call it again and again, it's creating new blocks on the Stack memory until it's full. So let me show you, and I'm going to be running this example. And as you'll see, really soon the memory is full, and is saying, "Exception in thread "main" java.lang.StackOverflowError". And this makes sense because well literally, the Stack memory gets full because too many methods constructors in this case are being added to the Stack. So that's the StackOverflow Error. Let's have a look at the OutOfMemoryError. And in case of the OutOfMemory, we actually want to be creating elements on the Heap. And so many are just going to be crushing. And to be honest this is going to be taking quite a while without JVM tuning, because my memory on my computer is quite big, and by default it starting it with quite some memory. So what I'm doing here, I'm creating a map and I'm going to be running this already because it's going to be running for a long time anyways, and this HashMap, it has a key of type integer and the value of type string, and in the loop, an infinite loop, because it says, "while true", I'm going to be adding random values to our map. So it has a random new key every time, and it has a value so random every time I'm going to be running this. And this going to be speed up a bit so you can see the error really soon. All right, there we have it. So this took a while, but it was speed up for you, so you're just seeing this OutOfMemoryError, and it's saying, "Exception in thread "main" java.lang.OutOfMemoryError". And then it says, "Java heap space". So we know what's going wrong. Clearly we know what's going wrong because well, we are doing something really stupid our map here, but something like this can also happen by accident, and then you'll also get the OutOfMemoryError. Which is not something that your program typically will recover from, but that's a story for another day.