To implement a callback function from the native code to Java code, I have to create a global reference using NewGloabRef . From the memory profile , I found that ,once I called env->NewGlobalRef(weak_this), even it was a weak reference of the player object, the Player object will be available as Root Objects, which I think will prevent it from being garbage collected.
But my understanding is the weak reference won't prevent the object from garbage collected.
//java code
Player{
native_init(new WeakReference(this)),
}
//JNi code
//listener
Listener::Listener(jobject weak_this)
{
//will use mObject for callback
mObject = env->NewGlobalRef(weak_this);
}
xxxx_Player_native_init(xxxx. Object weak_this)
{
Listener l = new Listener(weak_this);
}
EDIT:
memory profile :
Root Object 0x2C820E10 <com/trident/tv/media/player/JniTPlayer>
com/trident/tv/media/player/JniTPlayer.trace : 0x2C83CC54 <java/lang/String>
com/trident/tv/media/player/JniTPlayer.listenerList : 0x2C820E64 <java/util/Vector>
log of JNI
[JNI] NewGlobalRef(0x2C820E10 [com/trident/tv/media/player/JniTPlayer]) : 0x2C820E10
A WeakReference is a Java object with an ordinary reference to it. It contains a reference to another object. It is the contained reference that is "weak", not the reference to the WeakReference itself.
So when you call env->NewGlobalRef(weak_this) (assuming weak_this is a WeakReference), the effect is the same as assigning weak_this to a static. It doesn't cause the object reference contained by the WeakReference to be strongly reachable.
I think you may be misinterpreting what the memory profiler is telling you. In particular, I would expect it to show the contained reference of a WeakReference to be reachable ... up until the GC decided to break the link. Try an experiment with an WeakReference in an ordinary static variable.
UPDATE
I'm starting to think that this is normal behaviour for JNI NewGlobalRef. The JNI documentation is (as always) very vague about the method's behaviour.
Note that there is also a JNI method called NewGlobalWeakRef; see http://java.sun.com/docs/books/jni/html/refs.html#27531. If nothing else, NewGlobalWeakRef provides an alternative way of doing what you are trying to do.
Related
ReferenceQueue q = new ReferenceQueue();
Reference r = q.remove();
r.clear();
I see that the java doc says that the clear method clears this reference object. I don't understand the meaning of this. Does this clear from the memory and thus in other words the object has been garbage collected?
java.lang.Reference is a base class for few special references which are treated in special way by garbage collection.
Under certain circumstances garbage collector may push reference object in it's reference queue (reference may be queued only once in a lifetime).
clear() method can be used to suppress special handling (and thus additional work for garbage collector). If reference object is already in queue it doesn't make sense to clear it, it is already cleared by garbage collector.
This project on github has an implementation of resource management using PhantomReferences made for educational purpose. clear() is used if resource is disposed explicitly to avoid extra work for GC in that case.
clear() simply sets the internal reference to null. Since references are automatically cleared when being enqueued by the garbage collector (with the exception of phantom references, but this oddity can be ignored, it will be eliminated in Java 9), there is usually no need to call clear() on a reference received via ReferenceQueue.remove().
In principle, there is the possibility to enqueue references manually via enqueue() without clearing them, but there is little sense in that, as the primary purpose of the reference queue is to learn about references being enqueued by the garbage collector which will be cleared.
When you call clear() on a Reference object that has not been enqueued yet, it may allow the referent to get collected without enqueuing the Reference object. On the other hand, when you don’t need the Reference object anymore, you can let the JVM collect it like an ordinary object, together with the referent if there are no other references left, as in that case, it won’t get enqueued as well, making clear() unnecessary.
Right now I am working on one java application. In that I am creating lots of method local objects. I am using WeakReference to create those objects in method like below.
public void method() {
while(count < 10000000) {
AnimalBean animal = new WeakReference<AnimalBean>(new AnimalBean()).get();
//----------- HERE MY LOGIC -------------
}
}
I have one doubts, Is it good idea to use WeakReference for local variables ? If NO then why ?
Thanks a lot in advance.
Here is the guide to Understand weak reference
You should think about using one whenever you need a reference to an object, but you don't want that reference to protect the object from the garbage collector. A classic example is a cache that you want to be garbage collected when memory usage gets too high (often implemented with WeakHashMap).
Ref
Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings.
Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.Ref
I create a java object to query data from database. After I get the results and process then I no longer need the object. I also do not set the object reference to null in my code. Will Garbage collector considers this object for clean up? If the Garbage Collector do not clean up will this scenario create any kind of memory leak in the system?
We cannot tell with this much information.
If you have created a local variable, used it, and not done anything else with it, then it will be available for garbage collection as soon as it goes out of scope. If it's a variable within a method, for instance, then once the method returns, its reference is no longer counted as active by the garbage collector. (You could, of course, have another reference to the same object somewhere else).
If, on the other hand, you have an instance variable, then it will hold on to its object as long as that instance of that object is active. And, of course, if you have stored the reference in a static variable, then it is likely to just stay around as long as the program runs.
If I have a class Sample and I have an instance method, instanceMethod in it.
The class has a main method where I create an object of Sample itself and call it's instanceMethod without using a reference variable.
like this:
new Sample().instanceMethod();
inside the main.
Since this object has NO reference, will the garbage collector collect it ?
In Java1, I don't believe the object can be collected while instanceMethod() is being executed. In the main method's stack frame there is a reference to the object, at least logically (the JIT compiler may elide it). The fact that you're not assigning it to a variable doesn't affect the bytecode very much.
Of course when instanceMethod() completes, the object may be eligible for garbage collection - but it may not. For example, instanceMethod() may store a reference to this in a static variable.
Basically it's not worth getting hung up over intricate corner cases - just rely on the GC collecting objects which can't be reached any more in any way, but not collecting objects which may still be in use.
1 In .NET an object can still be garbage collected while an instance method is executing "in" the object, if the JIT compiler can prove that none of its variables will be read again. It's very confusing, and can cause very subtle bugs.
In Java, to unload an object from the heap, is it sufficient to simply write myObject = null; and the GC will take care of it from there?
EDIT : Ok let me explain my use case, since everyone is assuming that I shouldn't explicitly null objects, I shouldn't worry about it, etc. That's missing the point. I am serializing an object, and am "consuming" a field of this object before I serialize it in order to save disk space. And before you jump down my throat for this, too, I cannot declare this field transient because I am including this field in the object sometimes, but not others.
Does setting an object to null have any effect on the GC?
In some modern VMs, actively setting a reference to null hinders the garbage collector. You should just forget about that.
For knowing when an object is garbage collected, look at the java.lang.ref package - although I can honestly say that in 16 years of Java programming, I've never needed to know when an object is garbage collected.
Can you elaborate on why you think you need this?
No; all references to that object must be lost/nulled. In practice this is something you shouldn't worry about.
Your object will be de-allocated when it is no longer used. Just be aware that any references left to the object will keep the object on the heap and simply assigning null to any single reference will not cause the underlying object to magically go away.
No, and no. myObject = null; will only help if there are no other references to the object, and in most cases it's superfluous because local objects go out of scope at the end of each method.
As for when objects are actually deallocated, that's completely up to the GC. What you can do is add a finalize method that will be called just before the object is deallocated, but this is problematic as well and should not be relied on.