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