Why doesn't the JVM destroy a resource as soon

2019-04-25 01:34发布

问题:

I have always wondered why the garbage collector in Java activates whenever it feels like it rather than do:

if(obj.refCount == 0)
{
   delete  obj;
}

Are there any big advantages to how Java does it that I overlooked?

Thanks

回答1:

Each JVM is different, but the HotSpot JVM does not primarily rely on reference counting as a means for garbage collection. Reference counting has the advantage of being simple to implement, but it is inherently error-prone. In particular, if you have a reference cycle (a set of objects that all refer to one another in a cycle), then reference counting will not correctly reclaim those objects because they all have nonzero reference count. This forces you to use an auxiliary garbage collector from time to time, which tends to be slower (Mozilla Firefox had this exact problem, and their solution was to add in a garbage collector at the cost of much code readability). This is why, for example, languages like C++ tend to have a combination of shared_ptrs that use reference counting and weak_ptrs that don't use reference cycles.

Additionally, associating a reference count with each object makes the cost of assigning a reference greater than normal, because of the extra bookkeeping involved of adjusting the reference count (which only gets worse in the presence of multithreading). Furthermore, using reference counting precludes the use of certain types fast of memory allocators, which can be a problem. It also tends to lead to heap fragmentation in its naive form, since objects are scattered through memory rather than tightly-packed, decreasing allocation times and causing poor locality.

The HotSpot JVM uses a variety of different techniques to do garbage collection, but its primary garbage collector is called a stop-and-copy collector. This collector works by allocating objects contiguously in memory next to one another, and allows for extremely fast (one or two assembly instructions) allocation of new objects. When space runs out, all of the new objects are GC'ed simultaneously, which usually kills off most of the new objects that were constructed. As a result, the GC is much faster than a typically reference-counting implementation, and ends up having better locality and better performance.

For a comparison of techniques in garbage collecting, along with a quick overview of how the GC in HotSpot works, you may want to check out these lecture slides from a compilers course that I taught last summer. You may also want to look at the HotSpot garbage collection white paper that goes into much more detail about how the garbage collector works, including ways of tuning the collector on an application-by-application basis.

Hope this helps!



回答2:

Reference counting has the following limitations:

  • It is VERY bad for multithreading performance (basically, every assignment of an object reference must be protected).
  • You cannot free cycles automatically


回答3:

Because it doesn't work strictly based on reference counting.

Consider circular references which are no longer reachable from the "root" of the application.

For example:

APP has a reference to SOME_SCREEN

SOME_SCREEN has a reference to SOME_CHILD

SOME_CHILD has a reference to SOME_SCREEN

now, APP drops it's reference to SOME_SCREEN.

In this case, SOME_SCREEN still has a reference to SOME_CHILD, and SOME_CHILD still has a reference to SOME_SCREEN - so, in this case, your example doesn't work.

Now, others (Apple with ARC, Microsoft with COM, many others) have solutions for this and work more similarly to how you describe it.

With ARC you have to annotate your references with keywords like strong and weak to let ARC know how to deal with these references (and avoid circular references)... (don't read too far into my specific example with ARC because ARC handles these things ahead-of-time during the compilation process and doesn't require a specific runtime per-se) so it can definitely be done similarly to how you describe it, but it's just not workable with some of the features of Java. I also believe COM works more similarly to how you describe... but again, that's not free of some amount of consideration on the developer's part.

In fact, no "simple" reference counting scheme would ever be workable without some amount of thought by the application developer (to avoid circular references, etc)



回答4:

Because the garbage collector in modern JVMs is no longer tracking references count. This algorithm is used to teach how GC works, but it was both resource-consuming and error-prone (e.g. cyclic dependencies).



回答5:

because the garbage collector in java is based on copying collector for 'youg generation' objects, and mark and sweep for `tenure generations' objects.

Resources from: http://java.sun.com/docs/hotspot/gc1.4.2/faq.html