Apache HttpAsyncClient中的文件描述符泄漏

时间:2014-05-31 04:47:15

标签: java nio apache-httpclient-4.x file-descriptor resource-leak

在Linux上运行时(仅在Linux上运行),根据lsof,以下代码似乎泄漏了1个anon_inode和2个管道文件描述符:

CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
client.close();

但是,如果client.execute()被调用一次或多次,则不会发生泄漏。

CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
client.execute(new HttpGet("http://stackoverflow.com/questions/23966483"), null);
client.close();

完整的示例代码:

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ExecutionException;

public class Benchmark {

    public static void main(String[] args) throws ExecutionException, InterruptedException, IOException  {
        printFileDescriptorCounts();
        for(int i = 0; i < 20; i++) {
            CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
            client.start();
            //client.execute(new HttpGet("http://stackoverflow.com/questions/23966483"), null);
            client.close();
            printFileDescriptorCounts();
        }
    }

    // not portable -- Linux only
    private static void printFileDescriptorCounts() throws IOException {
        String processId = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        String cmd = String.format("lsof -p %s | grep 'anon_inode\\|pipe' | awk '{ print $NF; }' | sort | uniq -c", processId);
        Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        try {
            for(String line; (line = br.readLine()) != null; ) {
                System.out.print(line.replace("\n", "\t"));
            }
            System.out.println();
        } finally {
            br.close();
            process.destroy();
        }
    }

}

我看到了

  3 pipe
  1 anon_inode      5 pipe
  2 anon_inode      7 pipe
  3 anon_inode      9 pipe
  4 anon_inode     11 pipe
  5 anon_inode     13 pipe
  6 anon_inode     15 pipe
  7 anon_inode     17 pipe
  8 anon_inode     19 pipe
  9 anon_inode     21 pipe
 10 anon_inode     23 pipe
 11 anon_inode     25 pipe
 12 anon_inode     27 pipe
 13 anon_inode     29 pipe
 14 anon_inode     31 pipe
 15 anon_inode     33 pipe
 16 anon_inode     35 pipe
 17 anon_inode     37 pipe
 18 anon_inode     39 pipe
 19 anon_inode     41 pipe
 20 anon_inode     43 pipe

如果我取消注释execute行,则泄漏消失。

  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe

(1)是预期/预期的行为,还是这个错误?

(2)为什么/如何发生?

1 个答案:

答案 0 :(得分:1)

它看起来像I / O反应器状态管理逻辑中的缺陷。请在项目中提出JIRA。

https://issues.apache.org/jira/browse/HTTPCORE