I'm slowly working through Bruce Eckel's Thinking in Java 4th edition, and the following problem has me stumped:
Create a class with a finalize( ) method that prints a message. In main( ), create an object of your class. Modify the previous exercise so that your finalize( ) will always be called.
This is what I have coded:
public class Horse {
boolean inStable;
Horse(boolean in){
inStable = in;
}
public void finalize(){
if (!inStable) System.out.print("Error: A horse is out of its stable!");
}
}
public class MainWindow {
public static void main(String[] args) {
Horse h = new Horse(false);
h = new Horse(true);
System.gc();
}
}
It creates a new Horse object with the boolean inStable set to false. Now, in the finalize() method, it checks to see if inStable is false. If it is, it prints a message.
Unfortunately, no message is printed. Since the condition evaluates to true, my guess is that finalize() is not being called in the first place. I have run the program numerous times, and have seen the error message print only a couple of times. I was under the impression that when System.gc() is called, the garbage collector will collect any objects that aren't referenced.
Googling a correct answer gave me this link, which gives much more detailed, complicated code. It uses methods I haven't seen before, such as System.runFinalization(), Runtime.getRuntime(), and System.runFinalizersOnExit().
Is anybody able to give me a better understanding of how finalize() works and how to force it to run, or walk me through what is being done in the solution code?
When the garbage collector finds an object that is eligible for collection but has a finalizer it does not deallocate it immediately. The garbage collector tries to complete as quickly as possible, so it just adds the object to a list of objects with pending finalizers. The finalizer is called later on a separate thread.
You can tell the system to try to run pending finalizers immediately by calling the method System.runFinalization after a garbage collection.
But if you want to force the finalizer to run, you have to call it yourself. The garbage collector does not guarantee that any objects will be collected or that the finalizers will be called. It only makes a "best effort". However it is rare that you would ever need to force a finalizer to run in real code.
Outside of toy scenarios, it's generally not possible to ensure that a finalize will always be called on objects to which no "meaningful" references exist, because the garbage collector has no way of knowing which references are "meaningful". For example, an ArrayList-like object might have a "clear" method which sets its count to zero, and makes all elements within the backing array eligible to be overwritten by future Add calls, but doesn't actually clear the elements in that backing array. If the object has an array of size 50, and its Count is 23, then there may be no execution path by which code could ever examine the references stored in the last 27 slots of the array, but there would be no way for the garbage-collector to know that. Consequently, the garbage-collector would never call finalize on objects in those slots unless or until the container overwrote those array slots, the container abandoned the array (perhaps in favor of a smaller one), or all rooted references to the container itself were destroyed or otherwise ceased to exist.
There are various means to encourage the system to call finalize on any objects for which no strong rooted references happen to exist (which seems to be the point of the question, and which other answers have already covered), but I think it's important to note the distinction between the set of objects to which strong rooted references exist, and the set of objects that code may be interested in. The two sets largely overlap, but each set can contain objects not in the other. Objects' finalizers` run when the GC determines that the objects would no longer exist but for the existence of finalizers; that may or may not coincide with the time code they cease being of interest to anyone. While it would be helpful if one could cause finalizers to run on all objects that have ceased to be of interest, that is in general not possible.
A call to garabage collecter (System.gc()) method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse (i.e its just a suggestion to the jvm, and does not bind it to perform the action then and there, it may or may not do the same). When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects. finalize() is called by the garbage collector on an object when garbage collection determines that there are no more references to the object
run new constructor() and System.gc() more than twice.
public class Horse {
boolean inStable;
Horse(boolean in){
inStable = in;
}
public void finalize(){
if (!inStable) System.out.print("Error: A horse is out of its stable!");
}
}
public class MainWindow {
public static void main(String[] args) {
for (int i=0;i<100;i++){
Horse h = new Horse(false);
h = new Horse(true);
System.gc();
}
}
}
Here's what worked for me (partially, but it does illustrate the idea):
class OLoad {
public void finalize() {
System.out.println("I'm melting!");
}
}
public class TempClass {
public static void main(String[] args) {
new OLoad();
System.gc();
}
}
The line new OLoad(); does the trick, as it creates an object with no reference attached. This helps System.gc() run the finalize() method as it detects an object with no reference. Saying something like OLoad o1 = new OLoad(); will not work as it will create a reference that lives until the end of main(). Unfortunately, this works most of the time. As others pointed out, there's no way to ensure finalize() will be always called, except to call it yourself.
Related
I found it in many places that the finalize() method in java is called when the garbage collector or System.gc() has successfully retained the memory consumed by the redundant object with no more references to it. Also found that this method is called not more than a single time. I am not new to java but also not pretty much experienced. I may have a wrong understanding of it but let's say a piece of code
public class Solution {
#Override
protected void finalize(){
System.out.print("method called");
}
public static void main(String... args){
Solution obj1= new Solution();
Solution obj2 = new Solution();
Solution obj3 = new Solution();
System.gc();
obj1=obj2;
System.gc();
obj3=null;
System.gc();
}
}
Here, the finalize method is called twice because the memory heap becomes eligible for garbage cleaning two times. So, I am a bit confused whether I know the whole thing right or if it is supposed to behave the way it's behaving.
No. The finalize() method will only be called once by the GC on an object. The JVM sets a flag in the object header (I think) to say that it has been finalized, and won't finalize it again.
The javadoc states this explicitly:
" The finalize method is never invoked more than once by a Java virtual machine for any given object. "
Of course, there is nothing to stop an object method from calling this.finalize() any number of times.
Note that finalize() is deprecated in Java 9 and later for reasons stated in the javadoc. It is recommended that you switch to using one of the following instead:
AutoCloseable + try with resources
Cleaner
PhantomReference
Someone commented thus:
finalize() is called for every Object that is collected.
This is not true for a couple of reasons.
The javadoc explicitly states that there are no guarantees that finalize will ever be called. The thing that is guaranteed is that it will be called (once) before an object's storage is reclaimed. That is a weaker statement than the statement that the comment makes.
One scenario where garbage collected objects may not be finalized is if the JVM exits soon after a GC run.
Another (pathological) scenario occurs when a classes finalize method never returns1. When an instance of that class is finalized, the finalizer thread will get stuck. When all finalizer threads are stuck in that way, no more finalizable objects can be finalized2.
If the Object::finalize is not overridden in a class, the JVM will skip the finalization step for that class.
1 - This could be due to an infinite loop, or because the finalize() method gets stuck waiting on a lock or waiting for an internal or external "event" that never happens. Note also that "never" could mean "not for a long time" in this context. The overall impact can be the same.
2 - The objects will sit in the finalization queue indefinitely. This is a memory leak.
For a library that involves asynchronous operations, I have to keep a reference to an object alive until a certain condition is met.
(I know, that sounds unusual. So here is some context, although it may not strictly be relevant: The object may be considered to be a direct ByteBuffer which is used in JNI operations. The JNI operations will fetch the address of the buffer. At this point, this address is only a "pointer" that is not considered as a reference to the byte buffer. The address may be used asynchronously, later in time. Thus, the buffer has to be prevented from being garbage collected until the JNI operation is finished.)
To achieve this, I implemented a method that is basically equivalent to this:
private static void keepReference(final Object object)
{
Runnable runnable = new Runnable()
{
#SuppressWarnings("unused")
private Object localObject = object;
public void run()
{
// Do something that does NOT involve the "localObject" ...
waitUntilCertainCondition();
// When this is done, the localObject may be garbage collected
}
};
someExecutor.execute(runnable);
}
The idea is to create a Runnable instance that has the required object as a field, throw this runnable into an executor, and let the runnable wait until the condition is met. The executor will keep a reference to the runnable instance until it is finshed. The runnable is supposed to keep a reference to the required object. So only after the condition is met, the runnable will be released by the executor, and thus, the local object will become eligible for garbage collection.
The localObject field is not used in the body of the run() method. May the compiler (or more precisely: the runtime) detect this, and decide to remove this unused reference, and thus allow the object to be garbage collected too early?
(I considered workarounds for this. For example, using the object in a "dummy statement" like logger.log(FINEST, localObject);. But even then, one could not be sure that a "smart" optimizer wouldn't do some inlining and still detect that the object is not really used)
Update: As pointed out in the comments: Whether this can work at all might depend on the exact Executor implementation (although I'd have to analyze this more carefully). In the given case, the executor will be a ThreadPoolExecutor.
This may be one step towards the answer:
The ThreadPoolExecutor has an afterExecute method. One could override this method and then use a sledgehammer of reflection to dive into the Runnable instance that is given there as an argument. Now, one could simply use reflection hacks to walk to this reference, and use runnable.getClass().getDeclaredFields() to fetch the fields (namely, the localObject field), and then fetch the value of this field. And I think that it should not be allowed to observe a value there that is different from the one that it originally had.
Another comment pointed out that the default implementation of afterExecute is empty, but I'm not sure whether this fact can affect the question of whether the field may be removed or not.
Right now, I strongly assume that the field may not be removed. But some definite reference (or at least more convincing arguments) would be nice.
Update 2: Based on the comments and the answer by Holger, I think that not the removal of "the field itself" may be a problem, but rather the GC of the surrounding Runnable instance. So right now, I assume that one could try something like this:
private static long dummyCounter = 0;
private static Executor executor = new ThreadPoolExecutor(...) {
#Override
public void afterExecute(Runnable r, Throwable t) {
if (r != null) dummyCounter++;
if (dummyCounter == Long.MAX_VALUE) {
System.out.println("This will never happen", r);
}
}
}
to make sure that the localObject in the runnable really lives as long as it should. But I can hardly remember ever having been forced to write something that screamed "crude hack" as loud as these few lines of code...
If JNI code fetches the address of a direct buffer, it should be the responsibility of the JNI code itself, to hold a reference to the direct buffer object as long as the JNI code holds the pointer, e.g. using NewGlobalRef and DeleteGlobalRef.
Regarding your specific question, this is addressed directly in JLS §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. …
Another example of this occurs if the values in an object's fields are stored in registers. … Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
(the last sentence matters)
It is illustrated in that chapter by an example not too different to yours. To make things short, the localObject reference within the Runnable instance will keep the life time of the referenced object at least as long as the life time of the Runnable instance.
That said, the critical point here is the actual life time of the Runnable instance. It will be considered definitely alive, i.e. immune to optimizations, due to the rule specified above, if it is also referred by an object that is immune to optimizations, but even an Executor isn’t necessarily a globally visible object.
That said, method inlining is one of the simplest optimizations, after which a JVM would detect that the afterExecute of a ThreadPoolExecutor is a no-op. By the way, the Runnable passed to it is the Runnable passed to execute, but it wouldn’t be the same as passed to submit, if you use that method, as (only) in the latter case, it’s wrapped in a RunnableFuture.
Note that even the ongoing execution of the run() method does not prevent the collection of the Runnable implementation’s instance, as illustrated in “finalize() called on strongly reachable object in Java 8”.
The bottom line is that you will be walking on thin ice when you try to fight the garbage collector. As the first sentence of the cite above states: “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.” Whereas we all may find ourselves being thinking too naively…
As said at the beginning, you may rethink the responsibilities. It’s worth noting that when your class has a close() method which has to be invoked to release the resource after all threads have finished their work, this required explicit action is already sufficient to prevent the early collection of the resource (assuming that the method is indeed called at the right point)…
Execution of Runnable in a thread pool is not enough to keep an object from being garbage collected. Even "this" can be collected! See JDK-8055183.
The following example shows that keepReference does not really keep it. Though the problem does not happen with vanilla JDK (because the compiler is not smart enough), it can be reproduced when a call to ThreadPoolExecutor.afterExecute is commented out. It is absolutely possible optimization, because afterExecute is no-op in the default ThreadPoolExecutor implementation.
import java.lang.ref.WeakReference;
import java.util.concurrent.*;
public class StrangeGC {
private static final ExecutorService someExecutor =
Executors.newSingleThreadExecutor();
private static void keepReference(final Object object) {
Runnable runnable = new Runnable() {
#SuppressWarnings("unused")
private Object localObject = object;
public void run() {
WeakReference<?> ref = new WeakReference<>(object);
if (ThreadLocalRandom.current().nextInt(1024) == 0) {
System.gc();
}
if (ref.get() == null) {
System.out.println("Object is garbage collected");
System.exit(0);
}
}
};
someExecutor.execute(runnable);
}
public static void main(String[] args) throws Exception {
while (true) {
keepReference(new Object());
}
}
}
Your hack with overriding afterExecute will work though.
You've basically invented a kind of Reachability Fence, see JDK-8133348.
The problem you've faced is known. It will be addressed in Java 9 as a part of JEP 193. There will be a standard API to explicitly mark objects as reachable: Reference.reachabilityFence(obj).
Update
Javadoc comments to Reference.reachabilityFence suggest synchronized block as an alternative construction to ensure reachability.
Similar to Can JIT be prevented from optimising away method calls? I'm attempting to track memory usage of long-lived data store objects, however I'm finding that if I initialize a store, log the system memory, then initialize another store, sometimes the compiler (presumably the JIT) is smart enough to notice that these objects are no longer needed.
public class MemTest {
public static void main(String[] args) {
logMemory("Initial State");
MemoryHog mh = new MemoryHog();
logMemory("Built MemoryHog");
MemoryHog mh2 = new MemoryHog();
logMemory("Built Second MemoryHog"); // by here, mh may be GCed
}
}
Now the suggestion in the linked thread is to keep a pointer to these objects, but the GC appears to be smart enough to tell that the objects aren't used by main() anymore. I could add a call to these objects after the last logMemory() call, but that's a rather manual solution - every time I test an object, I have to do some sort of side-effect triggering call after the final logMemory() call, or I may get inconsistent results.
I'm looking for general case solutions; I understand that adding a call like System.out.println(mh.hashCode()+mh2.hashCode()) at the end of the main() method would be sufficient, but I dislike this for several reasons. First, it introduces an external dependency on the testing above - if the SOUT call is removed, the behavior of the JVM during the memory logging calls may change. Second, it's prone to user-error; if the objects being tested above change, or new ones are added, the user must remember to manually update this SOUT call as well, or they'll introduce difficult to detect inconsistencies in their test. Finally, I dislike that this solution prints at all - it seems like an unnecessary hack that I can avoid with a better understanding of the JIT's optimizations. To the last point, Patricia Shanahan's answer offers a reasonable solution (explicitly print that the output is for memory sanity purposes) but I'd still like to avoid it if possible.
So my initial solution is to store these objects in a static list, and then iterate over them in the main class's finalize method*, like so:
public class MemTest {
private static ArrayList<Object> objectHolder = new ArrayList<>();
public static void main(String[] args) {
logMemory("Initial State", null);
MemoryHog mh = new MemoryHog();
logMemory("Built MemoryHog", mh); // adds mh to objectHolder
MemoryHog mh2 = new MemoryHog();
logMemory("Built Second MemoryHog", mh2); // adds mh2 to objectHolder
}
protected void finalize() throws Throwable {
for(Object o : objectHolder) {
o.hashCode();
}
}
}
But now I've only offloaded the problem one step - what if the JIT optimizes away the loop in the finalize method, and decides these objects don't need to be saved? Admittedly, maybe simply holding the objects in the main class is enough for Java 7, but unless it's documented that the finalzie method can't be optimized away, there's still nothing theoretically preventing the JIT/GC from getting rid of these objects early, since there's no side effects in the contents of my finalize method.
One possibility would be to change the finalize method to:
protected void finalize() throws Throwable {
int codes = 0;
for(Object o : loggedObjects) {
codes += o.hashCode();
}
System.out.println(codes);
}
As I understand it (and I could be wrong here), calling System.out.println() will prevent the JIT from getting rid of this code, since it's a method with external side effects, so even though it doesn't impact the program, it can't be removed. This is promising, but I don't really want some sort of gibberish being output if I can help it. The fact that the JIT can't (or shouldn't!) optimize away System.out.println() calls suggests to me that the JIT has a notion of side effects, and if I can tell it this finalize block has such side effects, it should never optimize it away.
So my questions:
Is holdijng a list of objects in the main class enough to prevent them from ever being GCed?
Is looping over those objects and calling something trivial like .hashCode() in the finalize method enough?
Is computing and printing some result in this method enough?
Are there other methods (like System.out.println) the JIT is aware of that cannot be optimized away, or even better, is there some way to tell the JIT not to optimize away a method call / code block?
*Some quick testing confirms, as I suspected, that the JVM doesn't generally run the main class's finalize method, it abruptly exits. The JIT/GC may still not be smart enough to GC my objects simply because the finalize method exists, even if it doesn't get run, but I'm not confident that's always the case. If it's not documented behavior, I can't reasonably trust it will remain true, even if it's true now.
Here's a plan that may be overkill, but should be safe and reasonably simple:
Keep a List of references to the objects.
At the end, iterate over the list summing the hashCode() results.
Print the sum of the hash codes.
Printing the sum ensures that the final loop cannot be optimized out. The only thing you need to do for each object creation is put it in a List add call.
Yes, it would be legal for mh1 to be garbage collected at that point. At that point, there is no code that could possibly use the variable. If the JVM could detect this, then the corresponding MemoryHog object will be treated as unreachable ... if the GC were to run at that point.
A later call like System.out.println(mh1) would be sufficient to inhibit collection of the object. So would using it in a "computation"; e.g.
if (mh1 == mh2) { System.out.println("the sky is falling!"); }
Is holding a list of objects in the main class enough to prevent them from ever being GCed?
It depends on where the list is declared. If the list was a local variable, and it became unreachable before mh1, then putting the object into the list will make no difference.
Is looping over those objects and calling something trivial like .hashCode() in the finalize method enough?
By the time the finalize method is called, the GC has already decided that the object is unreachable. The only way that the finalize method could prevent the object being deleted would be to add it to some other (reachable) data structure or assign it to a (reachable) variable.
Are there other methods (like System.out.println) the JIT is aware of that cannot be optimized away,
Yea ... anything that makes the object reachable.
or even better, is there some way to tell the JIT not to optimize away a method call / code block?
No way to do that ... apart from making sure that the method call or code block does something that contributes to the computation being performed.
UPDATE
First, what is going on here is not really JIT optimization. Rather, the JIT is emitting some kind of "map" that the GC is using to determine when local variables (i.e. variables on the stack) are dead ... depending on the program counter (PC).
Your examples to inhibit collection all involve blocking the JIT via SOUT, I'd like to avoid that somewhat hacky solution.
Hey ... ANYTHING that depends on the exact timing of when things are garbage collected is a hack. You are not supposed to do that in a properly engineered application.
I updated my code to make it clear that the list that's holding my objects is a static variable of the main class, but it seems if the JIT's smart enough it could still theoretically GC these values once it knows the main method doesn't need them.
I disagree. In practice, the JIT cannot determine that a static will never be referenced. Consider these cases:
Before the JIT runs, it appears that nothing will use static s again. After the JIT has run, the application loads a new class that refers to s. If the JIT "optimized" the s variable, the GC would treat it as unreachable, and either null it or create a dangling references. When the dynamically loaded class then looked at s it would then see the wrong value ... or worse.
If the application ... or any libraries used by the application ... uses reflection, then it can refer to the value of any static variable without this being detectable by the JIT.
So while it is theoretically possible to do this optimization is a small number of cases:
in the vast majority of cases, you can't, and
in the few cases that you can, the pay-off (in terms of performance improvement) is most likely negligible.
I similarly updated my code to clarify that I'm talking about the finalize method of the main class.
The finalize method of the main class is irrelevant because:
you are not creating an instance of the main class, and
the finalize method CANNOT refer to the local variables of another method (e.g. the main method).
... it's existence prevents the JIT from nuking my static list.
Not true. The static list can't be nuked anyway; see above.
As I understand it, there's something special about SOUT that the JIT is aware of that prevents it from optimizing such calls away.
There is nothing special about sout. It is just something that we KNOW that influences the results of the computation and that we therefore KNOW that the JIT cannot legally optimize away.
In Java, I've done things like the following without thinking much about it:
public class Main {
public void run() {
// ...
}
public static void main(String[] args) {
new Main().run();
}
}
However, recently I've become unsure as to whether doing that is safe. After all, there is no reference to the Main object after it's created (well, there is the this reference, but does that count?), so it looks like there's a danger that the garbage collector might delete the object while it's in the middle of executing something. So perhaps the main method should look like this:
public static void main(String[] args) {
Main m = new Main();
m.run();
}
Now, I'm pretty sure that the first version works and I've never had any problems with it, but I'd like to know if it's safe to do in all cases (not only in a specific JVM, but preferably according to what the language specification says about such cases).
If an object method is being executed, it means someone is in possession of that reference. So no, an object can't be GC'd while a method is being executed.
For the most part garbage collection is transparent. It's there to remove the unnecessary complication of manual memory management. So, it will appear not to be collected, but what actually happens is more subtle.
Trivially, a compiler may completely elide the construction of the object. (By compiler, I mean a lower level compiler than javac. The bytecodes will be a literal transliteration of the source.) More obscurely, garbage collection typically runs in separate threads and actually remove the unaccessed object as a method on it is being run.
How can this be observed? The usual suspect in a finaliser. It may run concurrently with a method running on the object. Typically you would get around this problem with synchronized blocks in both the finaliser and the normal methods, which introduces the necessary happens-before relationship.
m is just a variable which has reference stored. This will be used by programmer to use the same object further to write logic on same object.
While execution, program will be converted to OP-CODES / INSTRUCTIONS .
These INSTRUCTION will have the reference to object(it is a memory location after all).
In case m is present, location of object will be accessed via INDIRECT REFERENCE.
If m is absent, the reference is DIRECT.
So here, object is being used by CPU registers, irrespective of use of reference variable.
This will be available till the flow of execution is in scope of main() function.
Further, as per GC process, GC only removes objects from memory, once GC is sure that the object will not be used any further.
Every object is given chance to survive a number of times(depends on situation and algorithm). Once the number of chances are over, then only object is garbage collected.
In simpler words, objects which were used recently, will be given chance to stay in memory.
Old objects will be removed from memory.
So given your code:
public class Main {
public void run() {
// ...
}
public static void main(String[] args) {
new Main().run();
}
}
the object will not be garbage collected.
Also, for examples, try to look at anonymous class examples. Or examples from event handling in AWT / SWING.
There, you will find a lot of usage like this.
The accepted answer is not correct. Whether the object can be GCed or not depends on if your public void run() {// ...} method has a reference to the class instance (this). Try:
public class FinalizeThis {
private String a = "a";
protected void finalize() {
System.out.println("finalized!");
}
void loop() {
System.out.println("loop() called");
for (int i = 0; i < 1_000_000_000; i++) {
if (i % 1_000_000 == 0)
System.gc();
}
// System.out.println(a);
System.out.println("loop() returns");
}
public static void main(String[] args) {
new FinalizeThis().loop();
}
}
The above program always outputs
loop() called
finalized!
loop() returns
in Java 8. If you, however, uncomment System.out.println(a), the output changes to
loop() called
a
loop() returns
There is no GC this time because the method called references the instance variable (this.a).
You can take look at this answer
If I have a class delete itself, should its internal methods stop executing? I have a class B that tells class A to remove B from A's ArrayList. I'm fairly certain B only exists in A's ArrayList, and so when I remove it, it should be deleted, right? (NOTE: I've included a Serializable implementation just in case that would have anything to do with how the VM handles my classes, but I did not write in the read- and writeObject methods here. I doubt it will have anything to do with this issue though.)
public class A implements Serializable, B_Listener {
ArrayList<B> bArray;
public A() {
bArray = new ArrayList<SomeObject>();
bArray.add(new B(bArray.size(), this));
}
#Override
public void deleteAtIndex(int index) {
bArray.remove(index);
}
}
public class B implements Serializable {
B_Listener listener;
int index;
public B(B_Listener listener, int index) {
this.listener = listener;
this.index = index;
}
//This is called at some point in a B's lifetime.
private void selfDestruct() {
listener.deleteAtIndex(index);
Log.w("B.class", "Should this not output? It does.");
}
}
public interface B_Listener {
public void deleteAtIndex(int index);
}
So the Log.w message executes when I don't believe it should. Therefore, I'm afraid I'm creating java's memory leaks. I've looked and looked throughout my code trying to find where B might be held by a pointer, but I've come up with nothing besides what I intended.
So then I'm asking if garbage is collected at a different time than when B is deleted on my end. If this is the case, then is it safe to say for the time being that I in fact am not holding objects I do not intend to hold?
Extra (NOTE: this might be hard to follow, everything above this should suffice for the problem):
I also have this tagged with Android-Views because I'm developing on Android: my B class holds View objects that point to B as a listener. When I removeView, the View manager or whatever Android has should no longer point to the View, I believe, and when I delete B, all its internal Views should also be deleted, meaning they can no longer hold B in existence by their own listener pointers. I'm just talking this out to see if my understanding here is correct.
Of course not.
A method will only "stop executing" if it returns, if an exception is thrown, or if the thread is aborted.
The whole point of garbage collection is that it is invisible to you. Barring special tricks (such as WeakReferences, or checking free memory), it is impossible to tell whether an object has been garbage collected – if you can check whether it exists, that means that you have a reference to it, so it cannot be collected.
Usually there will be two kinds of GC: minor (every second or so) and major (every hour or so, but if you give your VM enough memory it could as well be a week).
Objects are freed in an asynchronous way (it's much more effective to do that in bulk and it helps in keeping the memory unfragmented). They will not be deleted the millisecond they are not accessible.
Garbage collection only makes sense when no active thread is able to access an object, not when no object holds a reference to it. In your code, as long as selfDestruct runs, the thread owns an implicit "this" reference. This causes the object to be, indeed, referenced by a thread - and safe from GC.