无需系统调用的*nix sync()的Java实现

无需系统调用的*nix sync()的Java实现,java,system-calls,Java,System Calls,我正在努力从现有Java代码库中删除所有系统调用。我们在商业提供的封闭源代码JVM中运行应用程序。当JVM通过getRuntime.exec()java调用进行系统调用时,整个JVM进程会分叉,从而导致严重的性能问题。我们在linux平台上运行,但在理想情况下,尽量保持设备的可移植性 替换当前通过getRuntime.exec()方法使用的sync()调用时遇到问题。我知道还有sync()方法和。基于此,我希望与所有打开的文件流进行同步和刷新 我的问题是,我不知道有哪些文件流和描述符。我认为解决

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

替换当前通过getRuntime.exec()方法使用的sync()调用时遇到问题。我知道还有sync()方法和。基于此,我希望与所有打开的文件流进行同步和刷新

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

有人对如何在纯java中复制*nix sync()调用有什么建议吗?

您所做的不仅仅是
sync
调用。您正在尝试执行“刷新所有文件缓冲区并同步”操作。在C/C++中也有困难。 除了查找所有打开的文件的问题(您可能可以解决…),还有一个更大的问题;i、 e.是否是刷新缓冲区的正确时间

让我们假设您的应用程序是多线程的,一个线程负责调用
sync
。该线程如何知道正在写入文件的其他线程已达到文件的一致点;i、 e.如果应用程序被终止并重新启动,(假设)刷新的文件将包含应用程序的逻辑一致状态?答案是(很可能)它不知道。所以事实上如果应用程序在同步之前刷新,那么它的状态并没有明显改善

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

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


    我的建议是只做同步,忘记刷新。以经典的方式处理不一致文件的问题(通过让应用程序写入临时文件并进行原子重命名),或者让同步线程与写入文件的线程协调。。。因此,只有当关键文件一致时,它才会“同步”。

    造成性能问题的不是分叉,而是文件同步操作。如果你用另一种方式完全做到这一点,你仍然会遇到同样的问题。我还建议你使用下面的链接,它来自android开发者,但因为它是我们正在讨论的Linux/Java实现——它包含相关信息@对不起,我原来的帖子在这方面并不完全清楚。这个问题与这样一个事实有关,即在应用程序启动时,我们假定整个过程可能会被分叉,从而保留可用内存。这实际上会将可用内存减半,从而影响整体性能。@eharik-您根本不需要这样做,只需处理
    System.exec()
    。JVM将使用“vfork”而不是“fork”,并且一个“vfork”系统调用后跟一个“exec”系统调用进行最小的复制。@StephenC-这是真的吗?在这个问题上似乎存在一些分歧。在我们使用系统调用的JVM实现中,请尝试分配与父进程相同的内存量。我刚刚运行了一个简单的测试,其中我将超过50%的系统内存分配给了java进程,并运行了system.exec(),应用程序崩溃了。感谢您的输入。根据您的回答以及与团队成员的讨论,我认为调用线程需要提供文件流对象,并在适当的时候负责调用sync。正如您所指出的,从资源的角度来看,文件系统范围的同步是浪费的,从I/O完整性的角度来看,也是有问题的。