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