1 /*
   2  * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.io.*;
  29 import java.math.BigInteger;
  30 import java.util.AbstractList;
  31 import java.util.Arrays;
  32 import java.util.ArrayList;
  33 import java.util.regex.Matcher;
  34 import java.util.regex.Pattern;
  35 import java.util.stream.Collectors;
  36 import java.util.Collections;
  37 import java.util.List;
  38 import java.util.Optional;
  39 import java.util.RandomAccess;
  40 import java.util.StringTokenizer;
  41 import jdk.internal.reflect.CallerSensitive;
  42 import jdk.internal.reflect.Reflection;
  43 import sun.security.action.GetPropertyAction;
  44 
  45 /**
  46  * Every Java application has a single instance of class
  47  * {@code Runtime} that allows the application to interface with
  48  * the environment in which the application is running. The current
  49  * runtime can be obtained from the {@code getRuntime} method.
  50  * <p>
  51  * An application cannot create its own instance of this class.
  52  *
  53  * @author  unascribed
  54  * @see     java.lang.Runtime#getRuntime()
  55  * @since   1.0
  56  */
  57 
  58 public class Runtime {
  59     private static final Runtime currentRuntime = new Runtime();
  60 
  61     private static Version version;
  62 
  63     /**
  64      * Returns the runtime object associated with the current Java application.
  65      * Most of the methods of class {@code Runtime} are instance
  66      * methods and must be invoked with respect to the current runtime object.
  67      *
  68      * @return  the {@code Runtime} object associated with the current
  69      *          Java application.
  70      */
  71     public static Runtime getRuntime() {
  72         return currentRuntime;
  73     }
  74 
  75     /** Don't let anyone else instantiate this class */
  76     private Runtime() {}
  77 
  78     /**
  79      * Terminates the currently running Java virtual machine by initiating its
  80      * shutdown sequence.  This method never returns normally.  The argument
  81      * serves as a status code; by convention, a nonzero status code indicates
  82      * abnormal termination.
  83      *
  84      * <p> The virtual machine's shutdown sequence consists of two phases.  In
  85      * the first phase all registered {@link #addShutdownHook shutdown hooks},
  86      * if any, are started in some unspecified order and allowed to run
  87      * concurrently until they finish.  In the second phase all uninvoked
  88      * finalizers are run if {@link #runFinalizersOnExit finalization-on-exit}
  89      * has been enabled.  Once this is done the virtual machine {@link #halt halts}.
  90      *
  91      * <p> If this method is invoked after the virtual machine has begun its
  92      * shutdown sequence then if shutdown hooks are being run this method will
  93      * block indefinitely.  If shutdown hooks have already been run and on-exit
  94      * finalization has been enabled then this method halts the virtual machine
  95      * with the given status code if the status is nonzero; otherwise, it
  96      * blocks indefinitely.
  97      *
  98      * <p> The {@link System#exit(int) System.exit} method is the
  99      * conventional and convenient means of invoking this method.
 100      *
 101      * @param  status
 102      *         Termination status.  By convention, a nonzero status code
 103      *         indicates abnormal termination.
 104      *
 105      * @throws SecurityException
 106      *         If a security manager is present and its
 107      *         {@link SecurityManager#checkExit checkExit} method does not permit
 108      *         exiting with the specified status
 109      *
 110      * @see java.lang.SecurityException
 111      * @see java.lang.SecurityManager#checkExit(int)
 112      * @see #addShutdownHook
 113      * @see #removeShutdownHook
 114      * @see #runFinalizersOnExit
 115      * @see #halt(int)
 116      */
 117     public void exit(int status) {
 118         SecurityManager security = System.getSecurityManager();
 119         if (security != null) {
 120             security.checkExit(status);
 121         }
 122         Shutdown.exit(status);
 123     }
 124 
 125     /**
 126      * Registers a new virtual-machine shutdown hook.
 127      *
 128      * <p> The Java virtual machine <i>shuts down</i> in response to two kinds
 129      * of events:
 130      *
 131      *   <ul>
 132      *
 133      *   <li> The program <i>exits</i> normally, when the last non-daemon
 134      *   thread exits or when the {@link #exit exit} (equivalently,
 135      *   {@link System#exit(int) System.exit}) method is invoked, or
 136      *
 137      *   <li> The virtual machine is <i>terminated</i> in response to a
 138      *   user interrupt, such as typing {@code ^C}, or a system-wide event,
 139      *   such as user logoff or system shutdown.
 140      *
 141      *   </ul>
 142      *
 143      * <p> A <i>shutdown hook</i> is simply an initialized but unstarted
 144      * thread.  When the virtual machine begins its shutdown sequence it will
 145      * start all registered shutdown hooks in some unspecified order and let
 146      * them run concurrently.  When all the hooks have finished it will then
 147      * run all uninvoked finalizers if finalization-on-exit has been enabled.
 148      * Finally, the virtual machine will halt.  Note that daemon threads will
 149      * continue to run during the shutdown sequence, as will non-daemon threads
 150      * if shutdown was initiated by invoking the {@link #exit exit} method.
 151      *
 152      * <p> Once the shutdown sequence has begun it can be stopped only by
 153      * invoking the {@link #halt halt} method, which forcibly
 154      * terminates the virtual machine.
 155      *
 156      * <p> Once the shutdown sequence has begun it is impossible to register a
 157      * new shutdown hook or de-register a previously-registered hook.
 158      * Attempting either of these operations will cause an
 159      * {@link IllegalStateException} to be thrown.
 160      *
 161      * <p> Shutdown hooks run at a delicate time in the life cycle of a virtual
 162      * machine and should therefore be coded defensively.  They should, in
 163      * particular, be written to be thread-safe and to avoid deadlocks insofar
 164      * as possible.  They should also not rely blindly upon services that may
 165      * have registered their own shutdown hooks and therefore may themselves in
 166      * the process of shutting down.  Attempts to use other thread-based
 167      * services such as the AWT event-dispatch thread, for example, may lead to
 168      * deadlocks.
 169      *
 170      * <p> Shutdown hooks should also finish their work quickly.  When a
 171      * program invokes {@link #exit exit} the expectation is
 172      * that the virtual machine will promptly shut down and exit.  When the
 173      * virtual machine is terminated due to user logoff or system shutdown the
 174      * underlying operating system may only allow a fixed amount of time in
 175      * which to shut down and exit.  It is therefore inadvisable to attempt any
 176      * user interaction or to perform a long-running computation in a shutdown
 177      * hook.
 178      *
 179      * <p> Uncaught exceptions are handled in shutdown hooks just as in any
 180      * other thread, by invoking the
 181      * {@link ThreadGroup#uncaughtException uncaughtException} method of the
 182      * thread's {@link ThreadGroup} object. The default implementation of this
 183      * method prints the exception's stack trace to {@link System#err} and
 184      * terminates the thread; it does not cause the virtual machine to exit or
 185      * halt.
 186      *
 187      * <p> In rare circumstances the virtual machine may <i>abort</i>, that is,
 188      * stop running without shutting down cleanly.  This occurs when the
 189      * virtual machine is terminated externally, for example with the
 190      * {@code SIGKILL} signal on Unix or the {@code TerminateProcess} call on
 191      * Microsoft Windows.  The virtual machine may also abort if a native
 192      * method goes awry by, for example, corrupting internal data structures or
 193      * attempting to access nonexistent memory.  If the virtual machine aborts
 194      * then no guarantee can be made about whether or not any shutdown hooks
 195      * will be run.
 196      *
 197      * @param   hook
 198      *          An initialized but unstarted {@link Thread} object
 199      *
 200      * @throws  IllegalArgumentException
 201      *          If the specified hook has already been registered,
 202      *          or if it can be determined that the hook is already running or
 203      *          has already been run
 204      *
 205      * @throws  IllegalStateException
 206      *          If the virtual machine is already in the process
 207      *          of shutting down
 208      *
 209      * @throws  SecurityException
 210      *          If a security manager is present and it denies
 211      *          {@link RuntimePermission}("shutdownHooks")
 212      *
 213      * @see #removeShutdownHook
 214      * @see #halt(int)
 215      * @see #exit(int)
 216      * @since 1.3
 217      */
 218     public void addShutdownHook(Thread hook) {
 219         SecurityManager sm = System.getSecurityManager();
 220         if (sm != null) {
 221             sm.checkPermission(new RuntimePermission("shutdownHooks"));
 222         }
 223         ApplicationShutdownHooks.add(hook);
 224     }
 225 
 226     /**
 227      * De-registers a previously-registered virtual-machine shutdown hook.
 228      *
 229      * @param hook the hook to remove
 230      * @return {@code true} if the specified hook had previously been
 231      * registered and was successfully de-registered, {@code false}
 232      * otherwise.
 233      *
 234      * @throws  IllegalStateException
 235      *          If the virtual machine is already in the process of shutting
 236      *          down
 237      *
 238      * @throws  SecurityException
 239      *          If a security manager is present and it denies
 240      *          {@link RuntimePermission}("shutdownHooks")
 241      *
 242      * @see #addShutdownHook
 243      * @see #exit(int)
 244      * @since 1.3
 245      */
 246     public boolean removeShutdownHook(Thread hook) {
 247         SecurityManager sm = System.getSecurityManager();
 248         if (sm != null) {
 249             sm.checkPermission(new RuntimePermission("shutdownHooks"));
 250         }
 251         return ApplicationShutdownHooks.remove(hook);
 252     }
 253 
 254     /**
 255      * Forcibly terminates the currently running Java virtual machine.  This
 256      * method never returns normally.
 257      *
 258      * <p> This method should be used with extreme caution.  Unlike the
 259      * {@link #exit exit} method, this method does not cause shutdown
 260      * hooks to be started and does not run uninvoked finalizers if
 261      * finalization-on-exit has been enabled.  If the shutdown sequence has
 262      * already been initiated then this method does not wait for any running
 263      * shutdown hooks or finalizers to finish their work.
 264      *
 265      * @param  status
 266      *         Termination status. By convention, a nonzero status code
 267      *         indicates abnormal termination. If the {@link Runtime#exit exit}
 268      *         (equivalently, {@link System#exit(int) System.exit}) method
 269      *         has already been invoked then this status code
 270      *         will override the status code passed to that method.
 271      *
 272      * @throws SecurityException
 273      *         If a security manager is present and its
 274      *         {@link SecurityManager#checkExit checkExit} method
 275      *         does not permit an exit with the specified status
 276      *
 277      * @see #exit
 278      * @see #addShutdownHook
 279      * @see #removeShutdownHook
 280      * @since 1.3
 281      */
 282     public void halt(int status) {
 283         SecurityManager sm = System.getSecurityManager();
 284         if (sm != null) {
 285             sm.checkExit(status);
 286         }
 287         Shutdown.halt(status);
 288     }
 289 
 290     /**
 291      * Enable or disable finalization on exit; doing so specifies that the
 292      * finalizers of all objects that have finalizers that have not yet been
 293      * automatically invoked are to be run before the Java runtime exits.
 294      * By default, finalization on exit is disabled.
 295      *
 296      * <p>If there is a security manager,
 297      * its {@code checkExit} method is first called
 298      * with 0 as its argument to ensure the exit is allowed.
 299      * This could result in a SecurityException.
 300      *
 301      * @param value true to enable finalization on exit, false to disable
 302      * @deprecated  This method is inherently unsafe.  It may result in
 303      *      finalizers being called on live objects while other threads are
 304      *      concurrently manipulating those objects, resulting in erratic
 305      *      behavior or deadlock.
 306      *      This method is subject to removal in a future version of Java SE.
 307      *
 308      * @throws  SecurityException
 309      *        if a security manager exists and its {@code checkExit}
 310      *        method doesn't allow the exit.
 311      *
 312      * @see     java.lang.Runtime#exit(int)
 313      * @see     java.lang.Runtime#gc()
 314      * @see     java.lang.SecurityManager#checkExit(int)
 315      * @since   1.1
 316      */
 317     @Deprecated(since="1.2", forRemoval=true)
 318     public static void runFinalizersOnExit(boolean value) {
 319         SecurityManager security = System.getSecurityManager();
 320         if (security != null) {
 321             try {
 322                 security.checkExit(0);
 323             } catch (SecurityException e) {
 324                 throw new SecurityException("runFinalizersOnExit");
 325             }
 326         }
 327         Shutdown.setRunFinalizersOnExit(value);
 328     }
 329 
 330     /**
 331      * Executes the specified string command in a separate process.
 332      *
 333      * <p>This is a convenience method.  An invocation of the form
 334      * {@code exec(command)}
 335      * behaves in exactly the same way as the invocation
 336      * {@link #exec(String, String[], File) exec}{@code (command, null, null)}.
 337      *
 338      * @param   command   a specified system command.
 339      *
 340      * @return  A new {@link Process} object for managing the subprocess
 341      *
 342      * @throws  SecurityException
 343      *          If a security manager exists and its
 344      *          {@link SecurityManager#checkExec checkExec}
 345      *          method doesn't allow creation of the subprocess
 346      *
 347      * @throws  IOException
 348      *          If an I/O error occurs
 349      *
 350      * @throws  NullPointerException
 351      *          If {@code command} is {@code null}
 352      *
 353      * @throws  IllegalArgumentException
 354      *          If {@code command} is empty
 355      *
 356      * @see     #exec(String[], String[], File)
 357      * @see     ProcessBuilder
 358      */
 359     public Process exec(String command) throws IOException {
 360         return exec(command, null, null);
 361     }
 362 
 363     /**
 364      * Executes the specified string command in a separate process with the
 365      * specified environment.
 366      *
 367      * <p>This is a convenience method.  An invocation of the form
 368      * {@code exec(command, envp)}
 369      * behaves in exactly the same way as the invocation
 370      * {@link #exec(String, String[], File) exec}{@code (command, envp, null)}.
 371      *
 372      * @param   command   a specified system command.
 373      *
 374      * @param   envp      array of strings, each element of which
 375      *                    has environment variable settings in the format
 376      *                    <i>name</i>=<i>value</i>, or
 377      *                    {@code null} if the subprocess should inherit
 378      *                    the environment of the current process.
 379      *
 380      * @return  A new {@link Process} object for managing the subprocess
 381      *
 382      * @throws  SecurityException
 383      *          If a security manager exists and its
 384      *          {@link SecurityManager#checkExec checkExec}
 385      *          method doesn't allow creation of the subprocess
 386      *
 387      * @throws  IOException
 388      *          If an I/O error occurs
 389      *
 390      * @throws  NullPointerException
 391      *          If {@code command} is {@code null},
 392      *          or one of the elements of {@code envp} is {@code null}
 393      *
 394      * @throws  IllegalArgumentException
 395      *          If {@code command} is empty
 396      *
 397      * @see     #exec(String[], String[], File)
 398      * @see     ProcessBuilder
 399      */
 400     public Process exec(String command, String[] envp) throws IOException {
 401         return exec(command, envp, null);
 402     }
 403 
 404     /**
 405      * Executes the specified string command in a separate process with the
 406      * specified environment and working directory.
 407      *
 408      * <p>This is a convenience method.  An invocation of the form
 409      * {@code exec(command, envp, dir)}
 410      * behaves in exactly the same way as the invocation
 411      * {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, dir)},
 412      * where {@code cmdarray} is an array of all the tokens in
 413      * {@code command}.
 414      *
 415      * <p>More precisely, the {@code command} string is broken
 416      * into tokens using a {@link StringTokenizer} created by the call
 417      * {@code new {@link StringTokenizer}(command)} with no
 418      * further modification of the character categories.  The tokens
 419      * produced by the tokenizer are then placed in the new string
 420      * array {@code cmdarray}, in the same order.
 421      *
 422      * @param   command   a specified system command.
 423      *
 424      * @param   envp      array of strings, each element of which
 425      *                    has environment variable settings in the format
 426      *                    <i>name</i>=<i>value</i>, or
 427      *                    {@code null} if the subprocess should inherit
 428      *                    the environment of the current process.
 429      *
 430      * @param   dir       the working directory of the subprocess, or
 431      *                    {@code null} if the subprocess should inherit
 432      *                    the working directory of the current process.
 433      *
 434      * @return  A new {@link Process} object for managing the subprocess
 435      *
 436      * @throws  SecurityException
 437      *          If a security manager exists and its
 438      *          {@link SecurityManager#checkExec checkExec}
 439      *          method doesn't allow creation of the subprocess
 440      *
 441      * @throws  IOException
 442      *          If an I/O error occurs
 443      *
 444      * @throws  NullPointerException
 445      *          If {@code command} is {@code null},
 446      *          or one of the elements of {@code envp} is {@code null}
 447      *
 448      * @throws  IllegalArgumentException
 449      *          If {@code command} is empty
 450      *
 451      * @see     ProcessBuilder
 452      * @since 1.3
 453      */
 454     public Process exec(String command, String[] envp, File dir)
 455         throws IOException {
 456         if (command.length() == 0)
 457             throw new IllegalArgumentException("Empty command");
 458 
 459         StringTokenizer st = new StringTokenizer(command);
 460         String[] cmdarray = new String[st.countTokens()];
 461         for (int i = 0; st.hasMoreTokens(); i++)
 462             cmdarray[i] = st.nextToken();
 463         return exec(cmdarray, envp, dir);
 464     }
 465 
 466     /**
 467      * Executes the specified command and arguments in a separate process.
 468      *
 469      * <p>This is a convenience method.  An invocation of the form
 470      * {@code exec(cmdarray)}
 471      * behaves in exactly the same way as the invocation
 472      * {@link #exec(String[], String[], File) exec}{@code (cmdarray, null, null)}.
 473      *
 474      * @param   cmdarray  array containing the command to call and
 475      *                    its arguments.
 476      *
 477      * @return  A new {@link Process} object for managing the subprocess
 478      *
 479      * @throws  SecurityException
 480      *          If a security manager exists and its
 481      *          {@link SecurityManager#checkExec checkExec}
 482      *          method doesn't allow creation of the subprocess
 483      *
 484      * @throws  IOException
 485      *          If an I/O error occurs
 486      *
 487      * @throws  NullPointerException
 488      *          If {@code cmdarray} is {@code null},
 489      *          or one of the elements of {@code cmdarray} is {@code null}
 490      *
 491      * @throws  IndexOutOfBoundsException
 492      *          If {@code cmdarray} is an empty array
 493      *          (has length {@code 0})
 494      *
 495      * @see     ProcessBuilder
 496      */
 497     public Process exec(String cmdarray[]) throws IOException {
 498         return exec(cmdarray, null, null);
 499     }
 500 
 501     /**
 502      * Executes the specified command and arguments in a separate process
 503      * with the specified environment.
 504      *
 505      * <p>This is a convenience method.  An invocation of the form
 506      * {@code exec(cmdarray, envp)}
 507      * behaves in exactly the same way as the invocation
 508      * {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, null)}.
 509      *
 510      * @param   cmdarray  array containing the command to call and
 511      *                    its arguments.
 512      *
 513      * @param   envp      array of strings, each element of which
 514      *                    has environment variable settings in the format
 515      *                    <i>name</i>=<i>value</i>, or
 516      *                    {@code null} if the subprocess should inherit
 517      *                    the environment of the current process.
 518      *
 519      * @return  A new {@link Process} object for managing the subprocess
 520      *
 521      * @throws  SecurityException
 522      *          If a security manager exists and its
 523      *          {@link SecurityManager#checkExec checkExec}
 524      *          method doesn't allow creation of the subprocess
 525      *
 526      * @throws  IOException
 527      *          If an I/O error occurs
 528      *
 529      * @throws  NullPointerException
 530      *          If {@code cmdarray} is {@code null},
 531      *          or one of the elements of {@code cmdarray} is {@code null},
 532      *          or one of the elements of {@code envp} is {@code null}
 533      *
 534      * @throws  IndexOutOfBoundsException
 535      *          If {@code cmdarray} is an empty array
 536      *          (has length {@code 0})
 537      *
 538      * @see     ProcessBuilder
 539      */
 540     public Process exec(String[] cmdarray, String[] envp) throws IOException {
 541         return exec(cmdarray, envp, null);
 542     }
 543 
 544 
 545     /**
 546      * Executes the specified command and arguments in a separate process with
 547      * the specified environment and working directory.
 548      *
 549      * <p>Given an array of strings {@code cmdarray}, representing the
 550      * tokens of a command line, and an array of strings {@code envp},
 551      * representing "environment" variable settings, this method creates
 552      * a new process in which to execute the specified command.
 553      *
 554      * <p>This method checks that {@code cmdarray} is a valid operating
 555      * system command.  Which commands are valid is system-dependent,
 556      * but at the very least the command must be a non-empty list of
 557      * non-null strings.
 558      *
 559      * <p>If {@code envp} is {@code null}, the subprocess inherits the
 560      * environment settings of the current process.
 561      *
 562      * <p>A minimal set of system dependent environment variables may
 563      * be required to start a process on some operating systems.
 564      * As a result, the subprocess may inherit additional environment variable
 565      * settings beyond those in the specified environment.
 566      *
 567      * <p>{@link ProcessBuilder#start()} is now the preferred way to
 568      * start a process with a modified environment.
 569      *
 570      * <p>The working directory of the new subprocess is specified by {@code dir}.
 571      * If {@code dir} is {@code null}, the subprocess inherits the
 572      * current working directory of the current process.
 573      *
 574      * <p>If a security manager exists, its
 575      * {@link SecurityManager#checkExec checkExec}
 576      * method is invoked with the first component of the array
 577      * {@code cmdarray} as its argument. This may result in a
 578      * {@link SecurityException} being thrown.
 579      *
 580      * <p>Starting an operating system process is highly system-dependent.
 581      * Among the many things that can go wrong are:
 582      * <ul>
 583      * <li>The operating system program file was not found.
 584      * <li>Access to the program file was denied.
 585      * <li>The working directory does not exist.
 586      * </ul>
 587      *
 588      * <p>In such cases an exception will be thrown.  The exact nature
 589      * of the exception is system-dependent, but it will always be a
 590      * subclass of {@link IOException}.
 591      *
 592      * <p>If the operating system does not support the creation of
 593      * processes, an {@link UnsupportedOperationException} will be thrown.
 594      *
 595      *
 596      * @param   cmdarray  array containing the command to call and
 597      *                    its arguments.
 598      *
 599      * @param   envp      array of strings, each element of which
 600      *                    has environment variable settings in the format
 601      *                    <i>name</i>=<i>value</i>, or
 602      *                    {@code null} if the subprocess should inherit
 603      *                    the environment of the current process.
 604      *
 605      * @param   dir       the working directory of the subprocess, or
 606      *                    {@code null} if the subprocess should inherit
 607      *                    the working directory of the current process.
 608      *
 609      * @return  A new {@link Process} object for managing the subprocess
 610      *
 611      * @throws  SecurityException
 612      *          If a security manager exists and its
 613      *          {@link SecurityManager#checkExec checkExec}
 614      *          method doesn't allow creation of the subprocess
 615      *
 616      * @throws  UnsupportedOperationException
 617      *          If the operating system does not support the creation of processes.
 618      *
 619      * @throws  IOException
 620      *          If an I/O error occurs
 621      *
 622      * @throws  NullPointerException
 623      *          If {@code cmdarray} is {@code null},
 624      *          or one of the elements of {@code cmdarray} is {@code null},
 625      *          or one of the elements of {@code envp} is {@code null}
 626      *
 627      * @throws  IndexOutOfBoundsException
 628      *          If {@code cmdarray} is an empty array
 629      *          (has length {@code 0})
 630      *
 631      * @see     ProcessBuilder
 632      * @since 1.3
 633      */
 634     public Process exec(String[] cmdarray, String[] envp, File dir)
 635         throws IOException {
 636         return new ProcessBuilder(cmdarray)
 637             .environment(envp)
 638             .directory(dir)
 639             .start();
 640     }
 641 
 642     /**
 643      * Returns the number of processors available to the Java virtual machine.
 644      *
 645      * <p> This value may change during a particular invocation of the virtual
 646      * machine.  Applications that are sensitive to the number of available
 647      * processors should therefore occasionally poll this property and adjust
 648      * their resource usage appropriately. </p>
 649      *
 650      * @return  the maximum number of processors available to the virtual
 651      *          machine; never smaller than one
 652      * @since 1.4
 653      */
 654     public native int availableProcessors();
 655 
 656     /**
 657      * Returns the amount of free memory in the Java Virtual Machine.
 658      * Calling the
 659      * {@code gc} method may result in increasing the value returned
 660      * by {@code freeMemory.}
 661      *
 662      * @return  an approximation to the total amount of memory currently
 663      *          available for future allocated objects, measured in bytes.
 664      */
 665     public native long freeMemory();
 666 
 667     /**
 668      * Returns the total amount of memory in the Java virtual machine.
 669      * The value returned by this method may vary over time, depending on
 670      * the host environment.
 671      * <p>
 672      * Note that the amount of memory required to hold an object of any
 673      * given type may be implementation-dependent.
 674      *
 675      * @return  the total amount of memory currently available for current
 676      *          and future objects, measured in bytes.
 677      */
 678     public native long totalMemory();
 679 
 680     /**
 681      * Returns the maximum amount of memory that the Java virtual machine
 682      * will attempt to use.  If there is no inherent limit then the value
 683      * {@link java.lang.Long#MAX_VALUE} will be returned.
 684      *
 685      * @return  the maximum amount of memory that the virtual machine will
 686      *          attempt to use, measured in bytes
 687      * @since 1.4
 688      */
 689     public native long maxMemory();
 690 
 691     /**
 692      * Runs the garbage collector.
 693      * Calling this method suggests that the Java virtual machine expend
 694      * effort toward recycling unused objects in order to make the memory
 695      * they currently occupy available for quick reuse. When control
 696      * returns from the method call, the virtual machine has made
 697      * its best effort to recycle all discarded objects.
 698      * <p>
 699      * The name {@code gc} stands for "garbage
 700      * collector". The virtual machine performs this recycling
 701      * process automatically as needed, in a separate thread, even if the
 702      * {@code gc} method is not invoked explicitly.
 703      * <p>
 704      * The method {@link System#gc()} is the conventional and convenient
 705      * means of invoking this method.
 706      */
 707     public native void gc();
 708 
 709     /* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
 710     private static native void runFinalization0();
 711 
 712     /**
 713      * Runs the finalization methods of any objects pending finalization.
 714      * Calling this method suggests that the Java virtual machine expend
 715      * effort toward running the {@code finalize} methods of objects
 716      * that have been found to be discarded but whose {@code finalize}
 717      * methods have not yet been run. When control returns from the
 718      * method call, the virtual machine has made a best effort to
 719      * complete all outstanding finalizations.
 720      * <p>
 721      * The virtual machine performs the finalization process
 722      * automatically as needed, in a separate thread, if the
 723      * {@code runFinalization} method is not invoked explicitly.
 724      * <p>
 725      * The method {@link System#runFinalization()} is the conventional
 726      * and convenient means of invoking this method.
 727      *
 728      * @see     java.lang.Object#finalize()
 729      */
 730     public void runFinalization() {
 731         runFinalization0();
 732     }
 733 
 734     /**
 735      * Not implemented, does nothing.
 736      *
 737      * @deprecated
 738      * This method was intended to control instruction tracing.
 739      * It has been superseded by JVM-specific tracing mechanisms.
 740      *
 741      * @param on ignored
 742      */
 743     @Deprecated(since="9", forRemoval=true)
 744     public void traceInstructions(boolean on) { }
 745 
 746     /**
 747      * Not implemented, does nothing.
 748      *
 749      * @deprecated
 750      * This method was intended to control method call tracing.
 751      * It has been superseded by JVM-specific tracing mechanisms.
 752      *
 753      * @param on ignored
 754      */
 755     @Deprecated(since="9", forRemoval=true)
 756     public void traceMethodCalls(boolean on) { }
 757 
 758     /**
 759      * Loads the native library specified by the filename argument.  The filename
 760      * argument must be an absolute path name.
 761      * (for example
 762      * {@code Runtime.getRuntime().load("/home/avh/lib/libX11.so");}).
 763      *
 764      * If the filename argument, when stripped of any platform-specific library
 765      * prefix, path, and file extension, indicates a library whose name is,
 766      * for example, L, and a native library called L is statically linked
 767      * with the VM, then the JNI_OnLoad_L function exported by the library
 768      * is invoked rather than attempting to load a dynamic library.
 769      * A filename matching the argument does not have to exist in the file
 770      * system. See the JNI Specification for more details.
 771      *
 772      * Otherwise, the filename argument is mapped to a native library image in
 773      * an implementation-dependent manner.
 774      * <p>
 775      * First, if there is a security manager, its {@code checkLink}
 776      * method is called with the {@code filename} as its argument.
 777      * This may result in a security exception.
 778      * <p>
 779      * This is similar to the method {@link #loadLibrary(String)}, but it
 780      * accepts a general file name as an argument rather than just a library
 781      * name, allowing any file of native code to be loaded.
 782      * <p>
 783      * The method {@link System#load(String)} is the conventional and
 784      * convenient means of invoking this method.
 785      *
 786      * @param      filename   the file to load.
 787      * @exception  SecurityException  if a security manager exists and its
 788      *             {@code checkLink} method doesn't allow
 789      *             loading of the specified dynamic library
 790      * @exception  UnsatisfiedLinkError  if either the filename is not an
 791      *             absolute path name, the native library is not statically
 792      *             linked with the VM, or the library cannot be mapped to
 793      *             a native library image by the host system.
 794      * @exception  NullPointerException if {@code filename} is
 795      *             {@code null}
 796      * @see        java.lang.Runtime#getRuntime()
 797      * @see        java.lang.SecurityException
 798      * @see        java.lang.SecurityManager#checkLink(java.lang.String)
 799      */
 800     @CallerSensitive
 801     public void load(String filename) {
 802         load0(Reflection.getCallerClass(), filename);
 803     }
 804 
 805     synchronized void load0(Class<?> fromClass, String filename) {
 806         SecurityManager security = System.getSecurityManager();
 807         if (security != null) {
 808             security.checkLink(filename);
 809         }
 810         if (!(new File(filename).isAbsolute())) {
 811             throw new UnsatisfiedLinkError(
 812                 "Expecting an absolute path of the library: " + filename);
 813         }
 814         ClassLoader.loadLibrary(fromClass, filename, true);
 815     }
 816 
 817     /**
 818      * Loads the native library specified by the {@code libname}
 819      * argument.  The {@code libname} argument must not contain any platform
 820      * specific prefix, file extension or path. If a native library
 821      * called {@code libname} is statically linked with the VM, then the
 822      * JNI_OnLoad_{@code libname} function exported by the library is invoked.
 823      * See the JNI Specification for more details.
 824      *
 825      * Otherwise, the libname argument is loaded from a system library
 826      * location and mapped to a native library image in an implementation-
 827      * dependent manner.
 828      * <p>
 829      * First, if there is a security manager, its {@code checkLink}
 830      * method is called with the {@code libname} as its argument.
 831      * This may result in a security exception.
 832      * <p>
 833      * The method {@link System#loadLibrary(String)} is the conventional
 834      * and convenient means of invoking this method. If native
 835      * methods are to be used in the implementation of a class, a standard
 836      * strategy is to put the native code in a library file (call it
 837      * {@code LibFile}) and then to put a static initializer:
 838      * <blockquote><pre>
 839      * static { System.loadLibrary("LibFile"); }
 840      * </pre></blockquote>
 841      * within the class declaration. When the class is loaded and
 842      * initialized, the necessary native code implementation for the native
 843      * methods will then be loaded as well.
 844      * <p>
 845      * If this method is called more than once with the same library
 846      * name, the second and subsequent calls are ignored.
 847      *
 848      * @param      libname   the name of the library.
 849      * @exception  SecurityException  if a security manager exists and its
 850      *             {@code checkLink} method doesn't allow
 851      *             loading of the specified dynamic library
 852      * @exception  UnsatisfiedLinkError if either the libname argument
 853      *             contains a file path, the native library is not statically
 854      *             linked with the VM,  or the library cannot be mapped to a
 855      *             native library image by the host system.
 856      * @exception  NullPointerException if {@code libname} is
 857      *             {@code null}
 858      * @see        java.lang.SecurityException
 859      * @see        java.lang.SecurityManager#checkLink(java.lang.String)
 860      */
 861     @CallerSensitive
 862     public void loadLibrary(String libname) {
 863         loadLibrary0(Reflection.getCallerClass(), libname);
 864     }
 865 
 866     synchronized void loadLibrary0(Class<?> fromClass, String libname) {
 867         SecurityManager security = System.getSecurityManager();
 868         if (security != null) {
 869             security.checkLink(libname);
 870         }
 871         if (libname.indexOf((int)File.separatorChar) != -1) {
 872             throw new UnsatisfiedLinkError(
 873     "Directory separator should not appear in library name: " + libname);
 874         }
 875         ClassLoader.loadLibrary(fromClass, libname, false);
 876     }
 877 
 878     /**
 879      * Creates a localized version of an input stream. This method takes
 880      * an {@code InputStream} and returns an {@code InputStream}
 881      * equivalent to the argument in all respects except that it is
 882      * localized: as characters in the local character set are read from
 883      * the stream, they are automatically converted from the local
 884      * character set to Unicode.
 885      * <p>
 886      * If the argument is already a localized stream, it may be returned
 887      * as the result.
 888      *
 889      * @param      in InputStream to localize
 890      * @return     a localized input stream
 891      * @see        java.io.InputStream
 892      * @see        java.io.BufferedReader#BufferedReader(java.io.Reader)
 893      * @see        java.io.InputStreamReader#InputStreamReader(java.io.InputStream)
 894      * @deprecated As of JDK&nbsp;1.1, the preferred way to translate a byte
 895      * stream in the local encoding into a character stream in Unicode is via
 896      * the {@code InputStreamReader} and {@code BufferedReader}
 897      * classes.
 898      * This method is subject to removal in a future version of Java SE.
 899      */
 900     @Deprecated(since="1.1", forRemoval=true)
 901     public InputStream getLocalizedInputStream(InputStream in) {
 902         return in;
 903     }
 904 
 905     /**
 906      * Creates a localized version of an output stream. This method
 907      * takes an {@code OutputStream} and returns an
 908      * {@code OutputStream} equivalent to the argument in all respects
 909      * except that it is localized: as Unicode characters are written to
 910      * the stream, they are automatically converted to the local
 911      * character set.
 912      * <p>
 913      * If the argument is already a localized stream, it may be returned
 914      * as the result.
 915      *
 916      * @deprecated As of JDK&nbsp;1.1, the preferred way to translate a
 917      * Unicode character stream into a byte stream in the local encoding is via
 918      * the {@code OutputStreamWriter}, {@code BufferedWriter}, and
 919      * {@code PrintWriter} classes.
 920      * This method is subject to removal in a future version of Java SE.
 921      *
 922      * @param      out OutputStream to localize
 923      * @return     a localized output stream
 924      * @see        java.io.OutputStream
 925      * @see        java.io.BufferedWriter#BufferedWriter(java.io.Writer)
 926      * @see        java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 927      * @see        java.io.PrintWriter#PrintWriter(java.io.OutputStream)
 928      */
 929     @Deprecated(since="1.1", forRemoval=true)
 930     public OutputStream getLocalizedOutputStream(OutputStream out) {
 931         return out;
 932     }
 933 
 934     /**
 935      * Returns the version of the Java Runtime Environment as a {@link
 936      * Runtime.Version}.
 937      *
 938      * @return  the {@link Runtime.Version} of the Java Runtime Environment
 939      *
 940      * @since  9
 941      */
 942     public static Version version() {
 943         if (version == null) {
 944             version = Version.parse(
 945                 GetPropertyAction.privilegedGetProperty("java.runtime.version"));
 946         }
 947         return version;
 948     }
 949 
 950     /**
 951      * A representation of a version string for an implemenation of the
 952      * Java&nbsp;SE Platform.  A version string contains a version number
 953      * optionally followed by pre-release and build information.
 954      *
 955      * <h2><a name="verNum">Version numbers</a></h2>
 956      *
 957      * <p> A <em>version number</em>, {@code $VNUM}, is a non-empty sequence
 958      * of elements separated by period characters (U+002E).  An element is
 959      * either zero, or a unsigned integer numeral without leading zeros.  The
 960      * final element in a version number must not be zero.  The format is:
 961      * </p>
 962      *
 963      * <blockquote><pre>
 964      *     ^[1-9][0-9]*(((\.0)*\.[1-9][0-9]*)*)*$    
 965      * </pre></blockquote>
 966      *
 967      * <p> The sequence may be of arbitrary length but the first three
 968      * elements are assigned specific meanings, as follows:</p>
 969      *
 970      * <blockquote><pre>
 971      *     $MAJOR.$MINOR.$SECURITY
 972      * </pre></blockquote>
 973      *
 974      * <ul>
 975      *
 976      * <li><p> <a name="major">{@code $MAJOR}</a> --- The major version
 977      * number, incremented for a major release that contains significant new
 978      * features as specified in a new edition of the Java SE Platform
 979      * Specification, <em>e.g.</em>, <a
 980      * href="https://jcp.org/en/jsr/detail?id=337">JSR 337</a> for
 981      * Java SE 8.  Features may be removed in a major release, given
 982      * advance notice at least one major release ahead of time, and
 983      * incompatible changes may be made when justified. The {@code $MAJOR}
 984      * version number of JDK 8 is {@code 8}; the {@code $MAJOR} version
 985      * number of JDK 9 is {@code 9}.  When {@code $MAJOR} is incremented,
 986      * all subsequent elements are removed. </p></li>
 987      *
 988      * <li><p> <a name="minor">{@code $MINOR}</a> --- The minor version
 989      * number, incremented for a minor update release that may contain
 990      * compatible bug fixes, revisions to standard APIs mandated by a <a
 991      * href="https://jcp.org/en/procedures/jcp2#5.3">Maintenance Release</a>
 992      * of the relevant Platform Specification, and implementation features
 993      * outside the scope of that Specification such as new JDK-specific APIs,
 994      * additional service providers, new garbage collectors, and ports to new
 995      * hardware architectures. </p></li>
 996      *
 997      * <li><p> <a name="security">{@code $SECURITY}</a> --- The security
 998      * level, incremented for a security update release that contains critical
 999      * fixes including those necessary to improve security.  {@code $SECURITY}
1000      * is <strong>not</strong> reset when {@code $MINOR} is incremented.  A
1001      * higher value of {@code $SECURITY} for a given {@code $MAJOR} value, 
1002      * therefore, always indicates a more secure release, regardless of the 
1003      * value of {@code $MINOR}. </p></li>
1004      *
1005      * </ul>
1006      *
1007      * <p> The fourth and later elements of a version number are free for use
1008      * by downstream consumers of this code base.  Such a consumer may,
1009      * <em>e.g.</em>, use the fourth element to identify patch releases which
1010      * contain a small number of critical non-security fixes in addition to
1011      * the security fixes in the corresponding security release. </p>
1012      *
1013      * <p> The version number does not include trailing zero elements;
1014      * <em>i.e.</em>, {@code $SECURITY} is omitted if it has the value zero,
1015      * and {@code $MINOR} is omitted if both {@code $MINOR} and {@code
1016      * $SECURITY} have the value zero. </p>
1017      *
1018      * <p> The sequence of numerals in a version number is compared to another
1019      * such sequence in numerical, pointwise fashion; <em>e.g.</em>, {@code
1020      * 9.9.1} is less than {@code 9.10.3}. If one sequence is shorter than
1021      * another then the missing elements of the shorter sequence are
1022      * considered to be less than the corresponding elements of the longer
1023      * sequence; <em>e.g.</em>, {@code 9.1.2} is less than {@code 9.1.2.1}. 
1024      * </p>
1025      *
1026      * <h2><a name="verStr">Version strings</a></h2>
1027      *
1028      * <p> A <em>version string</em>, {@code $VSTR}, consists of a version
1029      * number {@code $VNUM}, as described above, optionally followed by
1030      * pre-release and build information, in the format </p>
1031      *
1032      * <blockquote><pre>
1033      *     $VNUM(-$PRE)?(\+($BUILD)?(-$OPT)?)?
1034      * </pre></blockquote>
1035      *
1036      * <p> where: </p>
1037      *
1038      * <ul>
1039      *
1040      * <li><p> <a name="pre">{@code $PRE}</a>, matching {@code ([a-zA-Z0-9]+)}
1041      * --- A pre-release identifier.  Typically {@code ea}, for a
1042      * potentially unstable early-access release under active development,
1043      * or {@code internal}, for an internal developer build.  
1044      *
1045      * <li><p> <a name="build">{@code $BUILD}</a>, matching {@code
1046      * (0|[1-9][0-9]*)} --- The build number, incremented for each promoted
1047      * build.  {@code $BUILD} is reset to {@code 1} when any portion of {@code
1048      * $VNUM} is incremented. </p>
1049      *
1050      * <li><p> <a name="opt">{@code $OPT}</a>, matching {@code
1051      * ([-a-zA-Z0-9\.]+)} --- Additional build information, if desired.  In
1052      * the case of an {@code internal} build this will often contain the date
1053      * and time of the build. </p>
1054      *
1055      * </ul>
1056      *
1057      * <p> A version number {@code 10-ea} matches {@code $VNUM = "10"} and
1058      * {@code $PRE = "ea"}.  The version number {@code 10+-ea} matches
1059      * {@code $VNUM = "10"} and {@code $OPT = "ea"}. </p>
1060      *
1061      * <p> When comparing two version strings, the value of {@code $OPT}, if
1062      * present, may or may not be significant depending on the chosen
1063      * comparison method.  The comparison methods {@link #compareTo(Version)
1064      * compareTo()} and {@link #compareToIgnoreOpt(Version)
1065      * compareToIgnoreOpt()} should be used consistently with the
1066      * corresponding methods {@link #equals(Object) equals()} and {@link
1067      * #equalsIgnoreOpt(Object) equalsIgnoreOpt()}.  </p>
1068      *
1069      * <p> A <em>short version string</em>, {@code $SVSTR}, often useful in
1070      * less formal contexts, is a version number optionally followed by a
1071      * pre-release identifier:
1072      *
1073      * <blockquote><pre>
1074      *     $VNUM(-$PRE)?
1075      * </pre></blockquote>
1076      *
1077      * @since  9
1078      */
1079     public static class Version
1080         implements Comparable<Version>
1081     {
1082         private final List<Integer>     version;
1083         private final Optional<String>  pre;
1084         private final Optional<Integer> build;
1085         private final Optional<String>  optional;
1086 
1087 
1088         // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
1089         // RE limits the format of version strings
1090         // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
1091 
1092         private static final String VNUM
1093             = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
1094         private static final String VNUM_GROUP  = "VNUM";
1095 
1096         private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
1097         private static final String PRE_GROUP   = "PRE";
1098 
1099         private static final String BUILD
1100             = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
1101         private static final String PLUS_GROUP  = "PLUS";
1102         private static final String BUILD_GROUP = "BUILD";
1103 
1104         private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
1105         private static final String OPT_GROUP   = "OPT";
1106 
1107         private static final String VSTR_FORMAT
1108             = "^" + VNUM + PRE + BUILD + OPT + "$";
1109         private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
1110 
1111         /**
1112          * Constructs a valid <a href="verStr">version string</a> containing
1113          * a <a href="#verNum">version number</a> followed by pre-release and
1114          * build information.
1115          *
1116          * @param  s
1117          *         A string to be interpreted as a version
1118          *
1119          * @throws  IllegalArgumentException
1120          *          If the given string cannot be interpreted as a valid
1121          *          version
1122          *
1123          * @throws  NullPointerException
1124          *          If {@code s} is {@code null}
1125          *
1126          * @throws  NumberFormatException
1127          *          If an element of the version number or the build number
1128          *          cannot be represented as an {@link Integer}
1129          */
1130         private Version(String s) {
1131             if (s == null)
1132                 throw new NullPointerException();
1133 
1134             Matcher m = VSTR_PATTERN.matcher(s);
1135             if (!m.matches())
1136                 throw new IllegalArgumentException("Invalid version string: '"
1137                                                    + s + "'");
1138 
1139             // $VNUM is a dot-separated list of integers of arbitrary length
1140             List<Integer> list = new ArrayList<>();
1141             for (String i : m.group(VNUM_GROUP).split("\\."))
1142                 list.add(Integer.parseInt(i));
1143             version = Collections.unmodifiableList(list);
1144 
1145             pre = Optional.ofNullable(m.group(PRE_GROUP));
1146 
1147             String b = m.group(BUILD_GROUP);
1148             // $BUILD is an integer
1149             build = (b == null)
1150                 ? Optional.<Integer>empty()
1151                 : Optional.ofNullable(Integer.parseInt(b));
1152 
1153             optional = Optional.ofNullable(m.group(OPT_GROUP));
1154 
1155             // empty '+'
1156             if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
1157                 if (optional.isPresent()) {
1158                     if (pre.isPresent())
1159                         throw new IllegalArgumentException("'+' found with"
1160                             + " pre-release and optional components:'" + s 
1161                             + "'");
1162                 } else {
1163                     throw new IllegalArgumentException("'+' found with neither"
1164                         + " build or optional components: '" + s + "'");
1165                 }
1166             }
1167         }
1168 
1169         /**
1170          * Parses the given string as a valid <a
1171          * href="#verStr">version string</a> containing a <a
1172          * href="#verNum">version number</a> followed by pre-release and
1173          * build information.
1174          *
1175          * @param  s
1176          *         A string to interpret as a version
1177          *
1178          * @throws  IllegalArgumentException
1179          *          If the given string cannot be interpreted as a valid
1180          *          version
1181          *
1182          * @throws  NullPointerException
1183          *          If the given string is {@code null}
1184          *
1185          * @throws  NumberFormatException
1186          *          If an element of the version number or the build number
1187          *          cannot be represented as an {@link Integer}
1188          *
1189          * @return  This version
1190          */
1191         public static Version parse(String s) {
1192             return new Version(s);
1193         }
1194 
1195         /**
1196          * Returns the <a href="#major">major</a> version number.
1197          *
1198          * @return  The major version number
1199          */
1200         public int major() {
1201             return version.get(0);
1202         }
1203 
1204         /**
1205          * Returns the <a href="#minor">minor</a> version number or zero if it
1206          * was not set.
1207          *
1208          * @return  The minor version number or zero if it was not set
1209          */
1210         public int minor() {
1211             return (version.size() > 1 ? version.get(1) : 0);
1212         }
1213 
1214         /**
1215          * Returns the <a href="#security">security</a> version number or zero
1216          * if it was not set.
1217          *
1218          * @return  The security version number or zero if it was not set
1219          */
1220         public int security() {
1221             return (version.size() > 2 ? version.get(2) : 0);
1222         }
1223 
1224         /**
1225          * Returns an unmodifiable {@link java.util.List List} of the
1226          * integer numerals contained in the <a href="#verNum">version
1227          * number</a>.  The {@code List} always contains at least one
1228          * element corresponding to the <a href="#major">major version
1229          * number</a>.
1230          *
1231          * @return  An unmodifiable list of the integer numerals
1232          *          contained in the version number
1233          */
1234         public List<Integer> version() {
1235             return version;
1236         }
1237 
1238         /**
1239          * Returns the optional <a href="#pre">pre-release</a> information.
1240          *
1241          * @return  The optional pre-release information as a String
1242          */
1243         public Optional<String> pre() {
1244             return pre;
1245         }
1246 
1247         /**
1248          * Returns the <a href="#build">build number</a>.
1249          *
1250          * @return The optional build number.
1251          */
1252         public Optional<Integer> build() {
1253             return build;
1254         }
1255 
1256         /**
1257          * Returns <a href="#opt">optional</a> additional identifying build
1258          * information.
1259          *
1260          * @return  Additional build information as a String
1261          */
1262         public Optional<String> optional() {
1263             return optional;
1264         }
1265 
1266         /**
1267          * Compares this version to another.
1268          *
1269          * <p> Each of the components in the <a href="#verStr">version</a> is
1270          * compared in the follow order of precedence: version numbers,
1271          * pre-release identifiers, build numbers, optional build information.
1272          * </p>
1273          *
1274          * <p> Comparison begins by examining the sequence of version numbers.
1275          * If one sequence is shorter than another, then the missing elements
1276          * of the shorter sequence are considered to be less than the
1277          * corresponding elements of the longer sequence. </p>
1278          *
1279          * <p> A version with a pre-release identifier is always considered to
1280          * be less than a version without one.  Pre-release identifiers are
1281          * compared numerically when they consist only of digits, and
1282          * lexicographically otherwise.  Numeric identifiers are considered to
1283          * be less than non-numeric identifiers.  </p>
1284          *
1285          * <p> A version without a build number is always less than one with a
1286          * build number; otherwise build numbers are compared numerically. </p>
1287          *
1288          * <p> The optional build information is compared lexicographically.
1289          * During this comparison, a version with optional build information is
1290          * considered to be greater than a version without one. </p>
1291          *
1292          * <p> A version is not comparable to any other type of object.
1293          *
1294          * @param  ob
1295          *         The object to be compared
1296          *
1297          * @return  A negative integer, zero, or a positive integer if this
1298          *          {@code Version} is less than, equal to, or greater than the
1299          *          given {@code Version}
1300          *
1301          * @throws  NullPointerException
1302          *          If the given object is {@code null}
1303          */
1304         @Override
1305         public int compareTo(Version ob) {
1306             return compare(ob, false);
1307         }
1308 
1309         /**
1310          * Compares this version to another disregarding optional build
1311          * information.
1312          *
1313          * <p> Two versions are compared by examining the version string as
1314          * described in {@link #compareTo(Version)} with the exception that the
1315          * optional build information is always ignored. </p>
1316          *
1317          * <p> A version is not comparable to any other type of object.
1318          *
1319          * @param  ob
1320          *         The object to be compared
1321          *
1322          * @return  A negative integer, zero, or a positive integer if this
1323          *          {@code Version} is less than, equal to, or greater than the
1324          *          given {@code Version}
1325          *
1326          * @throws  NullPointerException
1327          *          If the given object is {@code null}
1328          */
1329         public int compareToIgnoreOpt(Version ob) {
1330             return compare(ob, true);
1331         }
1332 
1333         private int compare(Version ob, boolean ignoreOpt) {
1334             if (ob == null)
1335                 throw new NullPointerException("Invalid argument");
1336 
1337             int ret = compareVersion(ob);
1338             if (ret != 0)
1339                 return ret;
1340 
1341             ret = comparePre(ob);
1342             if (ret != 0)
1343                 return ret;
1344 
1345             ret = compareBuild(ob);
1346             if (ret != 0)
1347                 return ret;
1348 
1349             if (!ignoreOpt)
1350                 return compareOpt(ob);
1351 
1352             return 0;
1353         }
1354 
1355         private int compareVersion(Version ob) {
1356             int size = version.size();
1357             int oSize = ob.version().size();
1358             int min = Math.min(size, oSize);
1359             for (int i = 0; i < min; i++) {
1360                 Integer val = version.get(i);
1361                 Integer oVal = ob.version().get(i);
1362                 if (val != oVal)
1363                     return val - oVal;
1364             }
1365             if (size != oSize)
1366                 return size - oSize;
1367             return 0;
1368         }
1369 
1370         private int comparePre(Version ob) {
1371             Optional<String> oPre = ob.pre();
1372             if (!pre.isPresent()) {
1373                 if (oPre.isPresent())
1374                     return 1;
1375             } else {
1376                 if (!oPre.isPresent())
1377                     return -1;
1378                 String val = pre.get();
1379                 String oVal = oPre.get();
1380                 if (val.matches("\\d+")) {
1381                     return (oVal.matches("\\d+")
1382                         ? (new BigInteger(val)).compareTo(new BigInteger(oVal))
1383                         : -1);
1384                 } else {
1385                     return (oVal.matches("\\d+")
1386                         ? 1
1387                         : val.compareTo(oVal));
1388                 }
1389             }
1390             return 0;
1391         }
1392 
1393         private int compareBuild(Version ob) {
1394             Optional<Integer> oBuild = ob.build();
1395             if (oBuild.isPresent()) {
1396                 return (build.isPresent()
1397                         ? build.get().compareTo(oBuild.get())
1398                         : 1);
1399             } else if (build.isPresent()) {
1400                 return -1;
1401             }
1402             return 0;
1403         }
1404 
1405         private int compareOpt(Version ob) {
1406             Optional<String> oOpt = ob.optional();
1407             if (!optional.isPresent()) {
1408                 if (oOpt.isPresent())
1409                     return -1;
1410             } else {
1411                 if (!oOpt.isPresent())
1412                     return 1;
1413                 return optional.get().compareTo(oOpt.get());
1414             }
1415             return 0;
1416         }
1417 
1418         /**
1419          * Returns a string representation of this version.
1420          *
1421          * @return  The version string
1422          */
1423         @Override
1424         public String toString() {
1425             StringBuilder sb
1426                 = new StringBuilder(version.stream()
1427                     .map(Object::toString)
1428                     .collect(Collectors.joining(".")));
1429 
1430             pre.ifPresent(v -> sb.append("-").append(v));
1431 
1432             if (build.isPresent()) {
1433                 sb.append("+").append(build.get());
1434                 if (optional.isPresent())
1435                     sb.append("-").append(optional.get());
1436             } else {
1437                 if (optional.isPresent()) {
1438                     sb.append(pre.isPresent() ? "-" : "+-");
1439                     sb.append(optional.get());
1440                 }
1441             }
1442 
1443             return sb.toString();
1444         }
1445 
1446         /**
1447          * Determines whether this {@code Version} is equal to another object.
1448          *
1449          * <p> Two {@code Version}s are equal if and only if they represent the
1450          * same version string.
1451          *
1452          * <p> This method satisfies the general contract of the {@link
1453          * Object#equals(Object) Object.equals} method. </p>
1454          *
1455          * @param  ob
1456          *         The object to which this {@code Version} is to be compared
1457          *
1458          * @return  {@code true} if, and only if, the given object is a {@code
1459          *          Version} that is identical to this {@code Version}
1460          *
1461          */
1462         @Override
1463         public boolean equals(Object ob) {
1464             boolean ret = equalsIgnoreOpt(ob);
1465             if (!ret)
1466                 return false;
1467 
1468             Version that = (Version)ob;
1469             return (this.optional().equals(that.optional()));
1470         }
1471 
1472         /**
1473          * Determines whether this {@code Version} is equal to another
1474          * disregarding optional build information.
1475          *
1476          * <p> Two {@code Version}s are equal if and only if they represent the
1477          * same version string disregarding the optional build information.
1478          *
1479          * @param  ob
1480          *         The object to which this {@code Version} is to be compared
1481          *
1482          * @return  {@code true} if, and only if, the given object is a {@code
1483          *          Version} that is identical to this {@code Version}
1484          *          ignoring the optinal build information
1485          *
1486          */
1487         public boolean equalsIgnoreOpt(Object ob) {
1488             if (this == ob)
1489                 return true;
1490             if (!(ob instanceof Version))
1491                 return false;
1492 
1493             Version that = (Version)ob;
1494             return (this.version().equals(that.version())
1495                     && this.pre().equals(that.pre())
1496                     && this.build().equals(that.build()));
1497         }
1498 
1499         /**
1500          * Returns the hash code of this version.
1501          *
1502          * <p> This method satisfies the general contract of the {@link
1503          * Object#hashCode Object.hashCode} method.
1504          *
1505          * @return  The hashcode of this version
1506          */
1507         @Override
1508         public int hashCode() {
1509             int h = 1;
1510             int p = 17;
1511 
1512             h = p * h + version.hashCode();
1513             h = p * h + pre.hashCode();
1514             h = p * h + build.hashCode();
1515             h = p * h + optional.hashCode();
1516 
1517             return h;
1518         }
1519     }
1520 
1521 }