--- old/application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/JVMInformationPage.java 2018-11-05 11:58:11.533882156 -0500 +++ new/application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/pages/JVMInformationPage.java 2018-11-05 11:58:11.462882386 -0500 @@ -165,6 +165,8 @@ infoViewer.addAggregate(JdkAggregators.JVM_VERSION); infoViewer.addAggregate(JdkAggregators.JVM_ARGUMENTS); infoViewer.addAggregate(JdkAggregators.JAVA_ARGUMENTS); + infoViewer.addAggregate(JdkAggregators.JVM_SHUTDOWN_TIME); + infoViewer.addAggregate(JdkAggregators.JVM_SHUTDOWN_REASON); jvmInfSection.setClient(infoViewer.getControl()); Section allFlagsSection = CompositeToolkit.createSection(sash, toolkit, --- old/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/messages/internal/Messages.java 2018-11-05 11:58:11.804881279 -0500 +++ new/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/messages/internal/Messages.java 2018-11-05 11:58:11.735881502 -0500 @@ -199,6 +199,10 @@ public static final String ExceptionRule_RULE_NAME = "ExceptionRule_RULE_NAME"; //$NON-NLS-1$ public static final String ExceptionRule_TEXT_INFO_LONG = "ExceptionRule_TEXT_INFO_LONG"; //$NON-NLS-1$ public static final String ExceptionRule_TEXT_MESSAGE = "ExceptionRule_TEXT_MESSAGE"; //$NON-NLS-1$ + public static final String FatalErrorRule_RULE_NAME = "FatalErrorRule_RULE_NAME"; //$NON-NLS-1$ + public static final String FatalErrorRule_TEXT_OK = "FatalErrorRule_TEXT_OK"; //$NON-NLS-1$ + public static final String FatalErrorRule_TEXT_INFO = "FatalErrorRule_TEXT_INFO"; //$NON-NLS-1$ + public static final String FatalErrorRule_TEXT_WARN = "FatalErrorRule_TEXT_WARN"; //$NON-NLS-1$ public static final String FasttimeRule_TEXT_WARN = "FasttimeRule_TEXT_WARN"; //$NON-NLS-1$ public static final String FasttimeRule_TEXT_WARN_LONG = "FasttimeRule_TEXT_WARN_LONG"; //$NON-NLS-1$ public static final String FewSampledThreadsRule_AGGR_SAMPLES_PER_THREAD = "FewSampledThreadsRule_AGGR_SAMPLES_PER_THREAD"; //$NON-NLS-1$ --- old/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/resources/META-INF/services/org.openjdk.jmc.flightrecorder.rules.IRule 2018-11-05 11:58:12.085880369 -0500 +++ new/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/resources/META-INF/services/org.openjdk.jmc.flightrecorder.rules.IRule 2018-11-05 11:58:12.016880592 -0500 @@ -36,6 +36,7 @@ org.openjdk.jmc.flightrecorder.rules.jdk.cpu.ManyRunningProcessesRule org.openjdk.jmc.flightrecorder.rules.jdk.exceptions.ErrorRule org.openjdk.jmc.flightrecorder.rules.jdk.exceptions.ExceptionRule +org.openjdk.jmc.flightrecorder.rules.jdk.exceptions.FatalErrorRule org.openjdk.jmc.flightrecorder.rules.jdk.general.BufferLostRule org.openjdk.jmc.flightrecorder.rules.jdk.general.ClassLeakingRule org.openjdk.jmc.flightrecorder.rules.jdk.general.ClassLoadingRule --- old/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/resources/org/openjdk/jmc/flightrecorder/rules/jdk/messages/internal/messages.properties 2018-11-05 11:58:12.355879494 -0500 +++ new/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/resources/org/openjdk/jmc/flightrecorder/rules/jdk/messages/internal/messages.properties 2018-11-05 11:58:12.286879718 -0500 @@ -203,6 +203,10 @@ ExceptionRule_TEXT_INFO_LONG=Throwing exceptions is more expensive than normal code execution, which means that they should only be used for exceptional situations. Investigate the thrown exceptions to see if any of them can be avoided with a non-exceptional control flow. # {0} is a time period, {1} is a time stamp, {2} is a number ExceptionRule_TEXT_MESSAGE=The program generated {2} exceptions per second during {0} starting at {1}. +FatalErrorRule_RULE_NAME=Fatal Errors +FatalErrorRule_TEXT_OK=The JVM shut down in a normal way. +FatalErrorRule_TEXT_INFO=The JVM shut down due to there being no remaining non-daemon Java threads. +FatalErrorRule_TEXT_WARN=The JVM shut down due to a fatal error. This indicates that the program terminated in an abnormal way and should be investigated. FasttimeRule_TEXT_WARN=This Flight Recording was made with a JVM with a bug in the Fast Time conversion. FasttimeRule_TEXT_WARN_LONG=The timestamps in this recording are unreliable and may not represent the actual data properly or it may cause problems for JMC. Upgrade to Java 7u60 or later to resolve this issue. FewSampledThreadsRule_AGGR_SAMPLES_PER_THREAD=Samples per thread --- old/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkAggregators.java 2018-11-05 11:58:12.634878591 -0500 +++ new/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkAggregators.java 2018-11-05 11:58:12.564878818 -0500 @@ -118,6 +118,11 @@ public static final IAggregator JVM_VERSION = distinctAsString(VM_INFO, JdkAttributes.JVM_VERSION); public static final IAggregator JAVA_ARGUMENTS = distinctAsString(VM_INFO, JdkAttributes.JAVA_ARGUMENTS); public static final IAggregator JVM_ARGUMENTS = distinctAsString(VM_INFO, JdkAttributes.JVM_ARGUMENTS); + + public static final IAggregator JVM_SHUTDOWN_TIME = min(Messages.getString(Messages.ATTR_SHUTDOWN_TIME), null, + JdkTypeIDs.VM_SHUTDOWN, JfrAttributes.START_TIME); + public static final IAggregator JVM_SHUTDOWN_REASON = distinctAsString(JdkTypeIDs.VM_SHUTDOWN, + JdkAttributes.SHUTDOWN_REASON); // CPU info public static final IAggregator MIN_HW_THREADS = min(HW_THREADS.getName(), null, CPU_INFORMATION, HW_THREADS); --- old/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkAttributes.java 2018-11-05 11:58:12.908877704 -0500 +++ new/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkAttributes.java 2018-11-05 11:58:12.840877924 -0500 @@ -700,6 +700,10 @@ public static final IAttribute DUMP_REASON_RECORDING_ID = attr("recordingId", //$NON-NLS-1$ Messages.getString(Messages.ATTR_DUMP_REASON_RECORDING_ID), Messages.getString(Messages.ATTR_DUMP_REASON_RECORDING_ID_DESC), PLAIN_TEXT); + + public static final IAttribute SHUTDOWN_REASON = attr("reason", // $NON-NLS-1$ + Messages.getString(Messages.ATTR_SHUTDOWN_REASON), + Messages.getString(Messages.ATTR_SHUTDOWN_REASON_DESC), PLAIN_TEXT); public static final IAttribute CLASSLOADER_LOADED_COUNT = attr("loadedClassCount", //$NON-NLS-1$ Messages.getString(Messages.ATTR_CLASSLOADER_LOADED_COUNT), --- old/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkTypeIDs.java 2018-11-05 11:58:13.185876807 -0500 +++ new/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/JdkTypeIDs.java 2018-11-05 11:58:13.116877031 -0500 @@ -144,6 +144,7 @@ public static final String JAVA_THREAD_END = PREFIX + "ThreadEnd"; public static final String VM_OPERATIONS = PREFIX + "ExecuteVMOperation"; + public static final String VM_SHUTDOWN = PREFIX + "Shutdown"; public static final String THREAD_STATISTICS = PREFIX + "JavaThreadStatistics"; public static final String CONTEXT_SWITCH_RATE = PREFIX + "ThreadContextSwitchRate"; --- old/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/messages/internal/Messages.java 2018-11-05 11:58:13.453875939 -0500 +++ new/core/org.openjdk.jmc.flightrecorder/src/main/java/org/openjdk/jmc/flightrecorder/jdk/messages/internal/Messages.java 2018-11-05 11:58:13.379876179 -0500 @@ -443,6 +443,9 @@ public static final String ATTR_YOUNG_COLLECTOR_DESC = "ATTR_YOUNG_COLLECTOR_DESC"; //$NON-NLS-1$ public static final String ATTR_YOUNG_GENERATION_MAX_SIZE = "ATTR_YOUNG_GENERATION_MAX_SIZE"; //$NON-NLS-1$ public static final String ATTR_YOUNG_GENERATION_MIN_SIZE = "ATTR_YOUNG_GENERATION_MIN_SIZE"; //$NON-NLS-1$ + public static final String ATTR_SHUTDOWN_REASON = "ATTR_SHUTDOWN_REASON"; // $NON-NLS-1$ + public static final String ATTR_SHUTDOWN_REASON_DESC = "ATTR_SHUTDOWN_REASON_DESC"; // $NON-NLS-1$ + public static final String ATTR_SHUTDOWN_TIME = "ATTR_SHUTDOWN_TIME"; // $NON-NLS-1$ private Messages() { } --- old/core/org.openjdk.jmc.flightrecorder/src/main/resources/org/openjdk/jmc/flightrecorder/jdk/messages/internal/messages.properties 2018-11-05 11:58:13.731875039 -0500 +++ new/core/org.openjdk.jmc.flightrecorder/src/main/resources/org/openjdk/jmc/flightrecorder/jdk/messages/internal/messages.properties 2018-11-05 11:58:13.660875269 -0500 @@ -320,6 +320,9 @@ ATTR_CLASSLOADER_DATA=Classloader Data Pointer ATTR_PARENT_CLASSLOADER=Parent Class Loader ATTR_CLASSLOADER=Class Loader +ATTR_SHUTDOWN_REASON=Shutdown Reason +ATTR_SHUTDOWN_REASON_DESC=Reason for VM Shutdown +ATTR_SHUTDOWN_TIME=Shutdown Time AGGR_MAX_USED_MEMORY=Maximum used memory --- old/core/tests/org.openjdk.jmc.flightrecorder.rules.jdk.test/src/test/resources/baseline/JfrRuleBaseline.xml 2018-11-05 11:58:14.008874142 -0500 +++ new/core/tests/org.openjdk.jmc.flightrecorder.rules.jdk.test/src/test/resources/baseline/JfrRuleBaseline.xml 2018-11-05 11:58:13.936874375 -0500 @@ -161,6 +161,13 @@ The program generated 0 exceptions per second during 1.017 s starting at 4/26/18 12:10:30 PM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Information 29.510744962334375 @@ -549,6 +556,13 @@ The program generated 0 exceptions per second during 1.210 s starting at 4/26/18 12:12:47 PM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Information 29.510744962334375 @@ -937,6 +951,13 @@ The Thrown Exceptions rule requires events to be available from the following event types: 'Exception Statistics'.<p>They were either disabled during the recording or there might not have happened anything to trigger an event. Event settings like period and threshold may also prevent some events from being emitted. If you are using JMC to create a flight recording, then you can enable and configure event types in the Start Flight Recording wizard. If you are starting the flight recording from the command line, then you can use the settings parameter of <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html">-XX:FlightRecorderOptions</a>. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Not Applicable -1.0 @@ -1325,6 +1346,13 @@ The program generated 0 exceptions per second during 1.000 s starting at 4/25/18 11:38:36 AM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Not Applicable -1.0 @@ -1713,6 +1741,13 @@ The program generated 0 exceptions per second during 999.487 ms starting at 4/4/14 11:17:06 AM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads OK 0.0 @@ -2101,6 +2136,13 @@ The program generated 0 exceptions per second during 1.009 s starting at 4/4/14 8:54:34 AM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads OK 0.0 @@ -2489,6 +2531,13 @@ The program generated 0 exceptions per second during 1.054 s starting at 4/24/18 10:08:53 AM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Information 29.510744962334375 @@ -2877,6 +2926,13 @@ The program generated 515 exceptions per second during 28.060 s starting at 9/24/15 10:08:58 AM. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads OK 0.0 @@ -3267,6 +3323,13 @@ The Thrown Exceptions rule requires events to be available from the following event types: 'Exception Statistics'.<p>They were either disabled during the recording or there might not have happened anything to trigger an event. Event settings like period and threshold may also prevent some events from being emitted. If you are using JMC to create a flight recording, then you can enable and configure event types in the Start Flight Recording wizard. If you are starting the flight recording from the command line, then you can use the settings parameter of <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html">-XX:FlightRecorderOptions</a>. +Fatal Errors +Not Applicable +-1.0 +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'. +The Fatal Errors rule requires the following event types: 'jdk.Shutdown'.<p>They are either not available in this version of Java, or must be enabled in a third-party component. If you are using an older Java version, then you can consider upgrading. + + FewSampledThreads Not Applicable -1.0 --- /dev/null 2018-09-24 09:43:30.878999787 -0400 +++ new/core/org.openjdk.jmc.flightrecorder.rules.jdk/src/main/java/org/openjdk/jmc/flightrecorder/rules/jdk/exceptions/FatalErrorRule.java 2018-11-05 11:58:14.262873320 -0500 @@ -0,0 +1,85 @@ +package org.openjdk.jmc.flightrecorder.rules.jdk.exceptions; + +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; + +import org.openjdk.jmc.common.item.IItemCollection; +import org.openjdk.jmc.common.item.IItemFilter; +import org.openjdk.jmc.common.item.ItemFilters; +import org.openjdk.jmc.common.util.IPreferenceValueProvider; +import org.openjdk.jmc.common.util.TypedPreference; +import org.openjdk.jmc.flightrecorder.jdk.JdkAttributes; +import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs; +import org.openjdk.jmc.flightrecorder.rules.IRule; +import org.openjdk.jmc.flightrecorder.rules.Result; +import org.openjdk.jmc.flightrecorder.rules.jdk.messages.internal.Messages; +import org.openjdk.jmc.flightrecorder.rules.util.JfrRuleTopics; +import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit; +import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit.EventAvailability; + +public class FatalErrorRule implements IRule { + + private static final String RESULT_ID = "Fatal Errors"; //$NON-NLS-1$ + + private static final String ERROR_REASON = "VM Error"; //$NON-NLS-1$ + private static final String INFO_REASON = "No remaining non-daemon Java threads"; //$NON-NLS-1$ + + private FutureTask evaluationTask; + + @Override + public RunnableFuture evaluate(final IItemCollection items, final IPreferenceValueProvider valueProvider) { + evaluationTask = new FutureTask<>(new Callable() { + @Override + public Result call() throws Exception { + return getResult(items, valueProvider); + } + }); + return evaluationTask; + } + + private Result getResult(IItemCollection items, IPreferenceValueProvider valueProvider) { + EventAvailability eventAvailability = RulesToolkit.getEventAvailability(items, JdkTypeIDs.VM_SHUTDOWN); + if (eventAvailability != EventAvailability.AVAILABLE) { + return RulesToolkit.getEventAvailabilityResult(this, items, eventAvailability, JdkTypeIDs.VM_SHUTDOWN); + } + + IItemFilter shutdownFilter = ItemFilters.type(JdkTypeIDs.VM_SHUTDOWN); + IItemCollection shutdownItems = items.apply(shutdownFilter); + + if (shutdownItems.hasItems()) { + // Check the type of VM Shutdown, if it was a VM Error we should report it. + if (shutdownItems.apply(ItemFilters.contains(JdkAttributes.SHUTDOWN_REASON, ERROR_REASON)).hasItems()) { + String message = Messages.getString(Messages.FatalErrorRule_TEXT_WARN); + return new Result(this, 100, message); + } else if (shutdownItems.apply(ItemFilters.contains(JdkAttributes.SHUTDOWN_REASON, INFO_REASON)).hasItems()) { + String message = Messages.getString(Messages.FatalErrorRule_TEXT_INFO); + return new Result(this, 25, message); + } + } + + return new Result(this, 0, Messages.getString(Messages.FatalErrorRule_TEXT_OK)); + } + + @Override + public Collection> getConfigurationAttributes() { + return Collections.emptyList(); + } + + @Override + public String getId() { + return RESULT_ID; + } + + @Override + public String getName() { + return Messages.getString(Messages.FatalErrorRule_RULE_NAME); + } + + @Override + public String getTopic() { + return JfrRuleTopics.JVM_INFORMATION_TOPIC; + } +}