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