4

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.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?

Whymarrh
  • 13,139
  • 14
  • 57
  • 108
Kr0e
  • 2,149
  • 2
  • 24
  • 40
  • possible duplicate of [When and how are classes garbage collected in Java?](http://stackoverflow.com/questions/2433261/when-and-how-are-classes-garbage-collected-in-java) – Bohemian Sep 04 '11 at 10:42
  • I don't think this is a dupe of that question, see my answer (unless I'm misinterpreting) – Adam Batkin Sep 04 '11 at 10:43
  • I think normal references and weak references are not enough for the kind of cache you need. I recently asked a similar question on .net. .net offers a special class with the collection semantics needed here. One conclusion was that normal weak references are not a good way to do this. http://stackoverflow.com/questions/6601502/caching-reflection-data – CodesInChaos Sep 04 '11 at 13:00

3 Answers3

2

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.

Adam Batkin
  • 51,711
  • 9
  • 123
  • 115
  • Hi! The map (cache) should never go out of scope since its a static final cache. Sorry, I should have told that. But I guess this does not change anything. In my opinion class objects should not be able to be garbage-collected. But I'm not quite sure... – Kr0e Sep 04 '11 at 10:55
  • If you ever need to work with different classloaders (let's say your classes are in a Webapp/Servlet environment) you need to worry about memory leaks of class objects. – ysdx Sep 04 '11 at 19:45
  • @ysdx Yeah, but it isn't clear that the question involves creating new classes or classloaders, it's just a bunch of static data in a `Map`. So any memory issues are not `Class` specific and discussing classes/classloaders may be a red herring (in this instance). – Adam Batkin Sep 05 '11 at 15:02
0

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.

Finally, you should check whether you really need caching (e.g. with a profiler like JVisualVM) since you are using String and Class objects...

Alexey Ivanov
  • 11,541
  • 4
  • 39
  • 68
DaveFar
  • 7,078
  • 4
  • 50
  • 90
  • 1
    About the presentation of the third link: it's not a copy & paste mistake but a stackoverflow bug (you can hit edit and see for yourself ;) – DaveFar Sep 04 '11 at 11:12
  • The thing about `WeakHashMap` that prevents it being useful for caches is that without any other references to the key, entries may be removed from the map immediately. This does happen in practice, but only after some HotSpot optimisation which wont happen until the code is really quite "hot" - very difficult to test. – Tom Hawtin - tackline Sep 04 '11 at 12:13
0

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.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • Is it correct that you want a SoftReference to a weak reference? Don't you want a SoftReference to the class? i.e. something like `SoftReference>` – CodesInChaos Sep 04 '11 at 13:06
  • 1
    @CodeInChaos Yeah, that's quite correct. I don't want a soft reference to the class, because that will delay the whole class loader edifice from being collected. So there a weak reference to the class, which stays valid until the class has no strong references, and soft reference (only) to the weak reference which will remain until the JVM decides it needs to free up some memory. (Note both of these references should be associated with the `ReferenceQueue` - either reference being cleared should remove the entry from the map.) – Tom Hawtin - tackline Sep 04 '11 at 13:41
  • Ok, thanks. I've created a cache based on your suggestion. I would post the code but stackoverflow told me I had to wait for 4 hours before posting an answer to my question =( I'm new to stackoverflow.. So maybe I do something wrong. – Kr0e Sep 04 '11 at 13:56
  • @Kr0e Stack Overflow throttles certain behaviours of new users (low rep scores) to prevent spam and unwanted behaviour. In fact, all users have certain activities throttled, for instance time between upvoting comments. – Tom Hawtin - tackline Sep 04 '11 at 14:25