I'm saving the previous value of a Java object. I (almost) understand references are strong, weak, etc. but I can't find an example that classifies my specific situation that is apparently referencing an out-of-scope object. (I've looked at a lot of posts on this subject.)
Is the Java reference aTestCopy to the out-of-scope array of objects aTest valid?
It's a shallow copy but is it subject to garbage collection thus I need a deep copy for it to work reliably every time? Or should the declaration of the new object aTest be placed outside the while with the "previous" copied object aTestCopy?
Is the use of a null a good practice for the first-time-through switch or should that be a separate boolean variable?
Thanks.
Tester[] aTestCopy = null;
while(true)
{
Tester[] aTest = myMethodReturnsATesterArray(); // new values
// need code to skip using aTestCopy the first time through - no previous value
// else use the previous value here
aTestCopy = aTest; // save them for the next use of previous values
}
There is no problem to use null as initial value for reference types in Java. But there isn't any relevance between initialize a reference type as null and garbage collection. You should initialize aTestCopy as null to use in another scope like in your case in while.
Garbage collection is triggered whenever an object in memory is not pointed anymore by any reference.
When you assign a reference type to another reference type (if it is not immutable in this case), you made copy the memory address of that value. So when you can make a change in aTestCopy will be reflected to the reference aTest.
In Java, variables do not hold objects, only references to objects.
The lifetime of objects is largely independent of the lifetime of variables: Objects are created by executing new, and reclaimed once the program has relinquished all means of accessing them (i.e. the object is no longer reachable form the references the program holds).
Put differently, the first variable to hold a reference to an object holds no special significance. In particular, it does not determine the lifetime of that object. Any reference will keep the object alive, and there can be no such thing as an "out of scope" object.
Similarly, when you assign a variable of reference type, you are only assigning the reference, causing both variables to point to the same object, and to see any changes done to this object though the other variable.
If you want a new object, you must use new (or call a method that uses new).
In your case, I'd make sure that myMethodReturnsATesterArray returns a new array, referencing new Tester objects. Then, the objects created by separate iterations of the loop will exist independently, allowing the loop to reference both the old and new objects and do whichever comparision it deems appropriate, without having to fear that the invocation of myMethodReturnsATesterArray has somehow changed the previous object.
Related
This question already has answers here:
Where does class, object, reference variable get stored in Java. In heap or in stack? Where is heap or stack located?
(8 answers)
Closed 4 years ago.
This question is regarding Java, and how Objects are created, passed, and "deleted".
From what I know, when you want to create an object, you use the "new" keyword. From my understanding, this operator (new) allocates memory for the object, and the = operator assigns the reference to the location of this object in memory, to the variable name you give it.
For example, let's say you create an array in Java like so.
int[] arrayX = new int[size];
the = operator now stores the reference to the array in memory to the variable name arrayX.
This is all fine.
Now let's think about methods (functions).
Firstly, from my understanding, when you call a method, memory is allocated on the stack for this method's variables and processes, and when the method returns, it's instance on the stack is closed/deleted/put in garbage. However, this doesn't explain how you can return objects (such as arrays) which were created in the method back to the caller's scope using the return keyword.
From what I understand, since the method is returning, the data in its stack is going to be deleted. Therefore, the array that was created within this method's scope, will also be deleted. So the reference returned to the array's location, will point to "garbage" values. However, this is clearly not the case. In Java, if you return an Object, you can keep using it.
This makes me confused about how Objects are created, stored and returned...
are objects created always stored in permanent memory? or
does the return operator move the array or object from the method's temporary stack to the caller's stack?
if the second case is true, then are objects created within methods deleted after the method returns to the caller (but does not return the object)? In this third case, it would mean that one shouldn't worry about creating objects in methods, as those objects will be deleted. Thus, if a program was to call a method 1000 times, we shouldn't worry about the memory filling up with objects that we only use once.
I have looked through courses offered on edX on Java and even read a book (although not finished) and still haven't found an answer to this so I would appreciate your input (if you know).
EDIT: Please note, this questions asks 3 separate things:
1. Where are Objects and primitives stored
2. what does the new operator do specifically
3. what does the return operator do
However, this doesn't explain how you can return objects (such as arrays) which were created in the method back to the caller's scope using the return keyword
The reason you can do it is that the object is not created on the stack; only the reference to it is. The array stays in the dynamically allocated memory until it becomes eligible for garbage collection. When you assign the result returned from a method to another variable or to a field, the value of the reference is preserved, so the object stays in memory.
does the return operator move the array or object from the method's temporary stack to the caller's stack?
Only the value of the reference gets copied. The reference is a relatively small object, whose size depends only on the system on which JVM is running. In particular, the size of the reference does not change with the size of the object being referenced, so the amount of required copying is limited.
One important point to note is that if you return an object in a method and don't save it, it does in fact get garbage collected. For example if you have:
public int somemethod(){
int myint = 9;
return myint;
}
And then call someMethod() in your main method, in order to access this return for the future you have to store it.
public static void main(String [] args){
this.someMethod(); //can't access myInt.
int savedInt = someMethod(); // Saves the value 9 for future access.
}
So in general when you call a method and then the return type is present before that method gets removed from the stack, but in order to use it in the future you must store the value in a variable that will still be present.
I was browsing some old books and found a copy of "Practical Java" by Peter Hagger. In the performance section, there is a recommendation to set object references to null when no longer needed.
In Java, does setting object references to null improve performance or garbage collection efficiency? If so, in what cases is this an issue? Container classes? Object composition? Anonymous inner classes?
I see this in code pretty often. Is this now obsolete programming advice or is it still useful?
It depends a bit on when you were thinking of nulling the reference.
If you have an object chain A->B->C, then once A is not reachable, A, B and C will all be eligible for garbage collection (assuming nothing else is referring to either B or C). There's no need, and never has been any need, to explicitly set references A->B or B->C to null, for example.
Apart from that, most of the time the issue doesn't really arise, because in reality you're dealing with objects in collections. You should generally always be thinking of removing objects from lists, maps etc by calling the appropiate remove() method.
The case where there used to be some advice to set references to null was specifically in a long scope where a memory-intensive object ceased to be used partway through the scope. For example:
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; <-- explicitly set to null
doSomethingElse();
}
The rationale here was that because obj is still in scope, then without the explicit nulling of the reference, it does not become garbage collectable until after the doSomethingElse() method completes. And this is the advice that probably no longer holds on modern JVMs: it turns out that the JIT compiler can work out at what point a given local object reference is no longer used.
No, it's not obsolete advice. Dangling references are still a problem, especially if you're, say, implementing an expandable array container (ArrayList or the like) using a pre-allocated array. Elements beyond the "logical" size of the list should be nulled out, or else they won't be freed.
See Effective Java 2nd ed, Item 6: Eliminate Obsolete Object References.
Instance fields, array elements
If there is a reference to an object, it cannot be garbage collected. Especially if that object (and the whole graph behind it) is big, there is only one reference that is stopping garbage collection, and that reference is not really needed anymore, that is an unfortunate situation.
Pathological cases are the object that retains an unnessary instance to the whole XML DOM tree that was used to configure it, the MBean that was not unregistered, or the single reference to an object from an undeployed web application that prevents a whole classloader from being unloaded.
So unless you are sure that the object that holds the reference itself will be garbage collected anyway (or even then), you should null out everything that you no longer need.
Scoped variables:
If you are considering setting a local variable to null before the end of its scope , so that it can be reclaimed by the garbage collector and to mark it as "unusable from now on", you should consider putting it in a more limited scope instead.
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; // <-- explicitly set to null
doSomethingElse();
}
becomes
{
{
BigObject obj = ...
doSomethingWith(obj);
} // <-- obj goes out of scope
doSomethingElse();
}
Long, flat scopes are generally bad for legibility of the code, too. Introducing private methods to break things up just for that purpose is not unheard of, too.
In memory restrictive environments (e.g. cellphones) this can be useful. By setting null, the objetc don't need to wait the variable to get out of scope to be gc'd.
For the everyday programming, however, this shouldn't be the rule, except in special cases like the one Chris Jester-Young cited.
Firstly, It does not mean anything that you are setting a object to null. I explain it below:
List list1 = new ArrayList();
List list2 = list1;
In above code segment we are creating the object reference variable name list1 of ArrayList object that is stored in the memory. So list1 is referring that object and it nothing more than a variable. And in the second line of code we are copying the reference of list1 to list2. So now going back to your question if I do:
list1 = null;
that means list1 is no longer referring any object that is stored in the memory so list2 will also having nothing to refer. So if you check the size of list2:
list2.size(); //it gives you 0
So here the concept of garbage collector arrives which says «you nothing to worry about freeing the memory that is hold by the object, I will do that when I find that it will no longer used in program and JVM will manage me.»
I hope it clear the concept.
One of the reasons to do so is to eliminate obsolete object references.
You can read the text here.
I'm trying to perform a small memory optimisation for my Java game. It is a bit unclear to me how does Java allocate memory when it comes to fields:
public class Test {
private HashMap<String, String> info;
public Test(boolean createInfo) {
if (createInfo) {
info = new HashMap<String, String>();
}
}
}
As you can observe, the HashMap info is initialised if you pass true to Test's constructor.
Does new Test(true) take up more memory than new Test(false)?
Which leads to the more general question:
When you create a field in a class, does Java "reserve" the necessary memory for such field in case it is initialised, or will it do nothing until you actually initialise it?
There is this question: Is memory allocated for unused fields in Java? which seems to be almost exactly what I am looking for, but they seem to be asking what already instantiated fields that are unused, whereas I am asking for uninstantiated fields that may or may not be used.
Does new Test(true) take up more memory than new Test(false)?
Yes.
When you create a field in a class, does Java "reserve" the necessary memory for such field in case it is initialised, or will it do nothing until you actually initialise it?
There are two things here - the HashMap reference, and the HashMap object. Both of them require memory. When a class instance is created, memory is allocated for all its instance variable. In case of int type field, it will allocate 4 bytes, similarly for a reference, it will allocate some memory for that reference (I don't know exactly how much it is). But surely it will allocate memory for the fields.
Then when you initialize the fields in the constructor, the actual HashMap object is created, which will again take up memory to store the object.
The field itself has space for a reference to an object, and that space is allocated when the containing class (Test) is instantiated, even if the value placed in that field is null. Your example code doesn't create an extra object whose reference will go in that field when you pass in false.
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
public class App1
{
public static void main(String[] args)
{
Point point_1 = new Point(5,5);
Point point_2 = new Point(7,8);
Circle circle_1 = new Circle(point_2, 10);
point_1 = null;
point_2 = null;
}
}
How many object references exist after this code has executed? Why?
After this code has executed, exactly none, since it will have exited :-)
If you mean at the point just before exit, there's a reference on the stack to your circle and a reference in your circle to the second point, assuming the constructor stores it.
Despite formulation problems, the snippet is actually quite instructive on certain aspects of garbage collectibility. Let's take a look at it line-by-line.
Point point_1 = new Point(5,5);
So we've declared a reference variable point_1, and it points to a new Point. Let's assume for now that the constructor of Point doesn't do anything fancy and simply set fields final int x, y with the given values.
Thus, we now have something like this:
Now let's take a look at the next line:
Point point_2 = new Point(7,8);
Now we have something like this:
Now let's take a look at the next line:
Circle circle_1 = new Circle(point_2, 10);
Here again we don't quite know how Circle is implemented, but it's reasonable to assume that it has a final Point center and final int radius fields, and with the Point center specifically, it simply sets the reference to the given Point (i.e. no defensive copying since Point is immutable).
So now we may have something like this:
Then with the next two statements, we set point_1 and point_2 to point to null respectively:
point_1 = null;
point_2 = null;
So now we have something like this:
We can now observe that:
The object [aPoint(5 5)] is no longer reachable
The object [aPoint(7 8)], though no longer refered to by point_2, is still refered to by [aCircle(10)].center.
Garbage collectibility is defined by whether or not an object is reachable by a live reference. The object [aPoint(5 5)], we can strongly assume (based on how we think Point is implemented), is no longer reachable, so it is eligible for collection (it's a garbage! No one can "pick it up" now!).
On the other hand, the object [aPoint(7, 8)] is still referred to by [aCircle(10)].center, so we can say that it's NOT eligible for collection (it's not a garbage! Someone is still "hanging on" to it!).
Moral
So no, definitely setting a reference to null does NOT make the object previously being referred to automatically eligible for collection. It depends on the object itself, whether or not there are any references to the object.
Certainly, though, setting a reference to null CAN help make an object be eligible for collection, e.g. when that reference is the last remaining to the object.
You do NOT however, have to ALWAYS set a reference to null to make garbage collection "works". When variables goes out of scope, the reference is no longer alive, so in those kinds of cases explicitly setting to null is simply redundant code.
The classic example when explicitly setting to null DOES work is the Stack example: when the top element is popped from the Stack, the Stack should no longer refer to the object from its internal data structure.
See also
Effective Java 2nd Edition, Item 6: Eliminate obsolete object references
Related questions
Does variable = null set it for garbage collection
The answer is:
Define what you mean for an object reference to "exist".
It is impossible to know how many object references were even created, without details of the Point and Circle classes.
The answer is irrelevant, because after the main method exits none of the objects will be reachable ... whether or not the references still "exist".
We might infer that at the point in time immediately before the main method returns there will be one reachable reference to a Circle object and one reachable reference to a Point. But one has to make some (reasonable) assumptions about how those two classes are implemented to make that inference. (For example, one has to assume that the respective constructors don't add the Point and Circle reference to some static data structure.)
Are objects cleaned up when references to them are nulled?
No. Objects are cleaned up when the garbage collector runs, and it determines that the objects in question are no longer reachable. In this sense, "reachable" means that you can get to the object by following a chain of references to the object starting from:
a static attribute of some class
a local variable of some method that is currently being executed by some thread
an attribute of some other reachable object, or
an element of some other reachable array.
(I've simplified the explanations of GC and reachability a bit to avoid confusing the OP with things he/she won't understand yet.)