1 /* 2 * Copyright (c) 1995, 2017, 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.halt(status); 284 } 285 286 /** 287 * Enable or disable finalization on exit; doing so specifies that the 288 * finalizers of all objects that have finalizers that have not yet been 289 * automatically invoked are to be run before the Java runtime exits. 290 * By default, finalization on exit is disabled. 291 * 292 * <p>If there is a security manager, 293 * its {@code checkExit} method is first called 294 * with 0 as its argument to ensure the exit is allowed. 295 * This could result in a SecurityException. 296 * 297 * @param value true to enable finalization on exit, false to disable 298 * @deprecated This method is inherently unsafe. It may result in 299 * finalizers being called on live objects while other threads are 300 * concurrently manipulating those objects, resulting in erratic 301 * behavior or deadlock. 302 * This method is subject to removal in a future version of Java SE. 303 * 304 * @throws SecurityException 305 * if a security manager exists and its {@code checkExit} 306 * method doesn't allow the exit. 307 * 308 * @see java.lang.Runtime#exit(int) 309 * @see java.lang.Runtime#gc() 310 * @see java.lang.SecurityManager#checkExit(int) 311 * @since 1.1 312 */ 313 @Deprecated(since="1.2", forRemoval=true) 314 public static void runFinalizersOnExit(boolean value) { 315 SecurityManager security = System.getSecurityManager(); 316 if (security != null) { 317 try { 318 security.checkExit(0); 319 } catch (SecurityException e) { 320 throw new SecurityException("runFinalizersOnExit"); 321 } 322 } 323 Shutdown.setRunFinalizersOnExit(value); 324 } 325 326 /** 327 * Executes the specified string command in a separate process. 328 * 329 * <p>This is a convenience method. An invocation of the form 330 * {@code exec(command)} 331 * behaves in exactly the same way as the invocation 332 * {@link #exec(String, String[], File) exec}{@code (command, null, null)}. 333 * 334 * @param command a specified system command. 335 * 336 * @return A new {@link Process} object for managing the subprocess 337 * 338 * @throws SecurityException 339 * If a security manager exists and its 340 * {@link SecurityManager#checkExec checkExec} 341 * method doesn't allow creation of the subprocess 342 * 343 * @throws IOException 344 * If an I/O error occurs 345 * 346 * @throws NullPointerException 347 * If {@code command} is {@code null} 348 * 349 * @throws IllegalArgumentException 350 * If {@code command} is empty 351 * 352 * @see #exec(String[], String[], File) 353 * @see ProcessBuilder 354 */ 355 public Process exec(String command) throws IOException { 356 return exec(command, null, null); 357 } 358 359 /** 360 * Executes the specified string command in a separate process with the 361 * specified environment. 362 * 363 * <p>This is a convenience method. An invocation of the form 364 * {@code exec(command, envp)} 365 * behaves in exactly the same way as the invocation 366 * {@link #exec(String, String[], File) exec}{@code (command, envp, null)}. 367 * 368 * @param command a specified system command. 369 * 370 * @param envp array of strings, each element of which 371 * has environment variable settings in the format 372 * <i>name</i>=<i>value</i>, or 373 * {@code null} if the subprocess should inherit 374 * the environment of the current process. 375 * 376 * @return A new {@link Process} object for managing the subprocess 377 * 378 * @throws SecurityException 379 * If a security manager exists and its 380 * {@link SecurityManager#checkExec checkExec} 381 * method doesn't allow creation of the subprocess 382 * 383 * @throws IOException 384 * If an I/O error occurs 385 * 386 * @throws NullPointerException 387 * If {@code command} is {@code null}, 388 * or one of the elements of {@code envp} is {@code null} 389 * 390 * @throws IllegalArgumentException 391 * If {@code command} is empty 392 * 393 * @see #exec(String[], String[], File) 394 * @see ProcessBuilder 395 */ 396 public Process exec(String command, String[] envp) throws IOException { 397 return exec(command, envp, null); 398 } 399 400 /** 401 * Executes the specified string command in a separate process with the 402 * specified environment and working directory. 403 * 404 * <p>This is a convenience method. An invocation of the form 405 * {@code exec(command, envp, dir)} 406 * behaves in exactly the same way as the invocation 407 * {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, dir)}, 408 * where {@code cmdarray} is an array of all the tokens in 409 * {@code command}. 410 * 411 * <p>More precisely, the {@code command} string is broken 412 * into tokens using a {@link StringTokenizer} created by the call 413 * {@code new {@link StringTokenizer}(command)} with no 414 * further modification of the character categories. The tokens 415 * produced by the tokenizer are then placed in the new string 416 * array {@code cmdarray}, in the same order. 417 * 418 * @param command a specified system command. 419 * 420 * @param envp array of strings, each element of which 421 * has environment variable settings in the format 422 * <i>name</i>=<i>value</i>, or 423 * {@code null} if the subprocess should inherit 424 * the environment of the current process. 425 * 426 * @param dir the working directory of the subprocess, or 427 * {@code null} if the subprocess should inherit 428 * the working directory of the current process. 429 * 430 * @return A new {@link Process} object for managing the subprocess 431 * 432 * @throws SecurityException 433 * If a security manager exists and its 434 * {@link SecurityManager#checkExec checkExec} 435 * method doesn't allow creation of the subprocess 436 * 437 * @throws IOException 438 * If an I/O error occurs 439 * 440 * @throws NullPointerException 441 * If {@code command} is {@code null}, 442 * or one of the elements of {@code envp} is {@code null} 443 * 444 * @throws IllegalArgumentException 445 * If {@code command} is empty 446 * 447 * @see ProcessBuilder 448 * @since 1.3 449 */ 450 public Process exec(String command, String[] envp, File dir) 451 throws IOException { 452 if (command.length() == 0) 453 throw new IllegalArgumentException("Empty command"); 454 455 StringTokenizer st = new StringTokenizer(command); 456 String[] cmdarray = new String[st.countTokens()]; 457 for (int i = 0; st.hasMoreTokens(); i++) 458 cmdarray[i] = st.nextToken(); 459 return exec(cmdarray, envp, dir); 460 } 461 462 /** 463 * Executes the specified command and arguments in a separate process. 464 * 465 * <p>This is a convenience method. An invocation of the form 466 * {@code exec(cmdarray)} 467 * behaves in exactly the same way as the invocation 468 * {@link #exec(String[], String[], File) exec}{@code (cmdarray, null, null)}. 469 * 470 * @param cmdarray array containing the command to call and 471 * its arguments. 472 * 473 * @return A new {@link Process} object for managing the subprocess 474 * 475 * @throws SecurityException 476 * If a security manager exists and its 477 * {@link SecurityManager#checkExec checkExec} 478 * method doesn't allow creation of the subprocess 479 * 480 * @throws IOException 481 * If an I/O error occurs 482 * 483 * @throws NullPointerException 484 * If {@code cmdarray} is {@code null}, 485 * or one of the elements of {@code cmdarray} is {@code null} 486 * 487 * @throws IndexOutOfBoundsException 488 * If {@code cmdarray} is an empty array 489 * (has length {@code 0}) 490 * 491 * @see ProcessBuilder 492 */ 493 public Process exec(String cmdarray[]) throws IOException { 494 return exec(cmdarray, null, null); 495 } 496 497 /** 498 * Executes the specified command and arguments in a separate process 499 * with the specified environment. 500 * 501 * <p>This is a convenience method. An invocation of the form 502 * {@code exec(cmdarray, envp)} 503 * behaves in exactly the same way as the invocation 504 * {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, null)}. 505 * 506 * @param cmdarray array containing the command to call and 507 * its arguments. 508 * 509 * @param envp array of strings, each element of which 510 * has environment variable settings in the format 511 * <i>name</i>=<i>value</i>, or 512 * {@code null} if the subprocess should inherit 513 * the environment of the current process. 514 * 515 * @return A new {@link Process} object for managing the subprocess 516 * 517 * @throws SecurityException 518 * If a security manager exists and its 519 * {@link SecurityManager#checkExec checkExec} 520 * method doesn't allow creation of the subprocess 521 * 522 * @throws IOException 523 * If an I/O error occurs 524 * 525 * @throws NullPointerException 526 * If {@code cmdarray} is {@code null}, 527 * or one of the elements of {@code cmdarray} is {@code null}, 528 * or one of the elements of {@code envp} is {@code null} 529 * 530 * @throws IndexOutOfBoundsException 531 * If {@code cmdarray} is an empty array 532 * (has length {@code 0}) 533 * 534 * @see ProcessBuilder 535 */ 536 public Process exec(String[] cmdarray, String[] envp) throws IOException { 537 return exec(cmdarray, envp, null); 538 } 539 540 541 /** 542 * Executes the specified command and arguments in a separate process with 543 * the specified environment and working directory. 544 * 545 * <p>Given an array of strings {@code cmdarray}, representing the 546 * tokens of a command line, and an array of strings {@code envp}, 547 * representing "environment" variable settings, this method creates 548 * a new process in which to execute the specified command. 549 * 550 * <p>This method checks that {@code cmdarray} is a valid operating 551 * system command. Which commands are valid is system-dependent, 552 * but at the very least the command must be a non-empty list of 553 * non-null strings. 554 * 555 * <p>If {@code envp} is {@code null}, the subprocess inherits the 556 * environment settings of the current process. 557 * 558 * <p>A minimal set of system dependent environment variables may 559 * be required to start a process on some operating systems. 560 * As a result, the subprocess may inherit additional environment variable 561 * settings beyond those in the specified environment. 562 * 563 * <p>{@link ProcessBuilder#start()} is now the preferred way to 564 * start a process with a modified environment. 565 * 566 * <p>The working directory of the new subprocess is specified by {@code dir}. 567 * If {@code dir} is {@code null}, the subprocess inherits the 568 * current working directory of the current process. 569 * 570 * <p>If a security manager exists, its 571 * {@link SecurityManager#checkExec checkExec} 572 * method is invoked with the first component of the array 573 * {@code cmdarray} as its argument. This may result in a 574 * {@link SecurityException} being thrown. 575 * 576 * <p>Starting an operating system process is highly system-dependent. 577 * Among the many things that can go wrong are: 578 * <ul> 579 * <li>The operating system program file was not found. 580 * <li>Access to the program file was denied. 581 * <li>The working directory does not exist. 582 * </ul> 583 * 584 * <p>In such cases an exception will be thrown. The exact nature 585 * of the exception is system-dependent, but it will always be a 586 * subclass of {@link IOException}. 587 * 588 * <p>If the operating system does not support the creation of 589 * processes, an {@link UnsupportedOperationException} will be thrown. 590 * 591 * 592 * @param cmdarray array containing the command to call and 593 * its arguments. 594 * 595 * @param envp array of strings, each element of which 596 * has environment variable settings in the format 597 * <i>name</i>=<i>value</i>, or 598 * {@code null} if the subprocess should inherit 599 * the environment of the current process. 600 * 601 * @param dir the working directory of the subprocess, or 602 * {@code null} if the subprocess should inherit 603 * the working directory of the current process. 604 * 605 * @return A new {@link Process} object for managing the subprocess 606 * 607 * @throws SecurityException 608 * If a security manager exists and its 609 * {@link SecurityManager#checkExec checkExec} 610 * method doesn't allow creation of the subprocess 611 * 612 * @throws UnsupportedOperationException 613 * If the operating system does not support the creation of processes. 614 * 615 * @throws IOException 616 * If an I/O error occurs 617 * 618 * @throws NullPointerException 619 * If {@code cmdarray} is {@code null}, 620 * or one of the elements of {@code cmdarray} is {@code null}, 621 * or one of the elements of {@code envp} is {@code null} 622 * 623 * @throws IndexOutOfBoundsException 624 * If {@code cmdarray} is an empty array 625 * (has length {@code 0}) 626 * 627 * @see ProcessBuilder 628 * @since 1.3 629 */ 630 public Process exec(String[] cmdarray, String[] envp, File dir) 631 throws IOException { 632 return new ProcessBuilder(cmdarray) 633 .environment(envp) 634 .directory(dir) 635 .start(); 636 } 637 638 /** 639 * Returns the number of processors available to the Java virtual machine. 640 * 641 * <p> This value may change during a particular invocation of the virtual 642 * machine. Applications that are sensitive to the number of available 643 * processors should therefore occasionally poll this property and adjust 644 * their resource usage appropriately. </p> 645 * 646 * @return the maximum number of processors available to the virtual 647 * machine; never smaller than one 648 * @since 1.4 649 */ 650 public native int availableProcessors(); 651 652 /** 653 * Returns the amount of free memory in the Java Virtual Machine. 654 * Calling the 655 * {@code gc} method may result in increasing the value returned 656 * by {@code freeMemory.} 657 * 658 * @return an approximation to the total amount of memory currently 659 * available for future allocated objects, measured in bytes. 660 */ 661 public native long freeMemory(); 662 663 /** 664 * Returns the total amount of memory in the Java virtual machine. 665 * The value returned by this method may vary over time, depending on 666 * the host environment. 667 * <p> 668 * Note that the amount of memory required to hold an object of any 669 * given type may be implementation-dependent. 670 * 671 * @return the total amount of memory currently available for current 672 * and future objects, measured in bytes. 673 */ 674 public native long totalMemory(); 675 676 /** 677 * Returns the maximum amount of memory that the Java virtual machine 678 * will attempt to use. If there is no inherent limit then the value 679 * {@link java.lang.Long#MAX_VALUE} will be returned. 680 * 681 * @return the maximum amount of memory that the virtual machine will 682 * attempt to use, measured in bytes 683 * @since 1.4 684 */ 685 public native long maxMemory(); 686 687 /** 688 * Runs the garbage collector. 689 * Calling this method suggests that the Java virtual machine expend 690 * effort toward recycling unused objects in order to make the memory 691 * they currently occupy available for quick reuse. When control 692 * returns from the method call, the virtual machine has made 693 * its best effort to recycle all discarded objects. 694 * <p> 695 * The name {@code gc} stands for "garbage 696 * collector". The virtual machine performs this recycling 697 * process automatically as needed, in a separate thread, even if the 698 * {@code gc} method is not invoked explicitly. 699 * <p> 700 * The method {@link System#gc()} is the conventional and convenient 701 * means of invoking this method. 702 */ 703 public native void gc(); 704 705 /* Wormhole for calling java.lang.ref.Finalizer.runFinalization */ 706 private static native void runFinalization0(); 707 708 /** 709 * Runs the finalization methods of any objects pending finalization. 710 * Calling this method suggests that the Java virtual machine expend 711 * effort toward running the {@code finalize} methods of objects 712 * that have been found to be discarded but whose {@code finalize} 713 * methods have not yet been run. When control returns from the 714 * method call, the virtual machine has made a best effort to 715 * complete all outstanding finalizations. 716 * <p> 717 * The virtual machine performs the finalization process 718 * automatically as needed, in a separate thread, if the 719 * {@code runFinalization} method is not invoked explicitly. 720 * <p> 721 * The method {@link System#runFinalization()} is the conventional 722 * and convenient means of invoking this method. 723 * 724 * @see java.lang.Object#finalize() 725 */ 726 public void runFinalization() { 727 runFinalization0(); 728 } 729 730 /** 731 * Not implemented, does nothing. 732 * 733 * @deprecated 734 * This method was intended to control instruction tracing. 735 * It has been superseded by JVM-specific tracing mechanisms. 736 * This method is subject to removal in a future version of Java SE. 737 * 738 * @param on ignored 739 */ 740 @Deprecated(since="9", forRemoval=true) 741 public void traceInstructions(boolean on) { } 742 743 /** 744 * Not implemented, does nothing. 745 * 746 * @deprecated 747 * This method was intended to control method call tracing. 748 * It has been superseded by JVM-specific tracing mechanisms. 749 * This method is subject to removal in a future version of Java SE. 750 * 751 * @param on ignored 752 */ 753 @Deprecated(since="9", forRemoval=true) 754 public void traceMethodCalls(boolean on) { } 755 756 /** 757 * Loads the native library specified by the filename argument. The filename 758 * argument must be an absolute path name. 759 * (for example 760 * {@code Runtime.getRuntime().load("/home/avh/lib/libX11.so");}). 761 * 762 * If the filename argument, when stripped of any platform-specific library 763 * prefix, path, and file extension, indicates a library whose name is, 764 * for example, L, and a native library called L is statically linked 765 * with the VM, then the JNI_OnLoad_L function exported by the library 766 * is invoked rather than attempting to load a dynamic library. 767 * A filename matching the argument does not have to exist in the file 768 * system. 769 * See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a> 770 * 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 <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a> 824 * for more details. 825 * 826 * Otherwise, the libname argument is loaded from a system library 827 * location and mapped to a native library image in an implementation- 828 * dependent manner. 829 * <p> 830 * First, if there is a security manager, its {@code checkLink} 831 * method is called with the {@code libname} as its argument. 832 * This may result in a security exception. 833 * <p> 834 * The method {@link System#loadLibrary(String)} is the conventional 835 * and convenient means of invoking this method. If native 836 * methods are to be used in the implementation of a class, a standard 837 * strategy is to put the native code in a library file (call it 838 * {@code LibFile}) and then to put a static initializer: 839 * <blockquote><pre> 840 * static { System.loadLibrary("LibFile"); } 841 * </pre></blockquote> 842 * within the class declaration. When the class is loaded and 843 * initialized, the necessary native code implementation for the native 844 * methods will then be loaded as well. 845 * <p> 846 * If this method is called more than once with the same library 847 * name, the second and subsequent calls are ignored. 848 * 849 * @param libname the name of the library. 850 * @exception SecurityException if a security manager exists and its 851 * {@code checkLink} method doesn't allow 852 * loading of the specified dynamic library 853 * @exception UnsatisfiedLinkError if either the libname argument 854 * contains a file path, the native library is not statically 855 * linked with the VM, or the library cannot be mapped to a 856 * native library image by the host system. 857 * @exception NullPointerException if {@code libname} is 858 * {@code null} 859 * @see java.lang.SecurityException 860 * @see java.lang.SecurityManager#checkLink(java.lang.String) 861 */ 862 @CallerSensitive 863 public void loadLibrary(String libname) { 864 loadLibrary0(Reflection.getCallerClass(), libname); 865 } 866 867 synchronized void loadLibrary0(Class<?> fromClass, String libname) { 868 SecurityManager security = System.getSecurityManager(); 869 if (security != null) { 870 security.checkLink(libname); 871 } 872 if (libname.indexOf((int)File.separatorChar) != -1) { 873 throw new UnsatisfiedLinkError( 874 "Directory separator should not appear in library name: " + libname); 875 } 876 ClassLoader.loadLibrary(fromClass, libname, false); 877 } 878 879 /** 880 * Creates a localized version of an input stream. This method takes 881 * an {@code InputStream} and returns an {@code InputStream} 882 * equivalent to the argument in all respects except that it is 883 * localized: as characters in the local character set are read from 884 * the stream, they are automatically converted from the local 885 * character set to Unicode. 886 * <p> 887 * If the argument is already a localized stream, it may be returned 888 * as the result. 889 * 890 * @param in InputStream to localize 891 * @return a localized input stream 892 * @see java.io.InputStream 893 * @see java.io.BufferedReader#BufferedReader(java.io.Reader) 894 * @see java.io.InputStreamReader#InputStreamReader(java.io.InputStream) 895 * @deprecated As of JDK 1.1, the preferred way to translate a byte 896 * stream in the local encoding into a character stream in Unicode is via 897 * the {@code InputStreamReader} and {@code BufferedReader} 898 * classes. 899 * This method is subject to removal in a future version of Java SE. 900 */ 901 @Deprecated(since="1.1", forRemoval=true) 902 public InputStream getLocalizedInputStream(InputStream in) { 903 return in; 904 } 905 906 /** 907 * Creates a localized version of an output stream. This method 908 * takes an {@code OutputStream} and returns an 909 * {@code OutputStream} equivalent to the argument in all respects 910 * except that it is localized: as Unicode characters are written to 911 * the stream, they are automatically converted to the local 912 * character set. 913 * <p> 914 * If the argument is already a localized stream, it may be returned 915 * as the result. 916 * 917 * @deprecated As of JDK 1.1, the preferred way to translate a 918 * Unicode character stream into a byte stream in the local encoding is via 919 * the {@code OutputStreamWriter}, {@code BufferedWriter}, and 920 * {@code PrintWriter} classes. 921 * This method is subject to removal in a future version of Java SE. 922 * 923 * @param out OutputStream to localize 924 * @return a localized output stream 925 * @see java.io.OutputStream 926 * @see java.io.BufferedWriter#BufferedWriter(java.io.Writer) 927 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) 928 * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream) 929 */ 930 @Deprecated(since="1.1", forRemoval=true) 931 public OutputStream getLocalizedOutputStream(OutputStream out) { 932 return out; 933 } 934 935 /** 936 * Returns the version of the Java Runtime Environment as a {@link Version}. 937 * 938 * @return the {@link Version} of the Java Runtime Environment 939 * 940 * @since 9 941 */ 942 public static Version version() { 943 if (version == null) { 944 version = new Version(VersionProps.versionNumbers(), 945 VersionProps.pre(), VersionProps.build(), 946 VersionProps.optional()); 947 } 948 return version; 949 } 950 951 /** 952 * A representation of a version string for an implementation of the 953 * Java SE Platform. A version string consists of a version number 954 * optionally followed by pre-release and build information. 955 * 956 * <h2><a id="verNum">Version numbers</a></h2> 957 * 958 * <p> A <em>version number</em>, {@code $VNUM}, is a non-empty sequence 959 * of elements separated by period characters (U+002E). An element is 960 * either zero, or an unsigned integer numeral without leading zeros. The 961 * final element in a version number must not be zero. The format is: 962 * </p> 963 * 964 * <blockquote><pre> 965 * [1-9][0-9]*((\.0)*\.[1-9][0-9]*)* 966 * </pre></blockquote> 967 * 968 * <p> The sequence may be of arbitrary length but the first three 969 * elements are assigned specific meanings, as follows:</p> 970 * 971 * <blockquote><pre> 972 * $MAJOR.$MINOR.$SECURITY 973 * </pre></blockquote> 974 * 975 * <ul> 976 * 977 * <li><p> <a id="major">{@code $MAJOR}</a> --- The major version 978 * number, incremented for a major release that contains significant new 979 * features as specified in a new edition of the Java SE Platform 980 * Specification, <em>e.g.</em>, <a 981 * href="https://jcp.org/en/jsr/detail?id=337">JSR 337</a> for 982 * Java SE 8. Features may be removed in a major release, given 983 * advance notice at least one major release ahead of time, and 984 * incompatible changes may be made when justified. The {@code $MAJOR} 985 * version number of JDK 8 is {@code 8}; the {@code $MAJOR} version 986 * number of JDK 9 is {@code 9}. When {@code $MAJOR} is incremented, 987 * all subsequent elements are removed. </p></li> 988 * 989 * <li><p> <a id="minor">{@code $MINOR}</a> --- The minor version 990 * number, incremented for a minor update release that may contain 991 * compatible bug fixes, revisions to standard APIs mandated by a 992 * <a href="https://jcp.org/en/procedures/jcp2#5.3">Maintenance Release</a> 993 * of the relevant Platform Specification, and implementation features 994 * outside the scope of that Specification such as new JDK-specific APIs, 995 * additional service providers, new garbage collectors, and ports to new 996 * hardware architectures. </p></li> 997 * 998 * <li><p> <a id="security">{@code $SECURITY}</a> --- The security 999 * level, incremented for a security update release that contains critical 1000 * fixes including those necessary to improve security. {@code $SECURITY} 1001 * is <strong>not</strong> reset when {@code $MINOR} is incremented. A 1002 * higher value of {@code $SECURITY} for a given {@code $MAJOR} value, 1003 * therefore, always indicates a more secure release, regardless of the 1004 * value of {@code $MINOR}. </p></li> 1005 * 1006 * </ul> 1007 * 1008 * <p> The fourth and later elements of a version number are free for use 1009 * by downstream consumers of this code base. Such a consumer may, 1010 * <em>e.g.</em>, use the fourth element to identify patch releases which 1011 * contain a small number of critical non-security fixes in addition to 1012 * the security fixes in the corresponding security release. </p> 1013 * 1014 * <p> The version number does not include trailing zero elements; 1015 * <em>i.e.</em>, {@code $SECURITY} is omitted if it has the value zero, 1016 * and {@code $MINOR} is omitted if both {@code $MINOR} and {@code 1017 * $SECURITY} have the value zero. </p> 1018 * 1019 * <p> The sequence of numerals in a version number is compared to another 1020 * such sequence in numerical, pointwise fashion; <em>e.g.</em>, {@code 1021 * 9.9.1} is less than {@code 9.10.3}. If one sequence is shorter than 1022 * another then the missing elements of the shorter sequence are 1023 * considered to be less than the corresponding elements of the longer 1024 * sequence; <em>e.g.</em>, {@code 9.1.2} is less than {@code 9.1.2.1}. 1025 * </p> 1026 * 1027 * <h2><a id="verStr">Version strings</a></h2> 1028 * 1029 * <p> A <em>version string</em>, {@code $VSTR}, consists of a version 1030 * number {@code $VNUM}, as described above, optionally followed by 1031 * pre-release and build information, in one of the following formats: 1032 * </p> 1033 * 1034 * <blockquote><pre> 1035 * $VNUM(-$PRE)?\+$BUILD(-$OPT)? 1036 * $VNUM-$PRE(-$OPT)? 1037 * $VNUM(+-$OPT)? 1038 * </pre></blockquote> 1039 * 1040 * <p> where: </p> 1041 * 1042 * <ul> 1043 * 1044 * <li><p> <a id="pre">{@code $PRE}</a>, matching {@code ([a-zA-Z0-9]+)} 1045 * --- A pre-release identifier. Typically {@code ea}, for a 1046 * potentially unstable early-access release under active development, 1047 * or {@code internal}, for an internal developer build. </p></li> 1048 * 1049 * <li><p> <a id="build">{@code $BUILD}</a>, matching {@code 1050 * (0|[1-9][0-9]*)} --- The build number, incremented for each promoted 1051 * build. {@code $BUILD} is reset to {@code 1} when any portion of {@code 1052 * $VNUM} is incremented. </p></li> 1053 * 1054 * <li><p> <a id="opt">{@code $OPT}</a>, matching {@code 1055 * ([-a-zA-Z0-9.]+)} --- Additional build information, if desired. In 1056 * the case of an {@code internal} build this will often contain the date 1057 * and time of the build. </p></li> 1058 * 1059 * </ul> 1060 * 1061 * <p> A version string {@code 10-ea} matches {@code $VNUM = "10"} and 1062 * {@code $PRE = "ea"}. The version string {@code 10+-ea} matches 1063 * {@code $VNUM = "10"} and {@code $OPT = "ea"}. </p> 1064 * 1065 * <p> When comparing two version strings, the value of {@code $OPT}, if 1066 * present, may or may not be significant depending on the chosen 1067 * comparison method. The comparison methods {@link #compareTo(Version) 1068 * compareTo()} and {@link #compareToIgnoreOptional(Version) 1069 * compareToIgnoreOptional()} should be used consistently with the 1070 * corresponding methods {@link #equals(Object) equals()} and {@link 1071 * #equalsIgnoreOptional(Object) equalsIgnoreOptional()}. </p> 1072 * 1073 * <p> A <em>short version string</em>, {@code $SVSTR}, often useful in 1074 * less formal contexts, is a version number optionally followed by a 1075 * pre-release identifier:</p> 1076 * 1077 * <blockquote><pre> 1078 * $VNUM(-$PRE)? 1079 * </pre></blockquote> 1080 * 1081 * <p>This is a <a href="./doc-files/ValueBased.html">value-based</a> 1082 * class; use of identity-sensitive operations (including reference equality 1083 * ({@code ==}), identity hash code, or synchronization) on instances of 1084 * {@code Version} may have unpredictable results and should be avoided. 1085 * </p> 1086 * 1087 * @since 9 1088 */ 1089 public static final class Version 1090 implements Comparable<Version> 1091 { 1092 private final List<Integer> version; 1093 private final Optional<String> pre; 1094 private final Optional<Integer> build; 1095 private final Optional<String> optional; 1096 1097 /* 1098 * List of version number components passed to this constructor MUST 1099 * be at least unmodifiable (ideally immutable). In the case on an 1100 * unmodifiable list, the caller MUST hand the list over to this 1101 * constructor and never change the underlying list. 1102 */ 1103 private Version(List<Integer> unmodifiableListOfVersions, 1104 Optional<String> pre, 1105 Optional<Integer> build, 1106 Optional<String> optional) 1107 { 1108 this.version = unmodifiableListOfVersions; 1109 this.pre = pre; 1110 this.build = build; 1111 this.optional = optional; 1112 } 1113 1114 /** 1115 * Parses the given string as a valid 1116 * <a href="#verStr">version string</a> containing a 1117 * <a href="#verNum">version number</a> followed by pre-release and 1118 * build information. 1119 * 1120 * @param s 1121 * A string to interpret as a version 1122 * 1123 * @throws IllegalArgumentException 1124 * If the given string cannot be interpreted as a valid 1125 * version 1126 * 1127 * @throws NullPointerException 1128 * If the given string is {@code null} 1129 * 1130 * @throws NumberFormatException 1131 * If an element of the version number or the build number 1132 * cannot be represented as an {@link Integer} 1133 * 1134 * @return The Version of the given string 1135 */ 1136 public static Version parse(String s) { 1137 if (s == null) 1138 throw new NullPointerException(); 1139 1140 // Shortcut to avoid initializing VersionPattern when creating 1141 // major version constants during startup 1142 if (isSimpleNumber(s)) { 1143 return new Version(List.of(Integer.parseInt(s)), 1144 Optional.empty(), Optional.empty(), Optional.empty()); 1145 } 1146 Matcher m = VersionPattern.VSTR_PATTERN.matcher(s); 1147 if (!m.matches()) 1148 throw new IllegalArgumentException("Invalid version string: '" 1149 + s + "'"); 1150 1151 // $VNUM is a dot-separated list of integers of arbitrary length 1152 String[] split = m.group(VersionPattern.VNUM_GROUP).split("\\."); 1153 Integer[] version = new Integer[split.length]; 1154 for (int i = 0; i < split.length; i++) { 1155 version[i] = Integer.parseInt(split[i]); 1156 } 1157 1158 Optional<String> pre = Optional.ofNullable( 1159 m.group(VersionPattern.PRE_GROUP)); 1160 1161 String b = m.group(VersionPattern.BUILD_GROUP); 1162 // $BUILD is an integer 1163 Optional<Integer> build = (b == null) 1164 ? Optional.empty() 1165 : Optional.of(Integer.parseInt(b)); 1166 1167 Optional<String> optional = Optional.ofNullable( 1168 m.group(VersionPattern.OPT_GROUP)); 1169 1170 // empty '+' 1171 if ((m.group(VersionPattern.PLUS_GROUP) != null) 1172 && !build.isPresent()) { 1173 if (optional.isPresent()) { 1174 if (pre.isPresent()) 1175 throw new IllegalArgumentException("'+' found with" 1176 + " pre-release and optional components:'" + s 1177 + "'"); 1178 } else { 1179 throw new IllegalArgumentException("'+' found with neither" 1180 + " build or optional components: '" + s + "'"); 1181 } 1182 } 1183 return new Version(List.of(version), pre, build, optional); 1184 } 1185 1186 private static boolean isSimpleNumber(String s) { 1187 for (int i = 0; i < s.length(); i++) { 1188 char c = s.charAt(i); 1189 char lowerBound = (i > 0) ? '0' : '1'; 1190 if (c < lowerBound || c > '9') { 1191 return false; 1192 } 1193 } 1194 return true; 1195 } 1196 1197 /** 1198 * Returns the <a href="#major">major</a> version number. 1199 * 1200 * @return The major version number 1201 */ 1202 public int major() { 1203 return version.get(0); 1204 } 1205 1206 /** 1207 * Returns the <a href="#minor">minor</a> version number or zero if it 1208 * was not set. 1209 * 1210 * @return The minor version number or zero if it was not set 1211 */ 1212 public int minor() { 1213 return (version.size() > 1 ? version.get(1) : 0); 1214 } 1215 1216 /** 1217 * Returns the <a href="#security">security</a> version number or zero 1218 * if it was not set. 1219 * 1220 * @return The security version number or zero if it was not set 1221 */ 1222 public int security() { 1223 return (version.size() > 2 ? version.get(2) : 0); 1224 } 1225 1226 /** 1227 * Returns an unmodifiable {@link java.util.List List} of the 1228 * integer numerals contained in the <a href="#verNum">version 1229 * number</a>. The {@code List} always contains at least one 1230 * element corresponding to the <a href="#major">major version 1231 * number</a>. 1232 * 1233 * @return An unmodifiable list of the integer numerals 1234 * contained in the version number 1235 */ 1236 public List<Integer> version() { 1237 return version; 1238 } 1239 1240 /** 1241 * Returns the optional <a href="#pre">pre-release</a> information. 1242 * 1243 * @return The optional pre-release information as a String 1244 */ 1245 public Optional<String> pre() { 1246 return pre; 1247 } 1248 1249 /** 1250 * Returns the <a href="#build">build number</a>. 1251 * 1252 * @return The optional build number. 1253 */ 1254 public Optional<Integer> build() { 1255 return build; 1256 } 1257 1258 /** 1259 * Returns <a href="#opt">optional</a> additional identifying build 1260 * information. 1261 * 1262 * @return Additional build information as a String 1263 */ 1264 public Optional<String> optional() { 1265 return optional; 1266 } 1267 1268 /** 1269 * Compares this version to another. 1270 * 1271 * <p> Each of the components in the <a href="#verStr">version</a> is 1272 * compared in the following order of precedence: version numbers, 1273 * pre-release identifiers, build numbers, optional build information. 1274 * </p> 1275 * 1276 * <p> Comparison begins by examining the sequence of version numbers. 1277 * If one sequence is shorter than another, then the missing elements 1278 * of the shorter sequence are considered to be less than the 1279 * corresponding elements of the longer sequence. </p> 1280 * 1281 * <p> A version with a pre-release identifier is always considered to 1282 * be less than a version without one. Pre-release identifiers are 1283 * compared numerically when they consist only of digits, and 1284 * lexicographically otherwise. Numeric identifiers are considered to 1285 * be less than non-numeric identifiers. </p> 1286 * 1287 * <p> A version without a build number is always less than one with a 1288 * build number; otherwise build numbers are compared numerically. </p> 1289 * 1290 * <p> The optional build information is compared lexicographically. 1291 * During this comparison, a version with optional build information is 1292 * considered to be greater than a version without one. </p> 1293 * 1294 * @param obj 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 obj) { 1306 return compare(obj, 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> This method provides ordering which is consistent with 1318 * {@code equalsIgnoreOptional()}. </p> 1319 * 1320 * @param obj 1321 * The object to be compared 1322 * 1323 * @return A negative integer, zero, or a positive integer if this 1324 * {@code Version} is less than, equal to, or greater than the 1325 * given {@code Version} 1326 * 1327 * @throws NullPointerException 1328 * If the given object is {@code null} 1329 */ 1330 public int compareToIgnoreOptional(Version obj) { 1331 return compare(obj, true); 1332 } 1333 1334 private int compare(Version obj, boolean ignoreOpt) { 1335 if (obj == null) 1336 throw new NullPointerException(); 1337 1338 int ret = compareVersion(obj); 1339 if (ret != 0) 1340 return ret; 1341 1342 ret = comparePre(obj); 1343 if (ret != 0) 1344 return ret; 1345 1346 ret = compareBuild(obj); 1347 if (ret != 0) 1348 return ret; 1349 1350 if (!ignoreOpt) 1351 return compareOptional(obj); 1352 1353 return 0; 1354 } 1355 1356 private int compareVersion(Version obj) { 1357 int size = version.size(); 1358 int oSize = obj.version().size(); 1359 int min = Math.min(size, oSize); 1360 for (int i = 0; i < min; i++) { 1361 int val = version.get(i); 1362 int oVal = obj.version().get(i); 1363 if (val != oVal) 1364 return val - oVal; 1365 } 1366 return size - oSize; 1367 } 1368 1369 private int comparePre(Version obj) { 1370 Optional<String> oPre = obj.pre(); 1371 if (!pre.isPresent()) { 1372 if (oPre.isPresent()) 1373 return 1; 1374 } else { 1375 if (!oPre.isPresent()) 1376 return -1; 1377 String val = pre.get(); 1378 String oVal = oPre.get(); 1379 if (val.matches("\\d+")) { 1380 return (oVal.matches("\\d+") 1381 ? (new BigInteger(val)).compareTo(new BigInteger(oVal)) 1382 : -1); 1383 } else { 1384 return (oVal.matches("\\d+") 1385 ? 1 1386 : val.compareTo(oVal)); 1387 } 1388 } 1389 return 0; 1390 } 1391 1392 private int compareBuild(Version obj) { 1393 Optional<Integer> oBuild = obj.build(); 1394 if (oBuild.isPresent()) { 1395 return (build.isPresent() 1396 ? build.get().compareTo(oBuild.get()) 1397 : -1); 1398 } else if (build.isPresent()) { 1399 return 1; 1400 } 1401 return 0; 1402 } 1403 1404 private int compareOptional(Version obj) { 1405 Optional<String> oOpt = obj.optional(); 1406 if (!optional.isPresent()) { 1407 if (oOpt.isPresent()) 1408 return -1; 1409 } else { 1410 if (!oOpt.isPresent()) 1411 return 1; 1412 return optional.get().compareTo(oOpt.get()); 1413 } 1414 return 0; 1415 } 1416 1417 /** 1418 * Returns a string representation of this version. 1419 * 1420 * @return The version string 1421 */ 1422 @Override 1423 public String toString() { 1424 StringBuilder sb 1425 = new StringBuilder(version.stream() 1426 .map(Object::toString) 1427 .collect(Collectors.joining("."))); 1428 1429 pre.ifPresent(v -> sb.append("-").append(v)); 1430 1431 if (build.isPresent()) { 1432 sb.append("+").append(build.get()); 1433 if (optional.isPresent()) 1434 sb.append("-").append(optional.get()); 1435 } else { 1436 if (optional.isPresent()) { 1437 sb.append(pre.isPresent() ? "-" : "+-"); 1438 sb.append(optional.get()); 1439 } 1440 } 1441 1442 return sb.toString(); 1443 } 1444 1445 /** 1446 * Determines whether this {@code Version} is equal to another object. 1447 * 1448 * <p> Two {@code Version}s are equal if and only if they represent the 1449 * same version string. 1450 * 1451 * @param obj 1452 * The object to which this {@code Version} is to be compared 1453 * 1454 * @return {@code true} if, and only if, the given object is a {@code 1455 * Version} that is identical to this {@code Version} 1456 * 1457 */ 1458 @Override 1459 public boolean equals(Object obj) { 1460 boolean ret = equalsIgnoreOptional(obj); 1461 if (!ret) 1462 return false; 1463 1464 Version that = (Version)obj; 1465 return (this.optional().equals(that.optional())); 1466 } 1467 1468 /** 1469 * Determines whether this {@code Version} is equal to another 1470 * disregarding optional build information. 1471 * 1472 * <p> Two {@code Version}s are equal if and only if they represent the 1473 * same version string disregarding the optional build information. 1474 * 1475 * @param obj 1476 * The object to which this {@code Version} is to be compared 1477 * 1478 * @return {@code true} if, and only if, the given object is a {@code 1479 * Version} that is identical to this {@code Version} 1480 * ignoring the optional build information 1481 * 1482 */ 1483 public boolean equalsIgnoreOptional(Object obj) { 1484 if (this == obj) 1485 return true; 1486 if (!(obj instanceof Version)) 1487 return false; 1488 1489 Version that = (Version)obj; 1490 return (this.version().equals(that.version()) 1491 && this.pre().equals(that.pre()) 1492 && this.build().equals(that.build())); 1493 } 1494 1495 /** 1496 * Returns the hash code of this version. 1497 * 1498 * @return The hashcode of this version 1499 */ 1500 @Override 1501 public int hashCode() { 1502 int h = 1; 1503 int p = 17; 1504 1505 h = p * h + version.hashCode(); 1506 h = p * h + pre.hashCode(); 1507 h = p * h + build.hashCode(); 1508 h = p * h + optional.hashCode(); 1509 1510 return h; 1511 } 1512 } 1513 1514 private static class VersionPattern { 1515 // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)? 1516 // RE limits the format of version strings 1517 // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))? 1518 1519 private static final String VNUM 1520 = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)"; 1521 private static final String PRE = "(?:-(?<PRE>[a-zA-Z0-9]+))?"; 1522 private static final String BUILD 1523 = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?"; 1524 private static final String OPT = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?"; 1525 private static final String VSTR_FORMAT = VNUM + PRE + BUILD + OPT; 1526 1527 static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT); 1528 1529 static final String VNUM_GROUP = "VNUM"; 1530 static final String PRE_GROUP = "PRE"; 1531 static final String PLUS_GROUP = "PLUS"; 1532 static final String BUILD_GROUP = "BUILD"; 1533 static final String OPT_GROUP = "OPT"; 1534 } 1535 }