【问题标题】:reduce number of opened files in java code减少java代码中打开文件的数量
【发布时间】:2011-05-24 15:11:55
【问题描述】:

您好,我有一些使用块的代码

RandomAccessFile file = new RandomAccessFile("some file", "rw");
FileChannel channel = file.getChannel();

// some code
String line = "some data";
ByteBuffer buf = ByteBuffer.wrap(line.getBytes());
channel.write(buf);

channel.close();
file.close();

但应用程序的具体情况是我必须生成大量临时文件,平均超过 4000 个(用于 Hive 插入分区表)。

问题是有时我会捕获异常

Failed with exception Too many open files

在应用程序运行期间。

如果有什么方法可以告诉操作系统该文件已经关闭并且不再使用,我会问为什么

channel.close();
file.close();

不会减少打开文件的数量。有没有办法在 Java 代码中做到这一点?

我已经增加了打开文件的最大数量

#/etc/sysctl.conf:
kern.maxfiles=204800
kern.maxfilesperproc=200000
kern.ipc.somaxconn=8096

更新: 我试图消除这个问题,所以我分开了代码来调查它的每一部分(创建文件、上传到配置单元、删除文件)。

使用类 'File' 或 'RandomAccessFile' 失败,出现“打开的文件太多”异常。

最后我使用了代码:

FileOutputStream s = null;
FileChannel c = null;

try {
    s = new FileOutputStream(filePath);
    c = s.getChannel();
    // do writes
    c.write("some data"); 
    c.force(true);
    s.getFD().sync();

} catch (IOException e) {
    // handle exception
} finally {
    if (c != null)
        c.close();
    if (s != null)
        s.close();
}

这适用于大量文件(在 20K 上测试,每个 5KB 大小)。代码本身不会像前两个类那样抛出异常。 但是生产代码(带有配置单元)仍然有例外。看来,通过 JDBC 的配置单元连接是它的原因。 我会进一步调查。

【问题讨论】:

  • 听起来有些东西依赖终结器来关闭外部资源。那是……真是自找麻烦。

标签: java io java-io


【解决方案1】:

操作系统可以使用的打开文件句柄的数量与进程可以打开的文件句柄的数量不同。大多数 unix 系统限制每个进程的文件句柄数。很可能它类似于 JVM 的 1024 个文件句柄。

a) 您需要将启动 JVM 的 shell 中的 ulimit 设置为更高的值。 (类似'ulimit -n 4000')

b) 您应该确认您没有任何资源泄漏导致您的文件无法“完成”。

【讨论】:

    【解决方案2】:

    确保使用 finally{} 块。如果由于某种原因出现异常,则在编写的代码中将永远不会发生关闭。

    【讨论】:

      【解决方案3】:

      这是确切的代码吗?因为我可以想到一种情况,您可能会在循环中打开所有文件并编写代码以最终关闭所有文件,这会导致此问题。请发布完整代码。

      【讨论】:

      • 使用模式如下:1)从mysql源获取数据到一些数据对象2)循环对象列表并在每次迭代中执行发布的代码。所以我在每次迭代中都会发布代码和平,并且不会将所有文件都打开一次。
      猜你喜欢
      • 2020-06-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 2018-12-08
      • 2015-07-03
      • 2012-04-27
      • 2020-03-27
      • 1970-01-01
      相关资源
      最近更新 更多