5

我正在努力从现有的 Java 代码库中删除所有系统调用。我们在商业提供的闭源 JVM 中运行我们的应用程序。当 JVM 通过 getRuntime.exec() 进行系统调用时,java 调用整个 JVM 进程分叉,这会导致严重的性能损失。我们在 linux 平台上运行,但理想情况下尽量保持可移植性。

我在替换我们当前通过 getRuntime.exec() 方法使用的 sync() 调用时遇到了问题。我知道还有这个sync() 方法和flush()。根据这篇文章,我希望对所有打开的文件流进行同步和刷新。

我的问题是我不直接知道那里有哪些文件流和描述符。我认为解决这个问题的一种方法是检查 /proc/(jvm 进程号)/fd 文件夹,但我找不到使用纯 java 可靠地获取 JVM 进程号的好方法。我认为我可能能够获取某个类(FileDescriptor 类)的所有对象,但从我正在阅读的内容来看,这也是不可行的。

有没有人有关于如何在纯 java 中复制 *nix sync() 调用的建议?

4

1 回答 1

4

你所做的不仅仅是一个电话sync。您正在尝试执行“刷新所有文件缓冲区和sync”操作。你在 C / C++ 中也很难做到这一点。

除了查找所有打开文件的问题(您可能可以解决......)之外,还有一个更大的问题;即是否是刷新缓冲区的正确时间。

假设您的应用程序是多线程的,并且一个线程负责调用sync. 该线程如何知道正在写入文件的其他线程已达到文件的一致点?即,如果应用程序被杀死并重新启动,(假设)刷新的文件将包含应用程序的逻辑一致状态?答案是(很可能)它知道。所以......事实上......如果应用程序在同步之前刷新,它并没有处于明显更好的位置。

还有另一个问题。假设线程 A 负责刷新/同步,而线程 B 正在愉快地写入某个输出流。考虑这个时间序列:

  1. 线程 A 刷新文件
  2. 线程 B 写入文件
  3. 线程 A 调用同步

避免这种情况的唯一方法是让线程 A 同步并阻止所有其他正在写入文件的线程......它执行刷新和同步之前。

我的建议是只进行同步,而忘记冲洗。以经典方式处理文件不一致的问题(通过让应用程序写入临时文件,并进行原子重命名),或者让同步线程与写入文件的线程协调......以便它仅在关键文件一致时“同步”。

于 2012-11-12T23:10:06.863 回答