WeakReference string did not collect garbage? How?

I read about WeakReference on Wikipedia and I saw this code

 public class ReferenceTest { public static void main(String[] args) throws InterruptedException { WeakReference r = new WeakReference(new String("I'm here")); WeakReference sr = new WeakReference("I'm here"); System.out.println("before gc: r=" + r.get() + ", static=" + sr.get()); System.gc(); Thread.sleep(100); // only r.get() becomes null System.out.println("after gc: r=" + r.get() + ", static=" + sr.get()); } } 

When it starts, this is the result

before gc: r = I'm here, static = I'm here

after gc: r = null, static = I'm here

sr and r variables - both refer to string objects. r now garbage collected, but why did sr not garbage collect after calling the garbage collector?

I'm just wondering how this happened.

+3
source share
3 answers

This is NOT due to the row pool itself.

The real reason is that the ReferenceTest class has an implicit hard link to a String object that represents the literal "I'm here" . This hard link means that the weak link in sr will not be broken by garbage collection 1 .

Actually:

  • An implicit reference would be necessary even if String objects corresponding to literals were not combined. (They are combined ... JLS effectively requires this ... but I say that links would be required even if they were not. An alternative for Java would be to mint a new String object every time a string literal expression was This would be terrible inefficient !!)

  • The string pool internally uses the weak link form ... so that unlisted interned strings can be garbage collected. If this is not the case, then each new interned line will be a memory leak.

In any case ... if you carefully build the string without using a string literal, and put it like this:

  char[] chars = {'a', 'b', 'c'}; WeakReference r = new WeakReference(new String(chars).intern()); 

... you should find that the weak link (in the end) is broken. (This may take several GC cycles.)


1 - Theoretically, by causing class unloading and garbage collection, you can get rid of the last available reference to this string literal. However, if this happened in this case, you will pass the point where you can observe the state of the WeakReference object. At least with your sample code. In addition, if you do not load the JVM using a special class loader, I don’t think it would be possible to infer entrypoint class unloading. This is not something that is easy or beneficial to do.

+6
source

This is due to the pool pool. When you create a line with a new statement, it will be created in the pool and available for regular garbage collection. But when you define a string as a literal, it will be created in the string pool, and this will not get garbage collected with normal gc operation

+1
source

Static variables are garbage collected only when the class is unloaded. Therefore, you can see that the value of the static variable is still printed even after you manually started garbage collection.

-1
source

Source: https://habr.com/ru/post/1489870/


All Articles