When does a Class object get garbage collected?
I was wondering if somebody could tell me when a Java Class
object gets garbage collected. My use case is a cache (Map<Class<?>, Class<?>[]>
) which holds the class-hierarchy of objects.
For instance:
The (short) hierarchy of String.class
would be (descending): String开发者_如何学Python.class
-> Object.class
. A valid cache-entry for this type would be [KEY: String.class, VALUE: {String.class, Object.class}]
.
I guess String.class
is a bad example since the String.class should be garbage-collected....
I need this cache for a serialization project I'm working on. When writing an object my system needs the hierarchy of this object for choosing the correct "Codecs (Serializers)". Collecting the hierarchy for each object would cause some overhead which is not necessary. But then I though about memory-leaks. Probably class-objects can be garbage-collected (Which i don't know) which would not work when using strong-references in my cache.
Do you think a WeakHashMap would be enough? Or do I have to use something like:
Map<WeakReference<Class<?>>, WeakReference<Class<?>>[]> ?
What do you think about this issue?
Without getting into the details of Class garbage collection in Java, I don't think you need to worry at all: The Class Objects themselves don't need to be collected to prevent a memory leak to accomplish what you want. After all, there will only ever be a single Class instance for java.lang.String
. So if you put a reference to String.class
into a Map
(or any other data structure) you aren't creating a new instance of the String class, just a reference to the existing one.
As soon as your Map
goes out of scope, the entire Map
will be eligible for garbage collection.
Classes are garbage collected at the same time as their class loader. So non-strong references are important if you want your code to work in the presence of transient class loaders.
Map<WeakReference<Class<?>>, WeakReference<Class<?>>[]>
This almost works. You can't have an array of a generic type. I suggest using a List
instead.
This is kind of interning rather the caching. It shouldn't really matter in this case as the amount of memory used per key is tiny in comparison to the class. If you really wanted a cache you would need to use ReferenceQueue
for eviction and something like:
Map<SoftReference<WeakReference<Class<?>>>, List<WeakReference<Class<?>>>>
(If you want, the angles could be cleaned up by introducing classes [with behaviour] that can be used for the key and value.)
You can't tell the exact time an object is garbage collected, not even when calling the garbage collector (Runtime.getRuntime().gc();).
Furthermore, using WeakHashMap for caching is usually a bad choice since weak references are used only for the keys and not for the values. Just google, you'll find a lot of helpful articles, e.g.
- http://www.codeinstructions.com/2008/09/weakhashmap-is-not-cache-understanding.html
- several issues at http://www.javaspecialists.eu/
- http://www.java2s.com/Tutorial/Java/0140_Collections/0340_WeakHashMap.htm
Finally, you should check whether you really need caching (e.g. with a profiler like JVisualVM) since you are using String and Class objects...
精彩评论