While reading on Thread Safety I came across this issue.
If I'm correct method local Primitives and object references lives inside a stack and actual objects pointed by the references inside the stack lives in the heap.
But when it comes to method local non primitive object initialization, wouldn't that cause a concurrency issue ? I mean if the method locals non primitives lives in the heap and only the pointers lives in the stacks, isn't it the same as of instance variables ?
Can someone please help me to understand this....
PS
Think of two threads with each having two stacks of their own and one heap. What I understood is that the two threads keep their method local primitive variables inside their stacks. I have no issue with that.
But what if we have a method with non primitive method local variables ? Then if the object for that variable is stored inside the heap, both the threads will have the access to the same object, won't they ? So if that's the case there would be Sync problems.
That is what I'm asking.
Thanks
But what if we have a method with non primitive method local variables
? Then if the object for that variable is stored inside the heap, both
the threads will have the access to the same object, won't they ? So
if that's the case there would be Sync problems.
I wonder why you will think the two references will refer to the same object.
The creation of the object referred is explicitly done by new (or other similar method, but idea is the same)
Therefore, unlike in C++, if you are declaring this in Java
Foo foo;
there is no Foo object instantiated. foo is just a pointer pointing to nothing.
This will create you a Foo object instance in heap.
Foo foo = new Foo();
If two thread is running this piece of code, thread 1 will have a Foo reference in stack, and ask to allocate a new Foo object in heap, and then assign the address of that Foo obj to the reference foo. Thread 2 is doing the same. Note that Thread 2 is also asking to allocate a new Foo object, it will be a different object from what Thread 1 is allocated.
That's the basic (and much simplified) idea.
Both threads could have access to the same object if they both have a reference to the object. If you have a method like the following:
public String concat(String a, String b) {
StringBuilder builder = new StringBuilder();
builder.append(a);
builder.append(b);
return builder.toString();
}
The StringBuilder object is indeed in the heap, but only one thread has a reference to this object. No other thread can have a reference to this StringBuilder. So it's inherently thread-safe.
If, on the contrary, you have the following:
public String concat(String a, String b) {
final StringBuilder builder = new StringBuilder();
new Thread(new Runnable() {
#Override
public void run() {
builder.append("haha!");
}
}).start();
builder.append(a);
builder.append(b);
return builder.toString();
}
Then you have a thread-safety issue, because you shere the locally created object reference with another thread, and StringBuilder is not thread-safe.
But what if we have a method with non primitive method local variables ? Then if the object for that variable is stored inside the heap, both the threads will have the access to the same object, won't they ? So if that's the case there would be Sync problems
You partially answered your own question.That reference value is stored in the stack but the actual object content is stored in heap and when you call new Object() each thread creates different new object that will be stored in the heap and each thread access the object it has created using the reference value stored in its own stack
Local variables are either primitives, references to objects created somewhere else (if you do an assignation), or references to newly created objects (using "new" operator)
For the first case, as you said, there is no issue.
For the last case, as you are locally craeting a new object, a new object will be created at every call, so no concurrency issue because there will be one object in the heap for each call
But for the second case, as the object has been created somewhere else, you have to think about concurrency
Just to toss in my thoughts regarding what may be your point of confusion: the heap is not managed like the stack. It is shared, yes - in that objects created by all threads are in the heap. However as each object is created, it's given a unique location/space in the heap. Two methods on two threads running concurrently and creating an object instance will create distinctly different objects in the shared heap.
They're created in this shared heap so that if method foo returns the object reference, or stores it, or calls another method that indirectly stores it... it won't be destroyed when foo returns and the stack is popped.
The magic of having a garbage collector is that you don't have to keep track of this "stuff" and destroy it yourself at some appropriate point in the future. Keeps your code simple, lets you focus on algorithms (or learning to program). But I digress...
Related
Coming from C/C++, I am a little confused about volatile object behavior in Java.
I understand that volatile in Java has two properties:
Won't bring object into cache, always keep it in main memory.
Guarantee "happen-before"
However I am not sure what happens if I make a new non-volatile reference to object. For example,
class Example {
private volatile Book b = null;
public init() { b = new Book(...); }
public use() {
Book local = b;
local.read();
}
}
AFAIK, volatile means the "book object" that b is referencing to should be in main memory. Compiler probably implement reference as pointer internally, so the b pointer probably sit in cache. And to my understanding, volatile is a qualifier for object, not for reference/pointer.
The question is: in the use method, the local reference is not volatile. Would this "local" reference bring the underlying Book object from main memory into cache, essentially making the object not "volatile"?
There is no such thing as a “volatile object” nor “always keep it in main memory” guarantees.
All that volatile variables of a reference type guaranty, is that there will be a happens-before relationship between a write to that variable and a subsequent read of the same variable.
Since happens-before relationships are transitive, they work for your example code, i.e. for b = new Book(...) all modifications made to the Book instance are committed before the reference is written to b and hence for Book local = b; local.read(); the read() is guaranteed to see all these modification made by the other thread before writing the reference.
This does not imply that the Book instance’s memory was special. E.g. modifications made to the instance after the reference has been written to b may or may not be visible to other threads and other threads may perceive only some of them or see them as if being made in a different order.
So it doesn’t matter which way you get the reference to the object, all that matters is whether the changes are made before or after publishing a reference to that object through b. Likewise, it doesn’t matter how you perform the read access to the object, as long as you do it after having acquired the reference by reading b.
With local.read(); you are accessing the object via the local variable local and within read(), the same reference will be accessed though this, but all that matters is that you have acquired the reference by reading b before reading the object’s state.
volatile is about the reference, not the object.
It guarantees that any thread reading the variable b after another thread has set the value of b will get the value assigned to b by the other thread, and not some cached value.
when does instance variable of a static method gets memory in java?
it is perfectly right to create instance variable in static method (either in parameter or declaring inside the function), but i want to know when does the instance variable of static method is allocated memory, if no object of the class is created?
Actually i meant to say the local variable inside static method
Firstly, the term instance variable is not accurate, I am assuming that you are asking about local variable such as a and b in the example below:
void method(int a) {
int b = 3;
}
In Java, only primitives and references are stored on stack, objects are stored in heap when they are constructed. Stack will be cleaned as soon as the scope ends, heap is cleaned by garbage collector.
Here is an example:
public class Main {
static A a = new A();
static void method() {
int b = 2;
C c = new C();
}
}
The first time your code refers to Main, class loader will load the class and initialize all its static fields - object new A() will go into heap. Nothing more happens here, method method could as well not exist.
When you call method method, it will add value 2 on the stack, then it will add reference c on the stack which will be pointing to the object new C() in the heap.
When method exists, 2 and c are removed from the stack (there is actually no removal, but the top of the stack is changed to two positions below so these two values will be overriden whenever something else comes onto stack), while new C() will remain in heap until garbage collector triggers. It's likely that it will be garbage collected immediately as GC may detect that there are no more references to this object.
If you declare a variable or use parameter inside a static method, its not at all instance variable. Its a local variable and it will be initialized once the method gets invoked
static void methodTest(int i) {
String s = "Hello";
}
Here s is a local variable to that method.
and i is the function parameter which is also a local variable to the method
There is not such thing as an instance variable in a static method.
If you mean parameters and local variables, those are allocated on stack (any created objects being allocated on heap as usual).
Static fields of the class will be initialized when the class is loaded.
Instance variables of a class will be allocated (and possibly initialized) when an instance is constructed.
The variable defined by static method is still local variable in scope of the method, just as if non-static method created local variable. However, problem is that the variable never gets garbage collected, as long as the class loader (usually main class, which gets "unloaded" only at runtime termination, which is like scratching your left ear with your right hand) is not unloaded and garbage collected. And objects get GC'd only if they are not referenced anymore, and in case of static fields, they have tendency to be referenced even when nothing uses them because of the behavior I described. So in large applications, where memory and resources are issue, it is pretty bad idea to declare anything inside static methods since you pretty soon pollute the memory with LOCAL VARIABLES that cannot be collected.
I know that when declaring object instances in c++ like so:
Object object
the Object constructor is called and memory is provided for that object, however i find that when you do this in java the object instance doesn't have a value until:
object = new Object()
is written. I want to know specifically when memory is provided for the object. I thought that both construction and the new keyword allocated memory so Object object = new Object() seems redundant. I read on oracle's site that declaration "reserves" memory and new "allocates" memory, I would like to know what is the difference between the two.
You need to differentiate between the space required for the variable and the space required for the object. Bear in mind that the value of the variable is just a reference - very much like a pointer in C++. So if you have:
Object x = null;
then the variable x itself takes up enough space for a reference (usually 4 or 8 bytes). Now if you have:
x = new Object();
that creates an object - the value of x is now a reference to the newly created object. x itself takes up the same amount of space as before, but there's also the space required for the object itself (basically the fields, a reference for the type of the object, and data for synchronization and house-keeping).
When you do something like
Object object = new Object()
in Java, object is a reference to the actual instance on the managed heap. Compared to C++, that's roughly doing
Object* object=new Object()
So when you do
Object object;
in Java, a place is created for the 'reference' to a instance.
Similar to
Object* object;
in C++.
Object foo=null;
in meaning of C++ creates reference foo to the object of class Object. So, it consumes memory for reference only.
Object realFoo=new Object();
creates such reference and also real object with whatever is with this object. So, it is memory for the reference and object itself.
In Java there is no memory reservation - only memory allocation.
declaration reserves memory: parameters and variables inside a method will have memory reserved for them in the stackframe.
allocates memory: at runtime, when executing "new", memory will be allocated for the new Object on the heap
It's important to understand that in Java, Object object is simply a reference to an Object called object. If you're familiar with C++, you can think of this reference as a pointer (though it's not quite the same).
On a 64-bit machine, the object reference is 8 bytes. When you actually instantiate an Object using the new keyword and assign it to the reference, this is where memory is allocated for your Object.
In the code below, given that amethod has been called. At what point/line is the Object originally referenced by myObject, eligible for Garbage Collection?
class Test {
private Object classObject;
public void amethod() {
Object myObject = new Object();
classObject = myObject;
myObject = null;
}
}
And if classObject or amethod had an access modifier of public, protected, default or static, would it affect what point the Object is eligible for Garbage Collection? If so, how would it be affected?
My first thought is that the Object is eligible for Garbage Collection when the Test object is eligible for Garbage Collection.
But then again. The optimizer may know that the classObject is never read from in which case classObject = myObject; would be optimized out and myObject = null; is the point it is eligible for Garbage Collection.
The object will not become a candidate for garbage collection until all references to it are discarded. Java objects are assigned by reference so when you had
classObject = myObject;
You assigned another reference to the same object on the heap. So this line
myObject = null;
Only gets rid of one reference. To make myObject a candidate for garbage collection, you have to have
classObject = null;
From Book OCA Java SE 7
An object is marked as eligible to be garbage collected when it
can no longer be accessed, which can happen when the object goes out
of scope. It can also happen when an object’s reference variable is
assigned an explicit null value or is reinitialized.
This is actually addressed precisely by the Java Language Specification, §12.6.1, Implementing Finalization :
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage. …
But
… Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
For example, consider the Finalizer Guardian pattern:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
The finalizer guardian forces super.finalize to be called if a subclass overrides finalize and does not explicitly call super.finalize.
If these optimizations are allowed for references that are stored on the heap, then a Java compiler can detect that the finalizerGuardian field is never read, null it out, collect the object immediately, and call the finalizer early. This runs counter to the intent: the programmer probably wanted to call the Foo finalizer when the Foo instance became unreachable. This sort of transformation is therefore not legal: the inner class object should be reachable for as long as the outer class object is reachable.
This example can be applied 1:1 to your example, as long as the object is referenced by the instance field classObject, it can not get garbage collected earlier than the Test instance containing the reference.
Note, however, that the aggressive optimizations mentioned in the specification are still allowed, when being applied to the code using the Test instance. The earlier-than-expected collection may happen, as long as both, the Test instance and the referenced object are collected together. In this case, the following aspect specified in §12.6 applies:
The Java programming language imposes no ordering on finalize method calls. Finalizers may be called in any order, or even concurrently.
So it’s perfectly possible that the Test instance is collected earlier than the object referenced by classObject whereas the “inner” object’s finalizer is invoked earlier. The only thing that is guaranteed, is, that when the inner object’s finalizer runs, the outer object is unreachable (or has a pending or concurrent finalization). Since in your example, neither has a non-trivial finalizer, that doesn’t matter anyway…
Your idea that the private object may be GC'd right away because no other code is able to access it does have some traction, but this would mess with the general semantics of Java memory management. For example, if that object implemented finalize, and Java semantics clearly dictates when an object is eligible for garbage collection, that finalizer method would be have to be called against the specification.
Also note that the object in turn may reference other objects, with even more complicated possible outcomes. Not to mention the object is reachable by Reflection anytime and it would make no sense for the field to be observed to suddenly change to null even if no code could have made that assignment.
To conclude, there are many reasons why your idea of optimization would not work in the wider picture.
No object is eligible for garbage collection here because you are creating two reference for the same object and you are giving null to only one reference but other reference is still pointing your object
Since you are holding myObject in classObject(reference is maintained), it(object in memory referenced through classObject) will not be available for Garbage collection until instance of Test is freed up/unloaded.
In the code below, given that amethod has been called. At what point/line is the Object originally referenced by myObject, eligible for Garbage Collection?
Your question is nonsensical because there is a disconnect between your high-level source code and the low-level representation (global roots in registers, on the stack and in global variables) that the garbage collector sees.
Your phrase "eligible for garbage collection" presumably means at what point does a heap-allocated block of memory become unreachable. So your question can only be answered by making a lot of (dubious) assumptions about what heap allocates and how long the generated code will keep references.
In java, when you pass an object to a method as a parameter, it is actually passing a reference, or a pointer, to that object because objects in Java are references.
Inside the function, it has a pointer to that object which is a location in memory. I am wondering where this pointer lives in memory? Is a new memory location created once inside the function to hold this reference?
Within a function, a parameter reference is stored on the stack. The thing-referenced can live anywhere.
When some code calls a method, what normally happens is that space is made on the executing thread's stack, and this space is used to hold the parameters that are passed to the function. If one of the parameters "is an object", what's really in play is a reference to an object; that reference is copied onto the stack so that the called code can find it. It's important to recognize that the object itself is not copied, just the reference.
The prologue section of the called code will then typically allocate more space on the stack, for the method's own local variables, but underneath, the JVM has a pointer to the stack frame with all the parameters, so the called code can locate the object named by the parameter. Items created with 'new' will be allocated from the heap, and can persist even after the method exits, but all items allocated on the stack are dumped simply by moving the stack pointer back to where it was before the call.
Objects are not references, but you use references everywhere. e.g.
String a = "abc";
the a is a reference to a String. So references get passed around everywhere. Are they pointers ? No. A reference is more like a handle to an object. The JVM is at liberty to move around objects within memory. A pointer would have to change to reflect this. A reference doesn't. A reference could be modelled as a pointer to a pointer.
Every parameter of the function is passed by value - however, the parameter is not an object, but instead is a reference.
So the same object exists with two references to it.
String s = "my string"; // reference to this object created
doSomething(s); // in the doSomething function, a new reference to the same point of memory is passed by value
This means when I have my function void doSomething(String str) I work the same way as I do outside the function, except I have a different reference. Same object being referenced, but different reference. So if inside my function I do str = "different string"; that won't change s - s still points to the same point of memory it did the whole time - but now str instead of pointing to what s points to, now points to where the "different string" is stored.
for example in JFrame you can start like this:
public myFrame mF;
public void Panel1(myFrame mF) { your code ... }