🔒 Locked
[java] [SOLVED] Weak reference not functioning as expected
Advertisement
Original Post
I am writing code for a thread that reads data from a weakly-referenced custom socket object and exits when the socket is dereferenced by outside code. That is, a socket that closes itself when you dereference it. The problem is that the thread never exits. I examined the socket in the NetBeans reference tracker and after I dereference the socket, and the only thing keeping the socket alive is a weak reference. That's not how it's supposed to work, right? [Edited by - Dathgale on May 31, 2009 4:09:29 PM]
It is not clear what the problem is. If you post some code, it will be easier to help.
Using the garbage collector to manage anything other than memory is bound to fail. There is no guarantee that the garbage collector will ever collect anything - until you physically run out of memory.
Thanks for the replies.
I doubt it. Check this out:
Here's the code that's giving me problems:
The problem here is that the weak reference to the outbound connection appears to be the only thing keeping the outbound connection alive, according to the NetBeans reference tracker. I explicitly call System.gc() when I want to disconnect, and I even left the program running until the heap filled up with garbage and the garbage collector had to run. It just kept on printing "timeout" to indicate that it was still running.
Quote:
Original post by ToohrVyk
The socket might also be kept alive by the fact that no garbage collection happens.
I doubt it. Check this out:
import java.lang.ref.*;public class WeakReferenceTest { static public void main(String[] args) { WeakReference<Object> obj = new WeakReference<Object>(new Object()); while(true) { Object referent = obj.get(); if(referent == null) break; referent = null; System.out.println("gc"); System.gc(); } System.out.println("done"); }}/* *****OUTPUT***** */gcdone/* It works perfectly. */Here's the code that's giving me problems:
class OutboundConnectionInputThread extends Thread { private WeakReference<OutboundConnection> conn; public OutboundConnectionInputThread(OutboundConnection connection) { super("OutboundConnection input"); conn = new WeakReference<OutboundConnection>(connection); } private OutboundConnection getConnection() throws InterruptedException { OutboundConnection connection = conn.get(); if(connection == null) { System.err.println( "OutboundConnection discarded; thread exiting." ); throw new InterruptedException(); } return connection; } private DatagramPacket getPacket() throws IOException, InterruptedException { OutboundConnection connection = getConnection(); DatagramPacket packet = new DatagramPacket( new byte[connection.sock.getReceiveBufferSize()], connection.sock.getReceiveBufferSize() ); connection = null; return packet; } private void recv(DatagramPacket in) throws IOException, InterruptedException { try { OutboundConnection connection = getConnection(); connection.sock.setSoTimeout(1000); connection.sock.receive(in); connection.received(new LocalIO(in.getData())); connection = null; } catch(SocketTimeoutException e) { System.err.println("timeout"); } } @Override public void run() { try { DatagramPacket in = getPacket(); while(true) { recv(in); } } catch(InterruptedException ignore) { } catch(IOException e) { e.printStackTrace(); } }}The problem here is that the weak reference to the outbound connection appears to be the only thing keeping the outbound connection alive, according to the NetBeans reference tracker. I explicitly call System.gc() when I want to disconnect, and I even left the program running until the heap filled up with garbage and the garbage collector had to run. It just kept on printing "timeout" to indicate that it was still running.
First, System.gc() is no guarantee that the garbage collector will run. It's just like saying "if you don't mind, please collect some garbage" [grin].
Second, your thread doesn't have any exit criteria, so why should it stop?
This basically runs until an exception is thrown, but I guess the only exceptions that are thrown are SocketTimeoutException which you catch.
Second, your thread doesn't have any exit criteria, so why should it stop?
DatagramPacket in = getPacket();while(true) { recv(in);}This basically runs until an exception is thrown, but I guess the only exceptions that are thrown are SocketTimeoutException which you catch.
Quote:
Original post by Lord_Evil
First, System.gc() is no guarantee that the garbage collector will run. It's just like saying "if you don't mind, please collect some garbage" [grin].
What is a guarantee, though, is letting the heap fill with data. I'm sure the garbage collector did run. Besides, System.gc() is kind enough to oblige me when the heap is nearly empty, and I'm pretty sure System.gc() doesn't roll dice to determine whether to garbage collect, so it probably does run.
Quote:
Second, your thread doesn't have any exit criteria, so why should it stop?
If you read my entire class you'll see an InterruptedException thrown in getConnection() when the WeakReference no longer references anything.
Quote:
Original post by Dathgale Quote:
Original post by Lord_Evil
First, System.gc() is no guarantee that the garbage collector will run. It's just like saying "if you don't mind, please collect some garbage" [grin].
What is a guarantee, though, is letting the heap fill with data. I'm sure the garbage collector did run. Besides, System.gc() is kind enough to oblige me when the heap is nearly empty, and I'm pretty sure System.gc() doesn't roll dice to determine whether to garbage collect, so it probably does run.
Well, if you run out of memory the garbage collector will run and it even will probably run if you call System.gc(). BUT there's no guarantee of what objects it will collect and how much memory is freed. Note that the specification gives the implementors every freedom they want.
Garbage collection is just that - garbage collection. It should never be used to control program flow.
Quote:
Original post by Dathgale Quote:
Second, your thread doesn't have any exit criteria, so why should it stop?
If you read my entire class you'll see an InterruptedException thrown in getConnection() when the WeakReference no longer references anything.
While this is true, your connection might never be collected - see above.
Weak references are only collected if memory is required and the garbage collector has exhausted other options for collecting memory. Second, since your thread is still running it is holding onto the reference, so it won't be collected with normal garbage, but only if after collecting normal garbage the collector still needs more memory.
In any case as Lord_Evil said you should not rely on the garbage collector to control program flow.
In any case as Lord_Evil said you should not rely on the garbage collector to control program flow.
Quote:
Original post by CaptainJester
Weak references are only collected if memory is required and the garbage collector has exhausted other options for collecting memory.
No, that's how soft references normally function, though soft references are not required to behave differently than weak references, which are collected with completely unreachable objects.
However, given the hints in this thread, I was able to do some research. Apparently old objects are considered less frequently for garbage collection because there are fewer of them; it's normally more efficient to collect iterators, vectors, strings, and whatnot before considering collections and sockets.
Thank you.
This seems rather esoteric, though. Memory management IS program flow. It doesn't happen by magic; there's a thread in the background that decides how to perform garbage collection.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement