Module java.base
Package java.lang

Class Runtime

java.lang.Object
java.lang.Runtime

public class Runtime extends Object
每个Java应用程序都有一个Runtime类的单个实例,允许应用程序与其运行环境进行交互。当前运行时可以通过getRuntime方法获取。

应用程序不能创建此类的自己的实例。

关闭序列

Java虚拟机响应以下事件之一而启动关闭序列

  1. 当非守护线程的数量首次降至零时(请参阅JNI调用API下面关于JNI调用API的注释);
  2. 当第一次调用Runtime.exitSystem.exit方法时;或
  3. 当发生某些外部事件,例如来自操作系统的中断或信号。

在关闭序列开始时,注册的关闭挂钩以某种未指定的顺序被启动。它们与在关闭序列开始时活动的任何守护线程或非守护线程并发运行。

关闭序列开始后,使用addShutdownHookremoveShutdownHook注册和注销关闭挂钩是被禁止的。但是,允许创建和启动新线程。新线程与注册的关闭挂钩以及已经运行的任何守护线程或非守护线程并发运行。

关闭序列在所有关闭挂钩终止时结束。此时,Java虚拟机将终止,如下所述。

可能有一个或多个关闭挂钩不会终止,例如由于无限循环。在这种情况下,关闭序列将永远不会结束。其他线程和关闭挂钩继续运行,并可以通过halt方法终止JVM。

在关闭序列开始之前,程序可以通过显式调用其start方法来启动关闭挂钩。如果发生这种情况,则关闭序列的行为是未指定的。

Java虚拟机终止

当关闭序列结束或调用halt时,JVM终止。与exit不同,halt方法不会启动关闭序列。

当JVM终止时,所有线程立即被阻止执行任何进一步的Java代码。这包括关闭挂钩以及守护线程和非守护线程。这意味着,例如:

  • 线程的当前方法不会正常或突然完成;
  • finally子句不会被执行;
  • 未捕获异常处理程序不会运行;以及
  • 使用try-with-resources打开的资源不会被关闭
实现注意事项:
本机代码通常使用JNI调用API来控制JVM的启动和终止。这样的本机代码调用JNI_CreateJavaVM函数来启动JVM。随后,本机代码调用DestroyJavaVM函数来等待该JVM的终止。当非守护线程的数量首次降至零时,DestroyJavaVM函数负责启动关闭序列。当关闭序列完成并JVM终止时,控制将返回调用DestroyJavaVM的本机代码。此行为与exithalt方法不同。这些方法通常终止托管JVM的操作系统进程,并且不与JNI调用API交互。
参见Java语言规范
12.8程序退出
自:
1.0
外部规范
另请参见:
  • Method Details

    • getRuntime

      public static Runtime getRuntime()
      返回与当前Java应用程序关联的运行时对象。类Runtime的大多数方法都是实例方法,必须相对于当前运行时对象调用。
      返回:
      与当前Java应用程序关联的Runtime对象。
    • exit

      public void exit(int status)
      启动Java虚拟机的关闭序列。除非安全管理器拒绝退出,否则此方法将启动关闭序列(如果尚未启动),然后无限期地阻塞。此方法既不返回也不抛出异常;也就是说,它既不正常完成也不突然完成。

      参数用作状态代码。按照惯例,非零状态代码表示异常终止。

      此方法的成功调用是串行化的,只有一个调用会启动关闭序列并使用给定状态代码终止VM。所有其他调用将不执行任何操作并无限期地阻塞。

      由于此方法的成功调用会无限期地阻塞,如果它是从关闭挂钩中调用的,它将阻止该关闭挂钩终止。因此,这将阻止关闭序列完成。

      System.exit方法是调用此方法的传统和便捷方式。

      实现注意事项:
      如果java.lang.Runtime系统记录器启用了日志级别Level.DEBUG,则会记录对Runtime.exit()的调用的堆栈跟踪。
      参数:
      status - 终止状态。按照惯例,非零状态代码表示异常终止。
      抛出:
      SecurityException - 如果存在安全管理器并且其checkExit方法不允许使用指定状态退出
      另请参见:
    • addShutdownHook

      public void addShutdownHook(Thread hook)
      注册一个新的虚拟机关闭挂钩。

      一个关闭挂钩只是一个已初始化但未启动的线程。关闭挂钩在关闭序列的开始时启动。一旦关闭序列开始,就不允许注册和注销关闭挂钩。

      未捕获的异常在关闭挂钩中处理,就像在任何其他线程中一样,如Thread.UncaughtExceptionHandler中指定的那样。在未捕获异常处理程序完成后,关闭挂钩被认为已终止,并且不会与没有抛出未捕获异常而终止的挂钩有任何不同对待。

      API 注意:
      关闭挂钩在虚拟机生命周期中运行的时间很微妙,因此应该进行防御性编码。它们应该特别编写为线程安全,并尽可能避免死锁。它们也不应该盲目依赖可能已经注册了自己的关闭挂钩的服务,因此它们本身可能正在关闭的过程中。尝试使用其他基于线程的服务,如AWT事件分派线程,例如,可能导致死锁。

      关闭挂钩应该快速完成它们的工作。当程序调用exit时,期望虚拟机将立即关闭并退出。当虚拟机由于用户注销或系统关闭而终止时,底层操作系统可能只允许有限的时间来关闭和退出。因此,在关闭挂钩中尝试进行任何用户交互或执行长时间运算是不明智的。

      参数:
      hook - 一个已初始化但未启动的Thread对象
      抛出:
      IllegalArgumentException - 如果与指定挂钩相同(使用==进行比较),已经注册了相同的挂钩,或者可以确定该挂钩已经在运行或已经运行过
      IllegalStateException - 如果关闭序列已经开始
      SecurityException - 如果存在安全管理器并且它拒绝RuntimePermission("shutdownHooks")
      自:
      1.3
      参见:
    • removeShutdownHook

      public boolean removeShutdownHook(Thread hook)
      注销先前注册的虚拟机关闭挂钩。挂钩使用==进行比较。一旦关闭序列开始,就不允许注册和注销关闭挂钩。
      参数:
      hook - 要移除的挂钩
      返回:
      如果指定的挂钩先前已注册并成功注销,则返回true,否则返回false
      抛出:
      IllegalStateException - 如果关闭序列已经开始
      SecurityException - 如果存在安全管理器并且它拒绝RuntimePermission("shutdownHooks")
      自:
      1.3
      参见:
    • halt

      public void halt(int status)
      立即终止Java虚拟机。如果安全管理器拒绝退出,则抛出SecurityException。否则,Java虚拟机的终止是无条件的和立即的。此方法不会启动关闭序列,也不会等待关闭序列完成(如果已经在进行中)。此方法的调用永远不会正常返回。
      API 注意:
      应该极度谨慎使用此方法。使用它可能规避或破坏关闭挂钩旨在执行的任何清理操作,可能导致数据损坏。请参阅上面的termination部分,了解停止Java虚拟机的其他可能后果。
      参数:
      status - 终止状态。按照惯例,非零状态码表示异常终止。如果已经调用了exit(等效地,System.exit)方法,则此状态码将覆盖传递给该方法的状态码。
      抛出:
      SecurityException - 如果存在安全管理器并且其checkExit方法不允许使用指定状态退出
      自:
      1.3
      参见:
    • exec

      @Deprecated(since="18") public Process exec(String command) throws IOException
      Deprecated.
      This method is error-prone and should not be used, the corresponding method exec(String[]) or ProcessBuilder should be used instead. The command string is broken into tokens using only whitespace characters. For an argument with an embedded space, such as a filename, this can cause problems as the token does not include the full filename.
      在单独的进程中执行指定的字符串命令。

      这是一个便利方法。形式为exec(command)的调用行为与调用exec(command, null, null)完全相同。

      实现注意:
      在参考实现中,可以启用创建进程的日志记录,请参阅ProcessBuilder.start()了解详情。
      参数:
      command - 指定的系统命令。
      返回:
      用于管理子进程的新Process对象
      抛出:
      SecurityException - 如果存在安全管理器并且其checkExec方法不允许创建子进程
      IOException - 如果发生I/O错误
      NullPointerException - 如果commandnull
      IllegalArgumentException - 如果command为空
      参见:
    • exec

      @Deprecated(since="18") public Process exec(String command, String[] envp) throws IOException
      Deprecated.
      This method is error-prone and should not be used, the corresponding method exec(String[], String[]) or ProcessBuilder should be used instead. The command string is broken into tokens using only whitespace characters. For an argument with an embedded space, such as a filename, this can cause problems as the token does not include the full filename.
      使用指定的环境在单独的进程中执行指定的字符串命令。

      这是一个便利方法。形式为exec(command, envp)的调用行为与调用exec(command, envp, null)完全相同。

      实现注意:
      在参考实现中,可以启用创建进程的日志记录,请参阅ProcessBuilder.start()了解详情。
      参数:
      command - 指定的系统命令。
      envp - 字符串数组,每个元素都以name=value的格式设置环境变量,如果子进程应继承当前进程的环境,则为null
      返回:
      用于管理子进程的新Process对象
      抛出:
      SecurityException - 如果存在安全管理器并且其checkExec方法不允许创建子进程
      IOException - 如果发生I/O错误
      NullPointerException - 如果commandnull,或者envp的一个元素为null
      IllegalArgumentException - 如果command为空
      参见:
    • exec

      @Deprecated(since="18") public Process exec(String command, String[] envp, File dir) throws IOException
      Deprecated.
      This method is error-prone and should not be used, the corresponding method exec(String[], String[], File) or ProcessBuilder should be used instead. The command string is broken into tokens using only whitespace characters. For an argument with an embedded space, such as a filename, this can cause problems as the token does not include the full filename.
      使用指定的环境和工作目录在单独的进程中执行指定的字符串命令。

      这是一个便利方法。形式为exec(command, envp, dir)的调用行为与调用exec(cmdarray, envp, dir)完全相同,其中cmdarraycommand中所有标记的数组。

      更准确地说,command字符串使用new StringTokenizer(command)创建的StringTokenizer分解为标记,没有对字符类别进行进一步修改。然后,标记由标记生成器产生的新字符串数组cmdarray按照相同顺序放置。

      实现注意事项:
      在参考实现中,可以启用创建进程的日志记录,请参阅 ProcessBuilder.start() 了解详情。
      参数:
      command - 指定的系统命令。
      envp - 字符串数组,每个元素都以 name=value 的格式设置环境变量,或者如果子进程应继承当前进程的环境,则为 null
      dir - 子进程的工作目录,或者如果子进程应继承当前进程的工作目录,则为 null
      返回:
      用于管理子进程的新 Process 对象
      抛出:
      SecurityException - 如果存在安全管理器且其 checkExec 方法不允许创建子进程
      IOException - 如果发生 I/O 错误
      NullPointerException - 如果 commandnull,或者 envp 的一个元素为 null
      IllegalArgumentException - 如果 command 为空
      自 JDK 版本:
      1.3
      参见:
    • exec

      public Process exec(String[] cmdarray) throws IOException
      在单独的进程中执行指定的命令和参数。

      这是一个便利方法。形式为 exec(cmdarray) 的调用行为与调用 exec(cmdarray, null, null) 完全相同。

      实现注意事项:
      在参考实现中,可以启用创建进程的日志记录,请参阅 ProcessBuilder.start() 了解详情。
      参数:
      cmdarray - 包含要调用的命令及其参数的数组。
      返回:
      用于管理子进程的新 Process 对象
      抛出:
      SecurityException - 如果存在安全管理器且其 checkExec 方法不允许创建子进程
      IOException - 如果发生 I/O 错误
      NullPointerException - 如果 cmdarraynull,或者 cmdarray 的一个元素为 null
      IndexOutOfBoundsException - 如果 cmdarray 是一个空数组(长度为 0
      参见:
    • exec

      public Process exec(String[] cmdarray, String[] envp) throws IOException
      在具有指定环境的单独进程中执行指定的命令和参数。

      这是一个便利方法。形式为 exec(cmdarray, envp) 的调用行为与调用 exec(cmdarray, envp, null) 完全相同。

      实现注意事项:
      在参考实现中,可以启用创建进程的日志记录,请参阅 ProcessBuilder.start() 了解详情。
      参数:
      cmdarray - 包含要调用的命令及其参数的数组。
      envp - 字符串数组,每个元素都以 name=value 的格式设置环境变量,或者如果子进程应继承当前进程的环境,则为 null
      返回:
      用于管理子进程的新 Process 对象
      抛出:
      SecurityException - 如果存在安全管理器且其 checkExec 方法不允许创建子进程
      IOException - 如果发生 I/O 错误
      NullPointerException - 如果 cmdarraynull,或者 cmdarray 的一个元素为 null,或者 envp 的一个元素为 null
      IndexOutOfBoundsException - 如果 cmdarray 是一个空数组(长度为 0)
      参见:
    • exec

      public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException
      在具有指定环境和工作目录的单独进程中执行指定的命令和参数。

      给定一个字符串数组 cmdarray,表示命令行的标记,以及一个字符串数组 envp,表示“环境”变量设置,此方法创建一个新进程来执行指定的命令。

      此方法检查 cmdarray 是否为有效的操作系统命令。哪些命令是有效的取决于系统,但至少命令必须是一个非空的非空字符串列表。

      如果 envpnull,则子进程将继承当前进程的环境设置。

      某些操作系统可能需要一组最小的系统相关环境变量才能启动进程。因此,子进程可能会继承除指定环境中的值之外的其他环境变量设置。最小的系统相关环境变量集可能会覆盖环境中提供的值。

      ProcessBuilder.start() 现在是启动具有修改环境的进程的首选方法。

      新子进程的工作目录由 dir 指定。如果 dirnull,则子进程将继承当前进程的当前工作目录。

      如果存在安全管理器,则将使用数组 cmdarray 的第一个组件作为其参数调用其 checkExec 方法。这可能导致抛出 SecurityException

      启动操作系统进程高度依赖于系统。可能出现的问题包括:

      • 未找到操作系统程序文件。
      • 拒绝访问程序文件。
      • 工作目录不存在。

      在这种情况下将抛出异常。异常的确切性质取决于系统,但它将始终是 IOException 的子类。

      如果操作系统不支持创建进程,则将抛出 UnsupportedOperationException

      实现注意事项:
      在参考实现中,可以启用创建进程的日志记录,请参阅 ProcessBuilder.start() 了解详情。
      参数:
      cmdarray - 包含要调用的命令及其参数的数组。
      envp - 字符串数组,每个元素都以 name=value 的格式设置环境变量,或者如果子进程应继承当前进程的环境,则为 null
      dir - 子进程的工作目录,或者如果子进程应继承当前进程的工作目录,则为 null
      返回:
      用于管理子进程的新 Process 对象
      抛出:
      SecurityException - 如果存在安全管理器且其 checkExec 方法不允许创建子进程
      UnsupportedOperationException - 如果操作系统不支持创建进程。
      IOException - 如果发生 I/O 错误
      NullPointerException - 如果 cmdarraynull,或者 cmdarray 的一个元素为 null,或者 envp 的一个元素为 null
      IndexOutOfBoundsException - 如果 cmdarray 是一个空数组(长度为 0)
      自 JDK 版本:
      1.3
      参见:
    • availableProcessors

      public int availableProcessors()
      返回 Java 虚拟机可用的处理器数量。

      此值在虚拟机的特定调用期间可能会更改。因此,对处理器数量敏感的应用程序应偶尔轮询此属性,并相应地调整其资源使用。

      返回:
      虚拟机可用的处理器数量的最大值;不会小于一
      自 JDK 版本:
      1.4
    • freeMemory

      public long freeMemory()
      返回 Java 虚拟机中的空闲内存量。调用 gc 方法可能会导致 freeMemory 返回值增加。
      返回:
      当前可用于未来分配对象的内存总量的近似值,以字节为单位。
    • totalMemory

      public long totalMemory()
      返回Java虚拟机中的总内存量。此方法返回的值可能随时间变化,取决于主机环境。

      请注意,持有任何给定类型对象所需的内存量可能取决于实现。

      返回:
      当前和未来对象可用的总内存量,以字节为单位。
    • maxMemory

      public long maxMemory()
      返回Java虚拟机将尝试使用的最大内存量。如果没有固有限制,则将返回值Long.MAX_VALUE
      返回:
      虚拟机将尝试使用的最大内存量,以字节为单位
      自:
      1.4
    • gc

      public void gc()
      在Java虚拟机中运行垃圾回收器。

      调用此方法表明Java虚拟机会努力回收未使用对象,以便使它们当前占用的内存可供Java虚拟机重用。当方法调用返回控制权时,Java虚拟机已尽最大努力从所有未使用对象中回收空间。不能保证此努力将回收任何特定数量的未使用对象,回收任何特定数量的空间,或在方法返回之前或之后的任何特定时间内完成,如果有的话。也不能保证此努力将确定任何特定数量对象的可达性变化,或者是否会清除和排队任何特定数量的Reference对象。

      名称gc代表“垃圾回收器”。Java虚拟机会根据需要自动在单独的线程中执行此回收过程,即使未显式调用gc方法。

      方法System.gc()是调用此方法的传统和便捷方式。

    • runFinalization

      @Deprecated(since="18", forRemoval=true) public void runFinalization()
      Deprecated, for removal: This API element is subject to removal in a future version.
      Finalization has been deprecated for removal. See Object.finalize() for background information and details about migration options.

      When running in a JVM in which finalization has been disabled or removed, no objects will be pending finalization, so this method does nothing.

      运行任何待终结的对象的终结方法。调用此方法表明Java虚拟机会努力运行已发现被丢弃但其终结方法尚未运行的对象的finalize方法。当方法调用返回控制权时,虚拟机已尽最大努力完成所有未完成的终结。

      虚拟机会根据需要自动执行终结过程,即使未显式调用runFinalization方法。

      方法System.runFinalization()是调用此方法的传统和便捷方式。

      参见Java语言规范
      12.6 类实例的终结
      另请参见:
    • load

      public void load(String filename)
      加载由文件名参数指定的本机库。文件名参数必须是绝对路径名(例如Runtime.getRuntime().load("/home/avh/lib/libX11.so");)。如果文件名参数在去除任何特定于平台的库前缀、路径和文件扩展名后指示一个名为L的库,且名为L的本机库已与VM静态链接,则将调用库导出的JNI_OnLoad_L函数,而不是尝试加载动态库。匹配参数的文件名不必存在于文件系统中。有关更多详细信息,请参阅JNI规范。否则,文件名参数将以实现相关的方式映射到本机库映像。

      首先,如果存在安全管理器,则将使用filename作为其参数调用其checkLink方法。这可能导致安全异常。

      这类似于方法loadLibrary(String),但它接受一个一般文件名作为参数,而不仅仅是一个库名,允许加载任何本机代码文件。

      方法System.load(String)是调用此方法的传统和便捷方式。

      参数:
      filename - 要加载的文件。
      抛出:
      SecurityException - 如果存在安全管理器且其checkLink方法不允许加载指定的动态库
      UnsatisfiedLinkError - 如果文件名不是绝对路径名、本机库未与VM静态链接,或主机系统无法将库映射到本机库映像。
      NullPointerException - 如果filenamenull
      外部规范
      另请参见:
    • loadLibrary

      public void loadLibrary(String libname)
      加载由libname参数指定的本机库。 libname参数不得包含任何特定于平台的前缀、文件扩展名或路径。如果名为libname的本机库已与VM静态链接,则将调用库导出的JNI_OnLoad_libname函数。有关更多详细信息,请参阅JNI规范。否则,将从系统库位置加载libname参数,并以实现相关的方式将其映射到本机库映像。

      首先,如果存在安全管理器,则将使用libname作为其参数调用其checkLink方法。这可能导致安全异常。

      方法System.loadLibrary(String)是调用此方法的传统和便捷方式。如果在类的实现中要使用本机方法,一个标准策略是将本机代码放在库文件中(称为LibFile),然后在类声明中放置一个静态初始化器:

       static { System.loadLibrary("LibFile"); }
       
      在加载和初始化类时,将加载所需的本机代码实现以用于本机方法。

      如果多次使用相同的库名称调用此方法,则会忽略第二次及后续调用。

      参数:
      libname - 库的名称。
      抛出:
      SecurityException - 如果存在安全管理器且其checkLink方法不允许加载指定的动态库
      UnsatisfiedLinkError - 如果libname参数包含文件路径、本机库未与VM静态链接,或主机系统无法将库映射到本机库映像。
      NullPointerException - 如果libnamenull
      外部规范
      另请参见:
    • version

      public static Runtime.Version version()
      返回Java运行时环境的版本作为Runtime.Version
      返回:
      Java运行时环境的Runtime.Version
      自:
      9