使用我的服务器应用程序,我使用WeakReferences列表来保持计数并处理到服务器的活动会话。我正在运行定期gc来清理非活动会话列表,但由于某种原因,始终会保留一个引用。根据重写的finalize方法,这是最后创建的会话。
我对为什么会发生这种情况一无所知。我首先想到这可能是由于静态方法或变量,但是现在我已经从ClientHandlerThread类中删除了这些对象。服务器类没有其他引用,但弱引用列表。目前这对我来说不是一个大问题,但是为了更好地理解java如何选择垃圾收集对象将来会有用。 :)以下是最重要的代码片段:
Server.java:
public class Server {
private List<WeakReference<ClientHandlerThread>> m_connectedClients =
Collections.synchronizedList(
new ArrayList<WeakReference<ClientHandlerThread>>());
/** Counter to identify sessions */
private static AtomicInteger m_NumSession = new AtomicInteger(0);
Server() {
SSLServerSocket sslDataTraffic = null;
// Sockets are initialized here - code removed for clarity
// Run periodic GC
Thread stThread = new Thread() {
public void run() {
do {
try {
Thread.sleep(5000);
}
catch (InterruptedException ignore) {}
System.runFinalization();
System.gc();
cleanUpSessionsList();
} while (true);
}
};
stThread.setPriority(Thread.MIN_PRIORITY);
stThread.start();
// Listen to new connections, create handlers and add to list
while (true) {
try {
SSLSocket sslDataTrafficSocketInstance =
(SSLSocket) sslDataTraffic.accept();
ClientHandlerThread c = new ClientHandlerThread(
sslDataTrafficSocketInstance,
m_NumSession.incrementAndGet());
c.start();
m_connectedClients.add(new WeakReference<>(c));
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** Clean any old references and return the number of active connections
* @return
*/
public int cleanUpSessionList() {
int i = 0;
synchronized(m_connectedClients) {
Iterator<WeakReference<ClientHandlerThread>> it =
m_connectedClients.iterator();
while (it.hasNext()) {
WeakReference<ClientHandlerThread> sessionRef = it.next();
if (sessionRef.get() == null)
it.remove();
else
i++;
}
}
System.out.println("Active sessions: " + i");
return i;
}
}
ClientHandlerThread.java:
public class ClientHandlerThread extends Thread {
private int m_SessionID;
private SSLSocket dataSocket;
public ClientHandlerThread(
SSLSocket dataSocket,
int sessionID) {
this.dataSocket = dataSocket;
m_SessionID = sessionID;
}
public void run() {
// code removed
}
@Override
protected void finalize() throws Throwable {
System.out.println("Session " + m_SessionID + " finalized");
super.finalize();
}
}
答案 0 :(得分:0)
那是关于所有错误的(代码本身并不坏,但你做了很多我通常会避免的事情)。
In [14]: from itertools import product
In [15]: pd.DataFrame(list(product(df.name, df.number)), columns=df.columns)
Out[15]:
name number
0 a 2
1 a 1
2 b 2
3 b 1
代替ReferenceQueue
。finalize
代替弱,因为AFAICT不需要访问裁判。关于问题本身......不知道,但代码中可能存在阻止最后一个帖子被释放的东西。如已经建议的那样,执行堆快照,通过内存分析器运行它。
答案 1 :(得分:0)
我发布了related question后发现了这个问题作为交叉参考。
我没有关于为什么发生的答案,我认为应该没有,但是我可以告诉您什么我认为正在发生,并且我很好奇建议的解决方法是否会改变您所看到的行为。 (如果您仍然有代码,我知道这是一个老问题了。)
据我所知,JRE某种程度上维护了对最后创建的作用域变量的引用。通过将变量设置为null(或创建另一个新的,不相关的作用域变量),此问题就消失了。
是这样的:
ClientHandlerThread c = new ClientHandlerThread(
sslDataTrafficSocketInstance,
m_NumSession.incrementAndGet());
c.start();
m_connectedClients.add(new WeakReference<>(c));
c = null;
同样,我并不是说应该这样运行,而是从我在类似情况下所做的测试中得出的结论。