17
17
package org .springframework .boot ;
18
18
19
19
import java .lang .StackWalker .StackFrame ;
20
+ import java .lang .management .ManagementFactory ;
20
21
import java .time .Duration ;
21
22
import java .util .ArrayList ;
22
23
import java .util .Arrays ;
35
36
36
37
import org .apache .commons .logging .Log ;
37
38
import org .apache .commons .logging .LogFactory ;
39
+ import org .crac .management .CRaCMXBean ;
38
40
39
41
import org .springframework .aot .AotDetector ;
40
42
import org .springframework .beans .BeansException ;
@@ -301,10 +303,10 @@ private Optional<Class<?>> findMainClass(Stream<StackFrame> stack) {
301
303
* @return a running {@link ApplicationContext}
302
304
*/
303
305
public ConfigurableApplicationContext run (String ... args ) {
306
+ Startup startup = Startup .create ();
304
307
if (this .registerShutdownHook ) {
305
308
SpringApplication .shutdownHook .enableShutdowHookAddition ();
306
309
}
307
- long startTime = System .nanoTime ();
308
310
DefaultBootstrapContext bootstrapContext = createBootstrapContext ();
309
311
ConfigurableApplicationContext context = null ;
310
312
configureHeadlessProperty ();
@@ -319,11 +321,11 @@ public ConfigurableApplicationContext run(String... args) {
319
321
prepareContext (bootstrapContext , context , environment , listeners , applicationArguments , printedBanner );
320
322
refreshContext (context );
321
323
afterRefresh (context , applicationArguments );
322
- Duration timeTakenToStartup = Duration . ofNanos ( System . nanoTime () - startTime );
324
+ startup . started ( );
323
325
if (this .logStartupInfo ) {
324
- new StartupInfoLogger (this .mainApplicationClass ).logStarted (getApplicationLog (), timeTakenToStartup );
326
+ new StartupInfoLogger (this .mainApplicationClass ).logStarted (getApplicationLog (), startup );
325
327
}
326
- listeners .started (context , timeTakenToStartup );
328
+ listeners .started (context , startup . timeTakenToStarted () );
327
329
callRunners (context , applicationArguments );
328
330
}
329
331
catch (Throwable ex ) {
@@ -335,8 +337,7 @@ public ConfigurableApplicationContext run(String... args) {
335
337
}
336
338
try {
337
339
if (context .isRunning ()) {
338
- Duration timeTakenToReady = Duration .ofNanos (System .nanoTime () - startTime );
339
- listeners .ready (context , timeTakenToReady );
340
+ listeners .ready (context , startup .ready ());
340
341
}
341
342
}
342
343
catch (Throwable ex ) {
@@ -1657,4 +1658,97 @@ public void run() {
1657
1658
1658
1659
}
1659
1660
1661
+ abstract static class Startup {
1662
+
1663
+ private Duration timeTakenToStarted ;
1664
+
1665
+ abstract long startTime ();
1666
+
1667
+ abstract Long processUptime ();
1668
+
1669
+ abstract String action ();
1670
+
1671
+ final Duration started () {
1672
+ long now = System .currentTimeMillis ();
1673
+ this .timeTakenToStarted = Duration .ofMillis (now - startTime ());
1674
+ return this .timeTakenToStarted ;
1675
+ }
1676
+
1677
+ private Duration ready () {
1678
+ long now = System .currentTimeMillis ();
1679
+ return Duration .ofMillis (now - startTime ());
1680
+ }
1681
+
1682
+ Duration timeTakenToStarted () {
1683
+ return this .timeTakenToStarted ;
1684
+ }
1685
+
1686
+ static Startup create () {
1687
+ if (ClassUtils .isPresent ("jdk.crac.management.CRaCMXBean" , Startup .class .getClassLoader ())) {
1688
+ return new CracStartup ();
1689
+ }
1690
+ return new StandardStartup ();
1691
+ }
1692
+
1693
+ }
1694
+
1695
+ private static class CracStartup extends Startup {
1696
+
1697
+ private final StandardStartup fallback = new StandardStartup ();
1698
+
1699
+ @ Override
1700
+ Long processUptime () {
1701
+ long uptime = CRaCMXBean .getCRaCMXBean ().getUptimeSinceRestore ();
1702
+ return (uptime >= 0 ) ? uptime : this .fallback .processUptime ();
1703
+ }
1704
+
1705
+ @ Override
1706
+ String action () {
1707
+ if (restoreTime () >= 0 ) {
1708
+ return "Restored" ;
1709
+ }
1710
+ return this .fallback .action ();
1711
+ }
1712
+
1713
+ private long restoreTime () {
1714
+ return CRaCMXBean .getCRaCMXBean ().getRestoreTime ();
1715
+ }
1716
+
1717
+ @ Override
1718
+ long startTime () {
1719
+ long restoreTime = restoreTime ();
1720
+ if (restoreTime >= 0 ) {
1721
+ return restoreTime ;
1722
+ }
1723
+ return this .fallback .startTime ();
1724
+ }
1725
+
1726
+ }
1727
+
1728
+ private static class StandardStartup extends Startup {
1729
+
1730
+ private final Long startTime = System .currentTimeMillis ();
1731
+
1732
+ @ Override
1733
+ long startTime () {
1734
+ return this .startTime ;
1735
+ }
1736
+
1737
+ @ Override
1738
+ Long processUptime () {
1739
+ try {
1740
+ return ManagementFactory .getRuntimeMXBean ().getUptime ();
1741
+ }
1742
+ catch (Throwable ex ) {
1743
+ return null ;
1744
+ }
1745
+ }
1746
+
1747
+ @ Override
1748
+ String action () {
1749
+ return "Started" ;
1750
+ }
1751
+
1752
+ }
1753
+
1660
1754
}
0 commit comments