-
Notifications
You must be signed in to change notification settings - Fork 668
/
Runtime.java
1525 lines (1392 loc) · 66.1 KB
/
Runtime.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
/**
* Every Java application has a single instance of class
* {@code Runtime} that allows the application to interface with
* the environment in which the application is running. The current
* runtime can be obtained from the {@code getRuntime} method.
* <p>
* An application cannot create its own instance of this class.
*
* @author unascribed
* @see java.lang.Runtime#getRuntime()
* @since 1.0
*/
// 运行时对象,持有一些底层操作工具方法
public class Runtime {
// 单例
private static final Runtime currentRuntime = new Runtime();
private static Version version; // 当前JDK版本
/*▼ 构造器/工厂 ████████████████████████████████████████████████████████████████████████████████┓ */
/** Don't let anyone else instantiate this class */
private Runtime() {
}
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class {@code Runtime} are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the {@code Runtime} object associated with the current
* Java application.
*/
// 返回Runtime对象(工厂方法)
public static Runtime getRuntime() {
return currentRuntime;
}
/*▲ 构造器/工厂 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 关机回调 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Registers a new virtual-machine shutdown hook.
*
* <p> The Java virtual machine <i>shuts down</i> in response to two kinds
* of events:
*
* <ul>
*
* <li> The program <i>exits</i> normally, when the last non-daemon
* thread exits or when the {@link #exit exit} (equivalently,
* {@link System#exit(int) System.exit}) method is invoked, or
*
* <li> The virtual machine is <i>terminated</i> in response to a
* user interrupt, such as typing {@code ^C}, or a system-wide event,
* such as user logoff or system shutdown.
*
* </ul>
*
* <p> A <i>shutdown hook</i> is simply an initialized but unstarted
* thread. When the virtual machine begins its shutdown sequence it will
* start all registered shutdown hooks in some unspecified order and let
* them run concurrently. When all the hooks have finished it will then
* halt. Note that daemon threads will continue to run during the shutdown
* sequence, as will non-daemon threads if shutdown was initiated by
* invoking the {@link #exit exit} method.
*
* <p> Once the shutdown sequence has begun it can be stopped only by
* invoking the {@link #halt halt} method, which forcibly
* terminates the virtual machine.
*
* <p> Once the shutdown sequence has begun it is impossible to register a
* new shutdown hook or de-register a previously-registered hook.
* Attempting either of these operations will cause an
* {@link IllegalStateException} to be thrown.
*
* <p> Shutdown hooks run at a delicate time in the life cycle of a virtual
* machine and should therefore be coded defensively. They should, in
* particular, be written to be thread-safe and to avoid deadlocks insofar
* as possible. They should also not rely blindly upon services that may
* have registered their own shutdown hooks and therefore may themselves in
* the process of shutting down. Attempts to use other thread-based
* services such as the AWT event-dispatch thread, for example, may lead to
* deadlocks.
*
* <p> Shutdown hooks should also finish their work quickly. When a
* program invokes {@link #exit exit} the expectation is
* that the virtual machine will promptly shut down and exit. When the
* virtual machine is terminated due to user logoff or system shutdown the
* underlying operating system may only allow a fixed amount of time in
* which to shut down and exit. It is therefore inadvisable to attempt any
* user interaction or to perform a long-running computation in a shutdown
* hook.
*
* <p> Uncaught exceptions are handled in shutdown hooks just as in any
* other thread, by invoking the
* {@link ThreadGroup#uncaughtException uncaughtException} method of the
* thread's {@link ThreadGroup} object. The default implementation of this
* method prints the exception's stack trace to {@link System#err} and
* terminates the thread; it does not cause the virtual machine to exit or
* halt.
*
* <p> In rare circumstances the virtual machine may <i>abort</i>, that is,
* stop running without shutting down cleanly. This occurs when the
* virtual machine is terminated externally, for example with the
* {@code SIGKILL} signal on Unix or the {@code TerminateProcess} call on
* Microsoft Windows. The virtual machine may also abort if a native
* method goes awry by, for example, corrupting internal data structures or
* attempting to access nonexistent memory. If the virtual machine aborts
* then no guarantee can be made about whether or not any shutdown hooks
* will be run.
*
* @param hook An initialized but unstarted {@link Thread} object
*
* @throws IllegalArgumentException If the specified hook has already been registered,
* or if it can be determined that the hook is already running or
* has already been run
* @throws IllegalStateException If the virtual machine is already in the process
* of shutting down
* @throws SecurityException If a security manager is present and it denies
* {@link RuntimePermission}("shutdownHooks")
* @see #removeShutdownHook
* @see #halt(int)
* @see #exit(int)
* @since 1.3
*/
/*
* 在JVM注册一个钩子线程,该线程在以下情形中被执行:
*
* 当最后一个非守护程序线程退出;
* 或调用Runtime#exit方法(与System.exit()等效);
* 或被用户中断(^C);
* 或被系统自然中断;
*/
public void addShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if(sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
// 注册用户级别的钩子
ApplicationShutdownHooks.add(hook);
}
/**
* De-registers a previously-registered virtual-machine shutdown hook.
*
* @param hook the hook to remove
*
* @return {@code true} if the specified hook had previously been
* registered and was successfully de-registered, {@code false}
* otherwise.
*
* @throws IllegalStateException If the virtual machine is already in the process of shutting
* down
* @throws SecurityException If a security manager is present and it denies
* {@link RuntimePermission}("shutdownHooks")
* @see #addShutdownHook
* @see #exit(int)
* @since 1.3
*/
// 移除注册的钩子线程
public boolean removeShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if(sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
// 移除用户级别的钩子
return ApplicationShutdownHooks.remove(hook);
}
/*▲ 关机回调 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 关机 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Terminates the currently running Java virtual machine by initiating its
* shutdown sequence. This method never returns normally. The argument
* serves as a status code; by convention, a nonzero status code indicates
* abnormal termination.
*
* <p> All registered {@linkplain #addShutdownHook shutdown hooks}, if any,
* are started in some unspecified order and allowed to run concurrently
* until they finish. Once this is done the virtual machine
* {@linkplain #halt halts}.
*
* <p> If this method is invoked after all shutdown hooks have already
* been run and the status is nonzero then this method halts the
* virtual machine with the given status code. Otherwise, this method
* blocks indefinitely.
*
* <p> The {@link System#exit(int) System.exit} method is the
* conventional and convenient means of invoking this method.
*
* @param status Termination status. By convention, a nonzero status code
* indicates abnormal termination.
*
* @throws SecurityException If a security manager is present and its
* {@link SecurityManager#checkExit checkExit} method does not permit
* exiting with the specified status
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkExit(int)
* @see #addShutdownHook
* @see #removeShutdownHook
* @see #halt(int)
*/
// 执行所有关机回调,并退出(关闭)虚拟机
public void exit(int status) {
SecurityManager security = System.getSecurityManager();
if(security != null) {
security.checkExit(status);
}
Shutdown.exit(status);
}
/**
* Forcibly terminates the currently running Java virtual machine. This
* method never returns normally.
*
* <p> This method should be used with extreme caution. Unlike the
* {@link #exit exit} method, this method does not cause shutdown
* hooks to be started. If the shutdown sequence has already been
* initiated then this method does not wait for any running
* shutdown hooks to finish their work.
*
* @param status Termination status. By convention, a nonzero status code
* indicates abnormal termination. If the {@link Runtime#exit exit}
* (equivalently, {@link System#exit(int) System.exit}) method
* has already been invoked then this status code
* will override the status code passed to that method.
*
* @throws SecurityException If a security manager is present and its
* {@link SecurityManager#checkExit checkExit} method
* does not permit an exit with the specified status
* @see #exit
* @see #addShutdownHook
* @see #removeShutdownHook
* @since 1.3
*/
/*
* 直接关闭虚拟机,不会执行关机回调
*
* status为关闭时的状态码,一般用非0的状态码表示异常退出状态
*/
public void halt(int status) {
SecurityManager sm = System.getSecurityManager();
if(sm != null) {
sm.checkExit(status);
}
// 通知虚拟机程序该终止了
Shutdown.beforeHalt();
// 关闭虚拟机
Shutdown.halt(status);
}
/*▲ 关机 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 进程/命令行 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Executes the specified string command in a separate process.
*
* <p>This is a convenience method. An invocation of the form
* {@code exec(command)}
* behaves in exactly the same way as the invocation
* {@link #exec(String, String[], File) exec}{@code (command, null, null)}.
*
* @param command a specified system command.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code command} is {@code null}
* @throws IllegalArgumentException If {@code command} is empty
* @see #exec(String[], String[], File)
* @see ProcessBuilder
*/
// 构造执行指定命令的进程
public Process exec(String command) throws IOException {
return exec(command, null, null);
}
/**
* Executes the specified string command in a separate process with the
* specified environment.
*
* <p>This is a convenience method. An invocation of the form
* {@code exec(command, envp)}
* behaves in exactly the same way as the invocation
* {@link #exec(String, String[], File) exec}{@code (command, envp, null)}.
*
* @param command a specified system command.
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* {@code null} if the subprocess should inherit
* the environment of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code command} is {@code null},
* or one of the elements of {@code envp} is {@code null}
* @throws IllegalArgumentException If {@code command} is empty
* @see #exec(String[], String[], File)
* @see ProcessBuilder
*/
// 构造执行指定命令的进程,envp为进程设置环境变量
public Process exec(String command, String[] envp) throws IOException {
return exec(command, envp, null);
}
/**
* Executes the specified string command in a separate process with the
* specified environment and working directory.
*
* <p>This is a convenience method. An invocation of the form
* {@code exec(command, envp, dir)}
* behaves in exactly the same way as the invocation
* {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, dir)},
* where {@code cmdarray} is an array of all the tokens in
* {@code command}.
*
* <p>More precisely, the {@code command} string is broken
* into tokens using a {@link StringTokenizer} created by the call
* {@code new {@link StringTokenizer}(command)} with no
* further modification of the character categories. The tokens
* produced by the tokenizer are then placed in the new string
* array {@code cmdarray}, in the same order.
*
* @param command a specified system command.
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* {@code null} if the subprocess should inherit
* the environment of the current process.
* @param dir the working directory of the subprocess, or
* {@code null} if the subprocess should inherit
* the working directory of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code command} is {@code null},
* or one of the elements of {@code envp} is {@code null}
* @throws IllegalArgumentException If {@code command} is empty
* @see ProcessBuilder
* @since 1.3
*/
// 构造执行指定命令的进程,envp为进程设置环境变量,dir为进程设置工作目录
public Process exec(String command, String[] envp, File dir) throws IOException {
if(command.length() == 0) {
throw new IllegalArgumentException("Empty command");
}
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for(int i = 0; st.hasMoreTokens(); i++) {
cmdarray[i] = st.nextToken();
}
return exec(cmdarray, envp, dir);
}
/**
* Executes the specified command and arguments in a separate process.
*
* <p>This is a convenience method. An invocation of the form
* {@code exec(cmdarray)}
* behaves in exactly the same way as the invocation
* {@link #exec(String[], String[], File) exec}{@code (cmdarray, null, null)}.
*
* @param cmdarray array containing the command to call and
* its arguments.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code cmdarray} is {@code null},
* or one of the elements of {@code cmdarray} is {@code null}
* @throws IndexOutOfBoundsException If {@code cmdarray} is an empty array
* (has length {@code 0})
* @see ProcessBuilder
*/
// 构造执行指定命令的进程,命令行以数组cmdarray形式给出
public Process exec(String cmdarray[]) throws IOException {
return exec(cmdarray, null, null);
}
/**
* Executes the specified command and arguments in a separate process
* with the specified environment.
*
* <p>This is a convenience method. An invocation of the form
* {@code exec(cmdarray, envp)}
* behaves in exactly the same way as the invocation
* {@link #exec(String[], String[], File) exec}{@code (cmdarray, envp, null)}.
*
* @param cmdarray array containing the command to call and
* its arguments.
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* {@code null} if the subprocess should inherit
* the environment of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code cmdarray} is {@code null},
* or one of the elements of {@code cmdarray} is {@code null},
* or one of the elements of {@code envp} is {@code null}
* @throws IndexOutOfBoundsException If {@code cmdarray} is an empty array
* (has length {@code 0})
* @see ProcessBuilder
*/
// 构造执行指定命令的进程,命令行以数组cmdarray形式给出,envp为进程设置环境变量
public Process exec(String[] cmdarray, String[] envp) throws IOException {
return exec(cmdarray, envp, null);
}
/**
* Executes the specified command and arguments in a separate process with
* the specified environment and working directory.
*
* <p>Given an array of strings {@code cmdarray}, representing the
* tokens of a command line, and an array of strings {@code envp},
* representing "environment" variable settings, this method creates
* a new process in which to execute the specified command.
*
* <p>This method checks that {@code cmdarray} is a valid operating
* system command. Which commands are valid is system-dependent,
* but at the very least the command must be a non-empty list of
* non-null strings.
*
* <p>If {@code envp} is {@code null}, the subprocess inherits the
* environment settings of the current process.
*
* <p>A minimal set of system dependent environment variables may
* be required to start a process on some operating systems.
* As a result, the subprocess may inherit additional environment variable
* settings beyond those in the specified environment.
*
* <p>{@link ProcessBuilder#start()} is now the preferred way to
* start a process with a modified environment.
*
* <p>The working directory of the new subprocess is specified by {@code dir}.
* If {@code dir} is {@code null}, the subprocess inherits the
* current working directory of the current process.
*
* <p>If a security manager exists, its
* {@link SecurityManager#checkExec checkExec}
* method is invoked with the first component of the array
* {@code cmdarray} as its argument. This may result in a
* {@link SecurityException} being thrown.
*
* <p>Starting an operating system process is highly system-dependent.
* Among the many things that can go wrong are:
* <ul>
* <li>The operating system program file was not found.
* <li>Access to the program file was denied.
* <li>The working directory does not exist.
* </ul>
*
* <p>In such cases an exception will be thrown. The exact nature
* of the exception is system-dependent, but it will always be a
* subclass of {@link IOException}.
*
* <p>If the operating system does not support the creation of
* processes, an {@link UnsupportedOperationException} will be thrown.
*
* @param cmdarray array containing the command to call and
* its arguments.
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* {@code null} if the subprocess should inherit
* the environment of the current process.
* @param dir the working directory of the subprocess, or
* {@code null} if the subprocess should inherit
* the working directory of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
* @throws UnsupportedOperationException If the operating system does not support the creation of processes.
* @throws IOException If an I/O error occurs
* @throws NullPointerException If {@code cmdarray} is {@code null},
* or one of the elements of {@code cmdarray} is {@code null},
* or one of the elements of {@code envp} is {@code null}
* @throws IndexOutOfBoundsException If {@code cmdarray} is an empty array
* (has length {@code 0})
* @see ProcessBuilder
* @since 1.3
*/
// 构造执行指定命令的进程,命令行以数组cmdarray形式给出,envp为进程设置环境变量,dir为进程设置工作目录
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException {
return new ProcessBuilder(cmdarray).environment(envp) // 为进程构造器设置环境变量
.directory(dir) // 为进程构造器设定工作目录
.start();
}
/*▲ 进程/命令行 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 清理 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Runs the garbage collector.
* Calling this method suggests that the Java virtual machine expend
* effort toward recycling unused objects in order to make the memory
* they currently occupy available for quick reuse. When control
* returns from the method call, the virtual machine has made
* its best effort to recycle all discarded objects.
* <p>
* The name {@code gc} stands for "garbage
* collector". The virtual machine performs this recycling
* process automatically as needed, in a separate thread, even if the
* {@code gc} method is not invoked explicitly.
* <p>
* The method {@link System#gc()} is the conventional and convenient
* means of invoking this method.
*/
// 通知虚拟机执行垃圾回收操作
public native void gc();
/**
* Runs the finalization methods of any objects pending finalization.
* Calling this method suggests that the Java virtual machine expend
* effort toward running the {@code finalize} methods of objects
* that have been found to be discarded but whose {@code finalize}
* methods have not yet been run. When control returns from the
* method call, the virtual machine has made a best effort to
* complete all outstanding finalizations.
* <p>
* The virtual machine performs the finalization process
* automatically as needed, in a separate thread, if the
* {@code runFinalization} method is not invoked explicitly.
* <p>
* The method {@link System#runFinalization()} is the conventional
* and convenient means of invoking this method.
*
* @see java.lang.Object#finalize()
*/
// 手动触发Finalizer的清理操作,不用等待FinalizerThread
public void runFinalization() {
SharedSecrets.getJavaLangRefAccess().runFinalization();
}
/*▲ 清理 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 信息 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Returns the maximum amount of memory that the Java virtual machine will attempt to use.
* If there is no inherent limit then the value {@link java.lang.Long#MAX_VALUE} will be returned.
*
* @return the maximum amount of memory that the virtual machine will attempt to use, measured in bytes
*
* @since 1.4
*/
/*
* 返回虚拟机可用内存的上限(字节数),可通过-Xmx设置
*
* max >= total >= free
*/
public native long maxMemory();
/**
* Returns the total amount of memory in the Java virtual machine.
* The value returned by this method may vary over time, depending on the host environment.
* <p>
* Note that the amount of memory required to hold an object of any given type may be implementation-dependent.
*
* @return the total amount of memory currently available for current and future objects, measured in bytes.
*/
/*
* 返回虚拟机当前可用的最大内存(字节数),会动态增长或减少,初始值可通过-Xms设置
*
* max >= total >= free
*/
public native long totalMemory();
/**
* Returns the amount of free memory in the Java Virtual Machine.
* Calling the {@code gc} method may result in increasing the value returned by {@code freeMemory.}
*
* @return an approximation to the total amount of memory currently available for future allocated objects, measured in bytes.
*/
/*
* 返回虚拟机当前未使用的内存(字节数),会动态变化;
* freeMemory的上限是totalMemory,而totalMemory的上限是maxMemory。
*
* max >= total >= free
*/
public native long freeMemory();
/**
* Returns the number of processors available to the Java virtual machine.
*
* <p> This value may change during a particular invocation of the virtual
* machine. Applications that are sensitive to the number of available
* processors should therefore occasionally poll this property and adjust
* their resource usage appropriately. </p>
*
* @return the maximum number of processors available to the virtual
* machine; never smaller than one
*
* @since 1.4
*/
// 返回虚拟机可用的处理器数量
public native int availableProcessors();
/**
* Returns the version of the Java Runtime Environment as a {@link Version}.
*
* @return the {@link Version} of the Java Runtime Environment
*
* @since 9
*/
// 返回当前JDK版本信息
public static Version version() {
if(version == null) {
version = new Version(VersionProps.versionNumbers(), VersionProps.pre(), VersionProps.build(), VersionProps.optional());
}
return version;
}
/*▲ 信息 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 本地库 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Loads the native library specified by the filename argument. The filename
* argument must be an absolute path name.
* (for example
* {@code Runtime.getRuntime().load("/home/avh/lib/libX11.so");}).
*
* If the filename argument, when stripped of any platform-specific library
* prefix, path, and file extension, indicates a library whose name is,
* for example, L, and a native library called L is statically linked
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the file
* system.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
* <p>
* First, if there is a security manager, its {@code checkLink}
* method is called with the {@code filename} as its argument.
* This may result in a security exception.
* <p>
* This is similar to the method {@link #loadLibrary(String)}, but it
* accepts a general file name as an argument rather than just a library
* name, allowing any file of native code to be loaded.
* <p>
* The method {@link System#load(String)} is the conventional and
* convenient means of invoking this method.
*
* @param filename the file to load.
*
* @throws SecurityException if a security manager exists and its
* {@code checkLink} method doesn't allow
* loading of the specified dynamic library
* @throws UnsatisfiedLinkError if either the filename is not an
* absolute path name, the native library is not statically
* linked with the VM, or the library cannot be mapped to
* a native library image by the host system.
* @throws NullPointerException if {@code filename} is
* {@code null}
* @see java.lang.Runtime#getRuntime()
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
/*
* 加载指定名称的本地库(要求filename是本地库的绝对路径)
* 发起加载操作的是load()方法的调用者所处的类(忽略反射栈帧)
*/
@CallerSensitive
public void load(String filename) {
load0(Reflection.getCallerClass(), filename);
}
/**
* Loads the native library specified by the {@code libname}
* argument. The {@code libname} argument must not contain any platform
* specific prefix, file extension or path. If a native library
* called {@code libname} is statically linked with the VM, then the
* JNI_OnLoad_{@code libname} function exported by the library is invoked.
* See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
* for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
* dependent manner.
* <p>
* First, if there is a security manager, its {@code checkLink}
* method is called with the {@code libname} as its argument.
* This may result in a security exception.
* <p>
* The method {@link System#loadLibrary(String)} is the conventional
* and convenient means of invoking this method. If native
* methods are to be used in the implementation of a class, a standard
* strategy is to put the native code in a library file (call it
* {@code LibFile}) and then to put a static initializer:
* <blockquote><pre>
* static { System.loadLibrary("LibFile"); }
* </pre></blockquote>
* within the class declaration. When the class is loaded and
* initialized, the necessary native code implementation for the native
* methods will then be loaded as well.
* <p>
* If this method is called more than once with the same library
* name, the second and subsequent calls are ignored.
*
* @param libname the name of the library.
*
* @throws SecurityException if a security manager exists and its
* {@code checkLink} method doesn't allow
* loading of the specified dynamic library
* @throws UnsatisfiedLinkError if either the libname argument
* contains a file path, the native library is not statically
* linked with the VM, or the library cannot be mapped to a
* native library image by the host system.
* @throws NullPointerException if {@code libname} is
* {@code null}
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
/*
* 加载指定名称的本地库,如"net"是指本地网络库
* 发起加载操作的是loadLibrary()方法的调用者所处的类(忽略反射栈帧)
*/
@CallerSensitive
public void loadLibrary(String libname) {
loadLibrary0(Reflection.getCallerClass(), libname);
}
// 加载指定名称的本地库(要求filename是本地库的绝对路径)
synchronized void load0(Class<?> fromClass, String filename) {
SecurityManager security = System.getSecurityManager();
if(security != null) {
security.checkLink(filename);
}
// 如果filename不是绝对路径,则抛异常
if(!(new File(filename).isAbsolute())) {
throw new UnsatisfiedLinkError("Expecting an absolute path of the library: " + filename);
}
// 加载指定名称的本地库
ClassLoader.loadLibrary(fromClass, filename, true);
}
// 加载指定名称的本地库,如"net"是指本地网络库
synchronized void loadLibrary0(Class<?> fromClass, String libname) {
SecurityManager security = System.getSecurityManager();
if(security != null) {
security.checkLink(libname);
}
// 如果libname包含路径内部的分隔符,则抛异常
if(libname.indexOf((int) File.separatorChar) != -1) {
throw new UnsatisfiedLinkError("Directory separator should not appear in library name: " + libname);
}
// 加载指定名称的本地库
ClassLoader.loadLibrary(fromClass, libname, false);
}
/*▲ 本地库 ███████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 杂项 ███████████████████████████████████████████████████████████████████████████████┓ */
/**
* Not implemented, does nothing.
*
* @param on ignored
*
* @deprecated This method was intended to control instruction tracing.
* It has been superseded by JVM-specific tracing mechanisms.
* This method is subject to removal in a future version of Java SE.
*/
@Deprecated(since = "9", forRemoval = true)
public void traceInstructions(boolean on) {
}
/**
* Not implemented, does nothing.
*
* @param on ignored
*
* @deprecated This method was intended to control method call tracing.
* It has been superseded by JVM-specific tracing mechanisms.
* This method is subject to removal in a future version of Java SE.
*/
@Deprecated(since = "9", forRemoval = true)
public void traceMethodCalls(boolean on) {
}
/*▲ 杂项 ███████████████████████████████████████████████████████████████████████████████┛ */
// 版本号正则
private static class VersionPattern {
// $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
// RE limits the format of version strings
// ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
static final String VNUM_GROUP = "VNUM";
static final String PRE_GROUP = "PRE";
static final String PLUS_GROUP = "PLUS";
static final String BUILD_GROUP = "BUILD";
static final String OPT_GROUP = "OPT";
private static final String VNUM = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
private static final String PRE = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
private static final String BUILD = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
private static final String OPT = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
private static final String VSTR_FORMAT = VNUM + PRE + BUILD + OPT;
static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
}
/**
* A representation of a version string for an implementation of the
* Java SE Platform. A version string consists of a version number
* optionally followed by pre-release and build information.
*
* <h2><a id="verNum">Version numbers</a></h2>
*
* <p> A <em>version number</em>, {@code $VNUM}, is a non-empty sequence of
* elements separated by period characters (U+002E). An element is either
* zero, or an unsigned integer numeral without leading zeros. The final
* element in a version number must not be zero. When an element is
* incremented, all subsequent elements are removed. The format is: </p>
*
* <blockquote><pre>
* [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
* </pre></blockquote>
*
* <p> The sequence may be of arbitrary length but the first four elements
* are assigned specific meanings, as follows:</p>
*
* <blockquote><pre>
* $FEATURE.$INTERIM.$UPDATE.$PATCH
* </pre></blockquote>
*
* <ul>
*
* <li><p> <a id="FEATURE">{@code $FEATURE}</a> — The
* feature-release counter, incremented for every feature release
* regardless of release content. Features may be added in a feature
* release; they may also be removed, if advance notice was given at least
* one feature release ahead of time. Incompatible changes may be made
* when justified. </p></li>
*
* <li><p> <a id="INTERIM">{@code $INTERIM}</a> — The
* interim-release counter, incremented for non-feature releases that
* contain compatible bug fixes and enhancements but no incompatible
* changes, no feature removals, and no changes to standard APIs.
* </p></li>
*
* <li><p> <a id="UPDATE">{@code $UPDATE}</a> — The update-release
* counter, incremented for compatible update releases that fix security
* issues, regressions, and bugs in newer features. </p></li>
*
* <li><p> <a id="PATCH">{@code $PATCH}</a> — The emergency
* patch-release counter, incremented only when it's necessary to produce
* an emergency release to fix a critical issue. </p></li>
*
* </ul>
*
* <p> The fifth and later elements of a version number are free for use by
* platform implementors, to identify implementor-specific patch
* releases. </p>
*
* <p> A version number never has trailing zero elements. If an element
* and all those that follow it logically have the value zero then all of
* them are omitted. </p>
*
* <p> The sequence of numerals in a version number is compared to another
* such sequence in numerical, pointwise fashion; <em>e.g.</em>, {@code
* 10.0.4} is less than {@code 10.1.2}. If one sequence is shorter than
* another then the missing elements of the shorter sequence are considered
* to be less than the corresponding elements of the longer sequence;
* <em>e.g.</em>, {@code 10.0.2} is less than {@code 10.0.2.1}. </p>
*
* <h2><a id="verStr">Version strings</a></h2>
*
* <p> A <em>version string</em>, {@code $VSTR}, is a version number {@code
* $VNUM}, as described above, optionally followed by pre-release and build
* information, in one of the following formats: </p>
*
* <blockquote><pre>
* $VNUM(-$PRE)?\+$BUILD(-$OPT)?
* $VNUM-$PRE(-$OPT)?
* $VNUM(+-$OPT)?
* </pre></blockquote>
*
* <p> where: </p>
*
* <ul>
*
* <li><p> <a id="pre">{@code $PRE}</a>, matching {@code ([a-zA-Z0-9]+)}
* — A pre-release identifier. Typically {@code ea}, for a
* potentially unstable early-access release under active development, or
* {@code internal}, for an internal developer build. </p></li>
*
* <li><p> <a id="build">{@code $BUILD}</a>, matching {@code
* (0|[1-9][0-9]*)} — The build number, incremented for each promoted
* build. {@code $BUILD} is reset to {@code 1} when any portion of {@code
* $VNUM} is incremented. </p></li>
*
* <li><p> <a id="opt">{@code $OPT}</a>, matching {@code ([-a-zA-Z0-9.]+)}
* — Additional build information, if desired. In the case of an