我有一个应用程序,它由服务器和客户端两部分组成。
它的工作原理如下:
客户端连接到服务器并发送字符串; server接收字符串并返回一个包含10000个元素的ArrayList(通过转换字符串)。
我编写了一个类(ClientConnector.java),它模拟许多客户端使用一个连接从服务器获取这些10000个元素。
当我运行这两个程序时,服务器端是可以的。但是在客户端,使用的堆总是在增加!我试图通过“null”释放使用过的对象,但是使用的内存仍然越来越大。
http://s10.postimage.org/egf4ugrd5/mem.png
我的服务器端代码: Client.java
public class Client {
private static final int PORT = 7571;
ClientHandler handler = new ClientHandler("hey");
IoConnector connector;
boolean available = true;
public synchronized void setAvailable(boolean available) {
this.available = available;
}
public synchronized boolean isAvailable() {
return available;
}
public void starter() throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
connector = new NioSocketConnector();
connector.getSessionConfig().setReadBufferSize(2048);
TextLineCodecFactory t = new TextLineCodecFactory(Charset.forName("UTF-8"));
t.setEncoderMaxLineLength(20 * 150000);
t.setDecoderMaxLineLength(20 * 150000);
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(t));
connector.setHandler(handler);
ConnectFuture future = connector.connect(new InetSocketAddress("localhost", PORT));
future.awaitUninterruptibly();
if (!future.isConnected()) {
return;
}
IoSession session = future.getSession();
session.getConfig().setUseReadOperation(true);
session.getCloseFuture().awaitUninterruptibly();
connector.dispose();
}
});
t.start();
Thread.sleep(300);
}
public void conClose() {
connector.dispose();
}
public ClientHandler getHandler() {
return handler;
}
public void reqInf() {
handler.reqInfo();
}
public static void main(String[] args) {
try {
Client c = new Client();
c.starter();
} catch (InterruptedException ex) {
System.out.println("error");
}
}
}
ClientHandler.java
公共类ClientHandler扩展了IoHandlerAdapter {
long time;
private final String values;
IoSession session;
public ClientHandler(String values) {
this.values = values;
}
@Override
public void sessionOpened(IoSession session) throws InterruptedException {
this.session = session;
}
public ArrayList<String> convert(String str) {
Gson gson = new Gson();
return gson.fromJson(str, ArrayList.class);
}
@Override
public void messageReceived(IoSession session, Object message) throws InterruptedException {
try {
ArrayList<String> test = convert(message.toString());
System.out.println("TIME : " + (System.currentTimeMillis() - time) + " strList:" + test.size());
message = null;
test = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
session.close();
System.out.println(cause.toString());
}
@Override
public void sessionClosed(IoSession session) {
System.out.println("Connection Lost");
}
public void reqInfo() {
time = System.currentTimeMillis();
session.write("test");
}
}
我的服务器端: Server.java
公共类服务器{
private static final int PORT = 7571; //TEST PORT
IoAcceptor acceptor = new NioSocketAcceptor();
public Server() throws IOException {
TextLineCodecFactory t = new TextLineCodecFactory(Charset.forName("UTF-8"));
t.setEncoderMaxLineLength(20*150000);
t.setDecoderMaxLineLength(20*150000);
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(t));
// acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool()));
Executor executor = new ThreadPoolExecutor(5, 70, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(executor));
acceptor.setHandler(new ServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1000);
//timer();
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("***Mina Server is ready !");
System.out.println("");
System.out.println("");
}
public static void main(String[] args) throws IOException {
Server m = new Server();
}
}
ServerHandler.java
公共类ServerHandler扩展了IoHandlerAdapter {
private final Logger logger = (Logger) LoggerFactory.getLogger(getClass());
IoSession sessions;
//Communication communication;
public ServerHandler() throws IOException {
loader();
// communication = new Communication(this);
}
@Override
public void sessionOpened(IoSession session) {
// set idle time to 10 seconds
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 1000);
System.out.println("Client Connected !!!");
//session.setAttribute("Values: ");
this.sessions = session;
}
public String toGSon(ArrayList<String> list) {
Gson gson = new Gson();
String str = gson.toJson(list);
return str;
}
ArrayList<String> str = new ArrayList<String>();
public void loader() {
for (int i = 0; i < 10000; i++) {
str.add("test" + i);
}
}
@Override
public void messageReceived(IoSession session, Object message) throws InterruptedException {
long time = System.currentTimeMillis();
session.write(toGSon(str));
System.out.println("TIME : " + (System.currentTimeMillis() - time));
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) {
System.out.println("Socket #" + session.getId() + " is disconnecting... (IDLE)");
session.close();
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("------------>" + cause.toString());
session.close();
}
}
我的主要课程
公共类ClientConnector {
public ClientConnector() throws InterruptedException {
Client cl = new Client();
cl.starter();
while (true) {
cl.reqInf();
Thread.sleep(100);
}
}
public static void main(String[] args) throws InterruptedException {
ClientConnector cl = new ClientConnector();
}
}
答案 0 :(得分:1)
我们的一位开发人员在Mina发现了一个问题,正在进行清理工作,并将修补程序应用于2.0.8版本。从今天开始这是“快照”,你必须从git中获取并自己构建它。这是从git获取它的命令:
git checkout 2.0
存储库uri:
git clone http://git-wip-us.apache.org/repos/asf/mina.git
答案 1 :(得分:0)
此代码不足以达到针对性的答案。
堆大小连续增加并且没有GC的影响 - >记忆泄漏的迹象。
可能你应该配置文件你的应用程序并使用一些OQL Tools来找出哪个类正在使用char[]
,这是查看你案例中堆转储的罪魁祸首< / p>
答案 2 :(得分:0)
您必须从客户端删除以下代码。
session.getConfig().setUseReadOperation(true);
上面的代码会导致内存泄漏。