destructor needed

Discussion in 'Java' started by Jacob, Oct 30, 2003.

  1. Jacob

    Jacob Guest

    I have objects that are added as listeners
    to various system events (such as change of
    language or units etc.).

    To subscribe to such events I typically call
    someManager.addListener(this); and the "this"
    object will be added in a subscription list
    of someManager.

    My problem is when these objects are no longer
    needed. Normally they would be GC'd, but because
    of the subscription references they are not,
    and the memory is in effect lost.

    My current approach is to have a destroy()
    method on these objects where I unsubscribe
    to system events (removeListener). I am then
    forced to think C++ and figure out when the
    object actually dies and call the destroy()
    method there, which is a pain as it may
    include calling destroy() of children objects
    etc. and in general it will be very hard to
    get rid of them all.

    As I assume my architechture is commonplace,
    some of you might have a brigther solution
    to the problem?

    Thanks!
     
    Jacob, Oct 30, 2003
    #1
    1. Advertising

  2. Jacob

    Sergio Juan Guest

    Hi.

    Look at java.lang.ref.WeakReference at the Java API documentation. I think
    it is what you are looking for, anyway I can not help you more as I never
    had to work with it.

    HTH

    "Jacob" <> escribió en el mensaje
    news:SI4ob.35122$...
    > I have objects that are added as listeners
    > to various system events (such as change of
    > language or units etc.).
    >
    > To subscribe to such events I typically call
    > someManager.addListener(this); and the "this"
    > object will be added in a subscription list
    > of someManager.
    >
    > My problem is when these objects are no longer
    > needed. Normally they would be GC'd, but because
    > of the subscription references they are not,
    > and the memory is in effect lost.
    >
    > My current approach is to have a destroy()
    > method on these objects where I unsubscribe
    > to system events (removeListener). I am then
    > forced to think C++ and figure out when the
    > object actually dies and call the destroy()
    > method there, which is a pain as it may
    > include calling destroy() of children objects
    > etc. and in general it will be very hard to
    > get rid of them all.
    >
    > As I assume my architechture is commonplace,
    > some of you might have a brigther solution
    > to the problem?
    >
    > Thanks!
    >
     
    Sergio Juan, Oct 30, 2003
    #2
    1. Advertising

  3. Jacob

    Jacob Guest

    Jacob, Oct 30, 2003
    #3
  4. Jacob

    Filip Larsen Guest

    Jacob wrote

    > I have objects that are added as listeners
    > to various system events (such as change of
    > language or units etc.).
    >
    > To subscribe to such events I typically call
    > someManager.addListener(this); and the "this"
    > object will be added in a subscription list
    > of someManager.
    >
    > My problem is when these objects are no longer
    > needed. Normally they would be GC'd, but because
    > of the subscription references they are not,
    > and the memory is in effect lost.


    As Sergio Juan already suggested, you can use java.lang.WeakReference to
    solve this problem.

    A simple way of doing this is to code a weak listener that holds a weak
    reference to the real listener and insert the weak listener instead. It goes
    like this:

    // this is the normal listener interface
    public interface MyListener extends EventListener {
    void myAction(EventObject ev);
    }

    // this is the class producing the events
    public class MyEventSource {
    public void addMyListener(MyListener l) { ... }
    public void removeMyListener(MyListener l) { ... }
    }

    // this is the new class you need
    public class WeakMyListener implements MyListener {

    final private WeakReference ref;

    public WeakMyListener(MyListener delegate) {
    this.ref = new WeakReference(delegate);
    }

    public void myAction(EventObject ev) {
    MyListener delegate = (MyListener) ref.get();
    if (delegate != null) {
    delegate.myAction(ev);
    } else {
    MyEventSource source = (MyEventSource) ev.getSource();
    source.removeMyListener(this);
    }
    }
    }

    With this you can add the listener with

    source.addMyListener(new WeakMyListener(myListener));

    If you want to manually remove the listener before it is garbage collected,
    you have to store a reference to the weak listener and remove that instead.
    Don't store any references to myListener or it might never be garbage
    collected. If you have trouble figuring out where to use weak references,
    make an object diagram (include the main thread in that diagram) that show
    the relevant object references in your system, and then figure out which
    references must be weak in order for the "branch" be garbage collected.
    Usually a branch only needs a single weak reference to allow a whole block
    to be garbage collected. If you overdo it and introduce too many weak
    references you run the risk of "premature" garbage collection, so be sure
    that you know what you are doing.

    Note that the above approach only works if the source object is actually
    emitting events. If it is not emitting event and you keep adding weak
    listeners, they will all just pile up in the listener list just as before.
    In this case you may have to use a ReferenceQueue or make the source emit
    some kind of "keep-alive" events.

    If the MySource is not a fixed class or interface (with add and remove for
    the listener type), or in other words, if you cannot generally do the cast
    in "(MyEventSource) ev.getSource()", you may have to use another approach to
    remove the weak listener from the list, like using reflection. However, if
    at all possible, I would strongly recommend that you at least use an
    interface for the add and remove method so you can cast directly.


    Regards,
    --
    Filip Larsen
     
    Filip Larsen, Oct 30, 2003
    #4
  5. Jacob wrote:

    > I have objects that are added as listeners
    > to various system events (such as change of
    > language or units etc.).
    >
    > To subscribe to such events I typically call
    > someManager.addListener(this); and the "this"
    > object will be added in a subscription list
    > of someManager.
    >
    > My problem is when these objects are no longer
    > needed. Normally they would be GC'd, but because
    > of the subscription references they are not,
    > and the memory is in effect lost.
    >
    > My current approach is to have a destroy()
    > method on these objects where I unsubscribe
    > to system events (removeListener). I am then
    > forced to think C++ and figure out when the
    > object actually dies and call the destroy()
    > method there, which is a pain as it may
    > include calling destroy() of children objects
    > etc. and in general it will be very hard to
    > get rid of them all.
    >
    > As I assume my architechture is commonplace,
    > some of you might have a brigther solution
    > to the problem?


    I think your architecture sounds strange, and could perhaps benefit from
    a redesign. A more typical design would feature

    (1) Listeners that are added and never need to be removed (normal for
    many GUIs)

    and/or

    (2) Listeners for which it is clear when and to what they should be
    added, and when and from what they should be removed. It is rare that
    you cannot bracket the code that requires the listener(s) with matching
    add and removeListener calls, preferrably in the same method but
    possibly in different methods invoked at the same call depth. try /
    finally is definately your friend if you need to ensure resource cleanup.


    Where the actual listener addition and removal logic goes depends on the
    specific requirements of your application. A hierarchical invocation of
    destroy / close methods, should it be necessary, oughtn't to be too
    difficult to achieve. Design your classes with that in mind if it's
    what you need.


    John Bollinger
     
    John C. Bollinger, Oct 30, 2003
    #5
  6. Java has a pre defined weak reference map (forget what it is called) that I
    have used for this problem. Though a map is not what I would normally
    choose, it worked fine.

    -David

    "Jacob" <> wrote in message
    news:SI4ob.35122$...
    > I have objects that are added as listeners
    > to various system events (such as change of
    > language or units etc.).
    >
    > To subscribe to such events I typically call
    > someManager.addListener(this); and the "this"
    > object will be added in a subscription list
    > of someManager.
    >
    > My problem is when these objects are no longer
    > needed. Normally they would be GC'd, but because
    > of the subscription references they are not,
    > and the memory is in effect lost.
    >
    > My current approach is to have a destroy()
    > method on these objects where I unsubscribe
    > to system events (removeListener). I am then
    > forced to think C++ and figure out when the
    > object actually dies and call the destroy()
    > method there, which is a pain as it may
    > include calling destroy() of children objects
    > etc. and in general it will be very hard to
    > get rid of them all.
    >
    > As I assume my architechture is commonplace,
    > some of you might have a brigther solution
    > to the problem?
    >
    > Thanks!
    >
     
    David Holliday, Oct 31, 2003
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thomas Nick
    Replies:
    0
    Views:
    1,953
    Thomas Nick
    Jun 13, 2005
  2. frs
    Replies:
    20
    Views:
    783
    Alf P. Steinbach
    Sep 21, 2005
  3. arun
    Replies:
    2
    Views:
    566
    benben
    Jun 13, 2006
  4. Jimmy Hartzell
    Replies:
    0
    Views:
    436
    Jimmy Hartzell
    May 19, 2008
  5. Jimmy Hartzell
    Replies:
    2
    Views:
    1,181
    Jimmy Hartzell
    May 20, 2008
Loading...

Share This Page