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
Related
I have read my question one more time and I think the example was not good enought to show where was my confusion. So I will show a different example.
public class Main {
public static void main(String args[]) {
Foo foo = new Foo();
foo.deleteOtherFoo();
}
}
public class Foo {
private OtherFoo otherFoo;
public Foo() {
otherFoo = new OtherFoo();
}
public void deleteOtherFoo() {
this.otherFoo = null;
}
}
public class OtherFoo {
public OtherFoo() {}
}
If I follow what I know about stack and heap, I can say:
my draw
in the frame deleteOtherFoo what do I have as parameters? because I know I can only have primitive type or reference type value. In that case I have a reference type Foo.otherFoo ? a value that contain a pointer of a pointer ?
Because when I put this.otherFoo = null, I remove the ref of otherFoo from the object foo.
code lives in an entirely different place. Code is effectively unchanging, save some crazy 'reload this class from disk again please' shenanigans (which the JVM does support but that's an entirely different can of worms).
So where does 'the method' live? Well, nowhere. The CODE of the method lives in what used to be called permgen. It's definitely not the stack, never gets garbage collected, and no matter how many Foo objects you make, the code is located in memory only once.
And that's that.. until you call the method.
When you call the method, if it's non-static, it needs 'an instance'. This is, as far as the JVM is concerned, pretty much 100% the same as a parameter: If you call foo.doThingie(a);, then both foo and a are parameters to the doThingie method. These are put on the stack, and then doThingie is executed. Once doThingie finishes execution, the stack is reset to the point before doThingie was invoked, so, 'foo' and 'a' are now gone.
In java, all non-primitives are 'references' which is just javaspeak for 'pointers'. So when I say 'foo and a are on the stack', what I really mean is 'a pointer, into the heap, pointing at the data (i.e., the fields) that represent an instance of Foo, is on the stack'.
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);
}
}
}
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!
Lets says I have the code in the entity class:
this.setCurrentState(new NormalState(this));
if in the normal state class I switch the state of the entity to:
entity.setCurrentState(new HungryState(entity));
will the NormalState object be garbage collected event though it holds a reference to the entity that is still active or will it not cause memory leaks?
Java's garbage collector removes all objects who don't have any references to them. If calling the setCurrentState method replaces the stored reference to the instance of NormalState and there isn't another reference to that object in the whole VM, then it's marked as garbage and thus, it'll be collected.
The garbage collector removes all objects not being used; if your NormalState is not held in a variable, nor being used by code, it will be garbage collected. The Entity will also be garbage collected if NormalState was the only object containing a reference to it.
For example, given two classes, A and B, where A contains a B as so:
public class A {
B inner = new B();
public A(B in) {
inner = in;
}
}
myB will be garbage collected (When our A is collected) in the following example:
public static void main(String[] args) {
B myB;
//setting a value with = returns the value
//myB = new B() -> myB
A firstObject = new A(myB = new B())
//bad coding practice, but the fastest way to clear variables
firstObject = null;
myB = null;
}
However, the following will not garbage collect myB because there's still a reference:
public static void main(String[] args) {
B myB;
A firstObject = new A(myB = new B())
A secondObject = new A(myB);
//clear references. secondObject still has a reference to what was myB.
//the now unnamed B will not be collected until secondObject changes.
firstObject = null;
myB = null;
}
NOTE: It's very annoying trying to name an object; as long as it has a variable, it's easy to say myB, but even after your stop calling it myB, it's still there in the computer. I don't know what to call it because I stopped calling it myB when I did myB = null;.
This question is for the java language in particular. I understand that there is a static protion of memory set aside for all static code.
My question is how is this static memory filled? Is a static object put into static memory at import, or at first reference? Also, do the same garbage collection rules apply to static objects as they do for all other objects?
public class Example{
public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;
public class MainApp{
public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
Example.someO.someMethod();
// Do the same garbage collection rules apply to a
// static object as they do all others?
Example.someO = null;
System.gc();
}
}
Imports don't correlate with any instructions in compiled code. They establish aliases for use at compile time only.
There are some reflective methods that allow the class to be loaded but not yet initialized, but in most cases, you can assume that whenever a class is referenced, it has been initialized.
Static member initializers and static blocks are executed as if they were all one static initializer block in source code order.
An object referenced through a static member variable is strongly referenced until the class is unloaded. A normal ClassLoader never unloads a class, but those used by application servers do under the right conditions. However, it's a tricky area and has been the source of many hard-to-diagnose memory leaks—yet another reason not to use global variables.
As a (tangential) bonus, here's a tricky question to consider:
public class Foo {
private static Foo instance = new Foo();
private static final int DELTA = 6;
private static int BASE = 7;
private int x;
private Foo() {
x = BASE + DELTA;
}
public static void main(String... argv) {
System.out.println(Foo.instance.x);
}
}
What will this code print? Try it, and you'll see that it prints "6". There are a few things at work here, and one is the order of static initialization. The code is executed as if it were written like this:
public class Foo {
private static Foo instance;
private static final int DELTA = 6;
private static int BASE;
static {
instance = null;
BASE = 0;
instance = new Foo(); /* BASE is 0 when instance.x is computed. */
BASE = 7;
}
private int x;
private Foo() {
x = BASE + 6; /* "6" is inlined, because it's a constant. */
}
}
There is normally no such thing as "static" memory. Most vm's have the permanent generation of the heap (where classes get loaded), which is normally not garbage collected.
Static objects are allocated just like any other object. But, if they live for long they will be moved between the different generations in the garbage collector. But they will not end up in permgenspace.
If your class is holding onto this object permanently, it will only be released when the vm exits.
This static variable some0 is initialized as soon as your class is referenced in your code. In your example this will be executed in first line of your main method.
You can validate this by creating a static initializer block. Put a break point in this initializer block and you'll see, when it will be called. Or even more simplier... put a breakpoint in the constructor of SomeObject.
The initialization of static variables is covered in Section 2.11 Static Initializers of suns JVM spec. The specification does not define the implementation of Garbage collection however so I imagine that garbage collection rules for static objects will vary depending on your VM.
It should be noted, that only the pointer (or any other primitive type) is stored in the PermGenSpace (thats the proper name for the area where the static stuff is stored).
So the Object referenced by the pointer sits in the normal heap, like any other object.
If the static field is changed to reference a different object, the original object pointed to by the static field is eligible for GC just like any other object.
It could also be free'ed (even if not nulled) if the class itself is unloaded and the entire object graph is cut from the heap. Of course, when a class can be unloaded is a good topic for a host of other questions... :)