1

I have a data producer that produces data that is used by a number of a different consumers (let's call them Cs). Each C has its own set of data that it's interested in. The data producer has weak references to the Cs so they can be notified for updates.

Each C is also used by a number of independent components, so no single one component can tell when the C is no longer needed, so we have to leave it to the JVM to determine when C is GC-able.

The goal here is to be notified when a C becomes obsolete, so the data producer can turn off data that is only interesting to that unused C.

As I mentioned earlier, the data producer always has weak references to the Cs, so it's easy to do it when a C is GCed. However, I noticed that the Cs usually stick around in the VM for an extended period of time before it's finally GC-ed and all this while, the data producer is producing a LOT of data it should have needed to.

Is there any way for me to force the GC of unused Cs? I am hoping for yes, but I'm expecting a No, so as a follow-up question, does anyone have a good suggestion to how I can (re)design this to make it work better/more efficiently?

Thank you!!

Some answers below make a lot of good points - in particular the suggestion to force users of C to subscribe and unsubscribe. This is difficult because:

C is just one possible implementation of an interface I (which doesn't have this subscription requirement), which is what the users really use. The C implementation is injected during run-time, so we can't force the users to comply to C-specific requirements. (Ouch?)

RAY
  • 6,810
  • 6
  • 40
  • 67
  • @pst - not really. The production of the data can be (and is) very expensive, and we only want to produce as little of it as possible. – RAY Feb 18 '11 at 09:22

5 Answers5

1

The components which use C can notify when they are interested and no longer interested.

When there is at least one interested component, turn on subscription. (Not before which appears the case here), when the last component un-subscribes, turn off the data.

Set<C> components = ...

public void subscribesTo(C component) {
   if (components.isEmpty()) 
      enableSubscription();
   components.add(component);
}

public void unsubscribeFrom(C component) {
   components.remove(component);
   if (components.isEmpty()) 
      disableSubscription();
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks.The issue is, the Cs are an existing class, and it's used by a zillion different purposes, it's impractical to require all users now to subscribe to it before using it. Also, there is no way we can enforce that the C users will honorably unsubscribe when they're done using C, which could result in serious memory and resource leaks. – RAY Feb 18 '11 at 09:14
  • @RAY: if you can't ensure that the users of C correctly close it, how can you ensure that they will let go of any references to C? – Joachim Sauer Feb 18 '11 at 09:27
  • If you have unreliable, unmaintainable code, efficiency shouldn't be a consideration, you just have to go with what works and hope for the best. – Peter Lawrey Feb 18 '11 at 09:34
  • @Joachim Sauer This is fair point. I guess the difference is that we'd require the users to be more dilligent if they are to do it explicitly. Chances are (as in my case), these users are not long-lived, and when they die themselves, the references of C are freed. – RAY Feb 18 '11 at 09:36
  • Let me try to clarify the situation a little better. The implementation of C tries to fit in to a more generic paradigm. Let's just say it implements some interface I and is just one of the many implementations. The users of C are in fact users of I, so it's practical (or correct?) to require them to be aware of C-specific requirements. – RAY Feb 18 '11 at 09:39
  • It is common practice with messaging (eg. JMS) and market data to subscribe to the things you are interested and notify directly or indirectly when not interested. – Peter Lawrey Feb 18 '11 at 09:44
1

I'll just go with System.gc();

There's some really interesting information in this related post: Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

Apparently a lot of IDEs use that too to evaluate the amount of available heap. Guess there's no reason I can't do that too.

Community
  • 1
  • 1
RAY
  • 6,810
  • 6
  • 40
  • 67
0

Perhaps we can clarify your architecture first. You have:

  1. A data producer (P)
  2. A number of consumers (C)
  3. A number of components that 'use' the consumers.

What I want to know is - what is the relationship from components to consumers? All you have stated is there are multiple components that use a single consumer.

Generally if the system was full of just P and Cs then you could get the C to de-register itself and you're done (As Peter shows in his example). However, in this case, a number of components use the C. I guess with limited knowledge of your architecture I would suggest that you get the components to register and de-register with each C when it needs it, and C can de-register itself from P when all components de-register.

  • Thanks. I think that's the same as what Peter Lawrey suggested. The Cs are used by people/programs that don't necessary have in-depth knowledge of the C class, and therefore it's hard to force them to register or de-regsiter them. – RAY Feb 18 '11 at 09:16
0

By calling System.gc() you suggest to the VM that it should do something about the memory situation. I quote from the javadoc:

When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Note that this doesn't mean that it actually has performed a GC, it just checks to see if it needs to. In practice, I haven't yet seen a VM ignore a System.gc() call.

Normally you don't have to and shouldn't do this. The VM has a far better understanding of the behaviour of the memory subsystem than you (and I) do. But, in some cases, where the application behaviour is uncommon and you know that the memory is needed it is ok to do it.

Erik
  • 2,013
  • 11
  • 17
0

You can't force the JVM to do garbage collection, the best you can do is suggest it via a call to System.gc().

Maybe a better solution would be to introduce some sort of Listener pattern with your Cs registering/deregistering with the data producer and the independent components registering with your C. As things deregister from your C it can check to see if it is no longer needed, in which case it can deregister from the data producer.

Richard Miskin
  • 1,260
  • 7
  • 12