我正在开发一个管理数据库的应用程序。它被设计为服务器/客户端,服务器处理所有数据库的事务。
它有点像这样:
当客户端启动时,它会搜索套接字/端口,如果打开,服务器会启动一个新线程:
while (true) {
new Thread(new comm.Protocol(serverSocket.accept()).start();
}
进入线程后,服务器会创建所需的通信对象(ObjectInputStream
& ObjectOutputStream
),并等待客户端发送登录信息。收到后,服务器会尝试创建新连接:
Class.forName("com.mysql.jdbc.Driver");
connection=DriverManager.getConnection(dbName, username, password);
如果成功,它会保存连接并继续循环等待客户端的请求。与DTO进行通信,DTO包含客户端的请求类型和查询所需的数据对象。服务器获取DTO并切换请求类型,执行请求的查询。然后,它以Plain Old Java Object
的形式设置结果,该java.util.ArrayList<POJO-Typed-Object>
对查询表进行建模,或者在DTO上为多结查询设置PreparedStatements
并将其发送回客户端。
显然工作正常,经过一些查询后,特别是那些行数很多的服务器应用程序内存不足。
ResultSet
在使用后关闭,{{1}}也是如此,所以我不知道内存在哪里。
任何建议都将不胜感激。
答案 0 :(得分:2)
您的应用程序中可能存在内存泄漏。 要测试实际拥有内存的内容,可以使用这些选项启动Java程序
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="C:\"
程序崩溃后,您将在C:\驱动器中获得堆转储。 有几种工具可用于分析堆转储(取决于您正在使用的IDE)。 对于eclipse,您可以下载http://www.eclipse.org/mat/
解析heapDump后,您可以看到哪些对象占用了内存。
是的,只是旁注:你的每个客户的线程解决方案都无法扩展。我会重新设计这个架构。
答案 1 :(得分:1)
由于您提到OutOfMemoryError倾向于遵循大型结果集,因此我发现了两个潜在的内存问题:
ExecutorService java doc page有一个很好的例子,说明如何将线程池与服务器套接字结合使用。
我还推荐@Funtik在另一个答案中推荐的HeapDumpOnOutOfMemoryError和HeapDumpPath参数。
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="C:\"
答案 2 :(得分:0)
我获得OutOfMemoryError
的唯一原因是当我有一些查询时我没有用Cursor
关闭cursor.close();