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