zoukankan      html  css  js  c++  java
  • java.lang.Process Pitfalls

    Recently, I used some method in java.lang.Process, and I meet some tricky problems, now leave some useful materials is used to review in the future.

    1.Description about Process in java document:

    public abstract class Process extends Object

    The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it. The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.

    The methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts. The created subprocess does not have its own terminal or console. All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream()getInputStream()getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

    The subprocess is not killed when there are no more references to the Process object, but rather the subprocess continues executing asynchronously.

    There is no requirement that a process represented by a Process object execute asynchronously or concurrently with respect to the Java process that owns the Process object.

    public abstract int waitFor() throws InterruptedException

    causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.

    2.Process.waitFor(), threads, and InputStreams (from stackoverflow)

    3.Five Common java.lang.Process Pitfalls

    by Kyle W. Cartmell on Jan.19, 2009, under Best PracticesJava

    The simplest way to call an external executable or shell script from Java is the creation of a Process via Runtime.exec or ProcessBuilder. Unfortunately there are several common traps that can cause code that works as expected for a single invocation of a small executable to do terrible things when repeatedly calling several complex external applications. In this article you will find explanations of five of the most common concerns along with strategies for handling such issues safely and effectively.

    Process.waitFor doesn’t have to return

    The Java 6 API documentation for Process.waitFor states that it “causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.” If an external process runs for three days then waitFor will happily block for three days. This is probably undesirable behavior in most applications.

    The best strategy for handling this situation is to kick off a thread just prior to calling waitFor that will interrupt the current thread after a suitable time period. TimerTask was designed for precisely this sort of situation, and waitFor is very responsive to interrupts in most cases. Click here for an example.

    There is some talk of adding a timeout interval directly to waitFor; see Sun bug 4890847 for more details.

    Process.waitFor does not clear thread interrupt flag when it throws InterruptedException

    By convention, methods that throw InterruptedException reset the thread interrupt flag. Unfortunately whoever implemented Process.waitFor didn’t get that memo. (See Sun bug 6420270) This is especially entertaining when a thread invokes multiple processes consecutively and calls waitFor for each of them; after one call to waitFor is interrupted, future calls to waitFor from the same thread will immediately throw InterruptedException until the interrupt flag is cleared.

    Process.waitFor should always be called from a try block whether InterruptedException is caught or not, with a corresponding finally block that calls Thread.interrupted to clear the interrupt flag.

    Process output must be promptly consumed

    This issue seems to come up in the Sun Java forums at least once a week. Runtime.exec is used to execute some command and it works sometimes but other times the process never terminates. The Java 6 API clearly states that failure to promptly “read the output stream of the subprocess may cause the subprocess to block, and even deadlock.”

    For any Process, the input and error streams must read even if the data written to these streams is not used by the application. The generally accepted solution for this problem is a stream gobbler thread that does nothing but consume data from an input stream until stopped. For more information regarding SteamGobblers, try Google!

    Process resources are not automatically freed until finalization

    When a Process is instantiated three streams are allocated to handle stdout, stderr, and stdin. These streams do not close on their own until the process object is finalized, which can often result in resource exhaustion. There are at least five different defects in the Sun bug database regarding this issue and several of them provide conflicting information regarding how to properly release system resources tied to an instance of Process.

    The safe bet for handling this problem today is to explicitly clean up every instance of Process by calling close on each stream made available through Process.getOutputSteam, Process.getInputStream, and Process.getErrorStream, and then call Process.destroy even if the process is already terminated.

    Process.destroy doesn’t kill process grandchildren

    If a Java application creates a subprocess which in turn creates its own subprocess and the Java application invokes Process.destroy, the grandchild process is not terminated. Sun is unlikely to ever “fix” this issue since there are so many different models for process handling in the various operating systems supported by Java. See Sun bug 4770092 for more details.

    This isn’t really a Java defect so much as a good example of why usage of Process needs to be carefully executed. It is fairly common to see code in commercial production applications that assume external processes will just “do the right thing” in every case. The developer has a responsibility to understand exactly how external processes work before invoking them to ensure that terrible problems do not emerge under unpredictable real world scenarios.

    Caveat Implementor

    java.lang.Process is a very complex module with a lot of moving parts that work well in most but not all situations. Sun notes in the Process API documentation that the “methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts.“ Products that rely on Process to deal with third-party code benefit greatly from extensive unit testing early on in the development process to ensure that “simple” problems such as those outlined above have been dealt with appropriately. Later on, thorough functional testing and load testing is extremely important to verify that the code is stable under stress and that the risk of wreaking havoc in a mission critical (or worse … multi-application) environment is minimized.

  • 相关阅读:
    让一个 csproj 项目指定多个开发框架
    推荐近乎免费的调试神器——OzCode
    再也不用克隆多个仓库啦!git worktree 一个 git 仓库可以连接多个工作目录
    .NET Core 和 .NET Framework 中的 MEF2
    将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件
    .NET 中的轻量级线程安全
    卡诺模型(KANO Model)
    C#/.NET 匿名函数会捕获变量,并延长对象的生命周期
    迫不及待地体验了一把 C#8.0 中的可空引用类型(Nullable Reference)
    异步任务中的重新进入(Reentrancy)
  • 原文地址:https://www.cnblogs.com/abnercai/p/2836008.html
Copyright © 2011-2022 走看看