Emergency JFR dump at OOME

Erik Gahlin erik.gahlin at oracle.com
Tue Nov 6 20:29:53 UTC 2018


On 2018-11-06 15:39, Erik Gahlin wrote:
> On 2018-11-01 14:26, Yasumasa Suenaga wrote:
>> Hi Erik,
>>
>> On 2018/11/01 14:13, Erik Gahlin wrote:
>>> Hi Yasumasa,
>>>
>>> Thanks for looking into this, but I don’t think emitting the Old 
>>> Object events is the right thing to do unless we produce a JFR file 
>>> at the same time.
>>>
>>> If anything should be added, it should be when the JVM exits.
>>>
>>>    if (ExitOnOutOfMemoryError) {
>>>        tty->print_cr("Terminating due to java.lang.OutOfMemoryError: 
>>> %s", message);
>>> + perhaps call emergency dump jfr here?
>>>        os::exit(3);
>>>      }
>>>
>>> That said, thinking this over, I’m not even sure this is a good idea.
>>>
>>> I don’t know how the ExitOnOutOfMemoryError flag is used in 
>>> production environments. Do people want a .jfr file at that point? 
>>> For all uses cases? Will it irritate people if they need to clean up 
>>> jfr files? Will it make them turn off Flight Recorder?
>>
>> IMHO ExitOnOutOfMemoryError (and CrashOnOutOfMemoryError) should be 
>> used in production system because any threads might caught OOME which 
>> causes by another thread.
>> For example, when request processor on Tomcat consumes a lot of 
>> memory, Tomcat acceptor thread might caught OOME. If so, Tomcat 
>> cannot process any requests in spite of the process is running.
> Yes, but do you always want a .jfr if this happens?
>
> Let's say you are using the Epsilon GC (which sets 
> ExitOnOutOfMemoryError) and have a script that restarts the JVM when 
> it exits. Then your hard disk may fill up with .jfr files.
>
> One idea would be to only do it for recordings that have specified 
> -XX:StartFlightRecording:dumponexit=true (which is implicitly set by 
> -XX:StartFlightRecording:filename=<filename>) That way, it would be 
> opt in behavior.
>
> This is non-trivial to implement since we can't call Java and allocate 
> objects when we are out of memory. One could perhaps make an up call 
> to Java and there take a previously prepared String representation of 
> the destination path and push that reference back into native, which 
> can then later be inspected.  A filename must also be generated if a 
> user hasn't specified one, which is trickier do to in native. Files in 
> the disk repository should also be removed when the JVM exits.
>
I filed an enhancement request where this could discussed further.
https://bugs.openjdk.java.net/browse/JDK-8213435

Erik

>>
>>
>>> Emergency (native) dumps should probably be reserved for cases when 
>>> the JVM crashes, similar to the hs_err file.
>>
>> I thought JfrEmergencyDump::on_vm_shutdown() should handle all of 
>> OOME, but It seems not to be the case.
>>
>>
>>> I’m reluctant to add a specific flag for the Old Object event for 
>>> the following reasons:
>>>
>>> 1) Very few people would find out about the flag, so it would add 
>>> little value in practise. Focus should be to build a product that 
>>> works well out of the box and not tie the implementation to a flag 
>>> that must be respected for the next decade or so.
>>>
>>> 2) The feature is new and there is not a good tool for visualising 
>>> old object samples. Once it exists, it’e easier to see if emitting 
>>> events and dumping a recording at this stage would help users in 
>>> real world scenarios.
>>>
>>> 3) The way configuration issues have been handled historically is 
>>> using a .jfc file. For instance, one could imagine something like this:
>>>
>>> <event name=“jdk.OldObjectSample”>
>>>   <setting name=“firstOOME”>true</setting>
>>>>>> </event>
>>>
>>> or perhaps a dedicated event, for example 
>>> “jdk.FirstOOMEObjectSample” (if there really is a use case to emit 
>>> events at this particular time that is not covered by the Old Object 
>>> events emitted when the recording ends). There are plans to allow 
>>> events to be configured on command line, so you would not need to 
>>> create a new jfc file to make a slight change. That feature would 
>>> then automatically provide command line capabilities for the Old 
>>> Object event in the scenario you describe.
>>>
>>> To me it seems best to wait with the enhancement for now.
>>
>> I agree with you "jdk.FirstOOMEObjectSample" should be added as event 
>> setting.
>> I don't care it can set whether *.jfc and commandline option.
>>
>> Anyway, I think it is very useful if we can get old object 
>> information in flight record when OOME occurs.
>> Of course we can get heap dump with HeapDumpOnOutOfMemoryError, but 
>> it is not contain time-series data like a flight record.
>>
>>
>> I hope this proposal is accepted JFR team.
>>
>>
>> Thanks,
>>
>> Yasumasa
>>
>>
>>> Thanks
>>> Erik
>>>
>>>
>>>> On 1 Nov 2018, at 04:15, Yasumasa Suenaga <yasuenag at gmail.com> wrote:
>>>>
>>>> Hi Erik,
>>>>
>>>>> If a user on the other hand has specified a flag that the JVM 
>>>>> should exit on OOME, then it makes sense to dump a recording with 
>>>>> the old object events and shortest path-to-gc-root.
>>>>> That part seems to be missing.
>>>>
>>>> I tried to add a flag `EmitLeakProfilerEventsOnOOME` to control it 
>>>> as below.
>>>> It works fine on my environment.
>>>>
>>>> ```
>>>> diff -r 3a8208766f7b src/hotspot/share/jfr/jfr.cpp
>>>> --- a/src/hotspot/share/jfr/jfr.cpp     Thu Nov 01 02:12:13 2018 +0100
>>>> +++ b/src/hotspot/share/jfr/jfr.cpp     Thu Nov 01 12:13:17 2018 +0900
>>>> @@ -91,6 +91,10 @@
>>>>    return JfrOptionSet::parse_start_flight_recording_option(option, 
>>>> delimiter);
>>>> }
>>>>
>>>> +void Jfr::emit_leak_profiler_events(jlong cutoff_ticks, bool 
>>>> emit_all) {
>>>> +  LeakProfiler::emit_events(cutoff_ticks, emit_all);
>>>> +}
>>>> +
>>>> Thread* Jfr::sampler_thread() {
>>>>    return JfrThreadSampling::sampler_thread();
>>>> }
>>>> diff -r 3a8208766f7b src/hotspot/share/jfr/jfr.hpp
>>>> --- a/src/hotspot/share/jfr/jfr.hpp     Thu Nov 01 02:12:13 2018 +0100
>>>> +++ b/src/hotspot/share/jfr/jfr.hpp     Thu Nov 01 12:13:17 2018 +0900
>>>> @@ -52,6 +52,7 @@
>>>>    static bool on_flight_recorder_option(const JavaVMOption** 
>>>> option, char* delimiter);
>>>>    static bool on_start_flight_recording_option(const 
>>>> JavaVMOption** option, char* delimiter);
>>>>    static void weak_oops_do(BoolObjectClosure* is_alive, 
>>>> OopClosure* f);
>>>> +  static void emit_leak_profiler_events(jlong cutoff_ticks, bool 
>>>> emit_all);
>>>>    static Thread* sampler_thread();
>>>> };
>>>>
>>>> diff -r 3a8208766f7b src/hotspot/share/runtime/globals.hpp
>>>> --- a/src/hotspot/share/runtime/globals.hpp     Thu Nov 01 02:12:13 
>>>> 2018 +0100
>>>> +++ b/src/hotspot/share/runtime/globals.hpp     Thu Nov 01 12:13:17 
>>>> 2018 +0900
>>>> @@ -2596,6 +2596,9 @@
>>>>    JFR_ONLY(product(ccstr, StartFlightRecording, 
>>>> NULL,                       \
>>>>            "Start flight recording with 
>>>> options"))                           \
>>>> \
>>>> +  JFR_ONLY(product(bool, EmitLeakProfilerEventsOnOOME, 
>>>> false,               \
>>>> +          "Emit LeakProfiler events when OutOfMemoryError 
>>>> occurs"))         \
>>>> + \
>>>>    experimental(bool, UseFastUnorderedTimeStamps, 
>>>> false,                     \
>>>>            "Use platform unstable time where supported for 
>>>> timestamps only")
>>>>
>>>> diff -r 3a8208766f7b src/hotspot/share/utilities/debug.cpp
>>>> --- a/src/hotspot/share/utilities/debug.cpp     Thu Nov 01 02:12:13 
>>>> 2018 +0100
>>>> +++ b/src/hotspot/share/utilities/debug.cpp     Thu Nov 01 12:13:17 
>>>> 2018 +0900
>>>> @@ -58,6 +58,9 @@
>>>> #include "utilities/globalDefinitions.hpp"
>>>> #include "utilities/macros.hpp"
>>>> #include "utilities/vmError.hpp"
>>>> +#if INCLUDE_JFR
>>>> +#include "jfr/jfr.hpp"
>>>> +#endif
>>>>
>>>> #include <stdio.h>
>>>>
>>>> @@ -306,6 +309,13 @@
>>>>    // commands multiple times we just do it once when the first 
>>>> threads reports
>>>>    // the error.
>>>>    if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
>>>> +
>>>> +#if INCLUDE_JFR
>>>> +      if (EmitLeakProfilerEventsOnOOME) {
>>>> +        Jfr::emit_leak_profiler_events(max_jlong, false);
>>>> +      }
>>>> +#endif
>>>> +
>>>>      // create heap dump before OnOutOfMemoryError commands are 
>>>> executed
>>>>      if (HeapDumpOnOutOfMemoryError) {
>>>>        tty->print_cr("java.lang.OutOfMemoryError: %s", message);
>>>> ```
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> Yasumasa
>>>>
>>>>
>>>> On 2018/11/01 8:47, Erik Gahlin wrote:
>>>>>> On 31 Oct 2018, at 03:58, Yasumasa Suenaga <yasuenag at gmail.com> 
>>>>>> wrote:
>>>>>>
>>>>>> 2018年10月31日(水) 0:35 Markus Gronlund 
>>>>>> <markus.gronlund at oracle.com>:
>>>>>>>
>>>>>>> I think I provided you with the wrong settings.
>>>>>>>
>>>>>>> Please change:
>>>>>>>
>>>>>>> JFR_ONLY(Jfr::emit_leak_profiler_events(0, true);)
>>>>>>>
>>>>>>> To
>>>>>>>
>>>>>>> JFR_ONLY(Jfr::emit_leak_profiler_events(max_jlong, false);)
>>>>>>>
>>>>>>> I think this will get you the GC roots as well.
>>>>>>
>>>>>> Thanks! It works fine.
>>>>>>
>>>>>>
>>>>>>> We need to think about if / how this should be integrated. If 
>>>>>>> so, it might be that it needs to be guarded behind some flag to 
>>>>>>> not always issue a full safepoint, root scanning and edge 
>>>>>>> traversals on every OOME.
>>>>>>
>>>>>> Do you mean VM operation should be added for 
>>>>>> Jfr::emit_leak_profiler_events()?
>>>>>> I think it can do so because HeapDumper is called from this 
>>>>>> function.
>>>>> When a recording ends, old object samples are written. They have 
>>>>> the most up to date information about what is leaking. I don’t 
>>>>> think we should emit old object events before that happens. It 
>>>>> will make recordings harder to analyze and introduce an intrusive 
>>>>> safepoint.
>>>>> If a user on the other hand has specified a flag that the JVM 
>>>>> should exit on OOME, then it makes sense to dump a recording with 
>>>>> the old object events and shortest path-to-gc-root.
>>>>> That part seems to be missing.
>>>>> Erik
>>>>>>
>>>>>> Anyway, I want you to merge this change to JFR. :-)
>>>>>>
>>>>>>
>>>>>> Yasumasa
>>>>>>
>>>>>>
>>>>>>> Markus
>>>>>>>
>>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Yasumasa Suenaga <yasuenag at gmail.com>
>>>>>>> Sent: den 30 oktober 2018 14:54
>>>>>>> To: Markus Gronlund <markus.gronlund at oracle.com>
>>>>>>> Cc: hotspot-jfr-dev at openjdk.java.net
>>>>>>> Subject: Re: Emergency JFR dump at OOME
>>>>>>>
>>>>>>> Thanks Markus!
>>>>>>> It works fine on my environment.
>>>>>>>
>>>>>>> Could you apply this change to JFR?
>>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>>
>>>>>>> Yasumasa
>>>>>>>
>>>>>>>
>>>>>>> P.S.
>>>>>>>    I got flight record with path-to-gc-roots=true, however "GC 
>>>>>>> Root" in JMC
>>>>>>>    is null. Is it correct?
>>>>>>>    (Application is OOME.java which I shared before)
>>>>>>>
>>>>>>>
>>>>>>> On 2018/10/30 21:01, Markus Gronlund wrote:
>>>>>>>> Hi again,
>>>>>>>>
>>>>>>>> Maybe you can try something like this:
>>>>>>>>
>>>>>>>> # HG changeset patch
>>>>>>>> # User mgronlun
>>>>>>>> # Date 1540900357 -3600
>>>>>>>> #      Tue Oct 30 12:52:37 2018 +0100
>>>>>>>> # Node ID 32a48c323970c5fc4d0d1ffff5860a3c55c4a4dc
>>>>>>>> # Parent  80d104390dd2821fd95d56981bf9d37f1cc2e363
>>>>>>>> [mq]: yasumasa
>>>>>>>>
>>>>>>>> diff --git a/src/hotspot/share/jfr/jfr.cpp
>>>>>>>> b/src/hotspot/share/jfr/jfr.cpp
>>>>>>>> --- a/src/hotspot/share/jfr/jfr.cpp
>>>>>>>> +++ b/src/hotspot/share/jfr/jfr.cpp
>>>>>>>> @@ -91,6 +91,10 @@
>>>>>>>>     return 
>>>>>>>> JfrOptionSet::parse_start_flight_recording_option(option, 
>>>>>>>> delimiter);
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +void Jfr::emit_leak_profiler_events(jlong cutoff_ticks, bool
>>>>>>>> +emit_all) {
>>>>>>>> +  LeakProfiler::emit_events(cutoff_ticks, emit_all); }
>>>>>>>> +
>>>>>>>>   Thread* Jfr::sampler_thread() {
>>>>>>>>     return JfrThreadSampling::sampler_thread();
>>>>>>>>   }
>>>>>>>> diff --git a/src/hotspot/share/jfr/jfr.hpp
>>>>>>>> b/src/hotspot/share/jfr/jfr.hpp
>>>>>>>> --- a/src/hotspot/share/jfr/jfr.hpp
>>>>>>>> +++ b/src/hotspot/share/jfr/jfr.hpp
>>>>>>>> @@ -52,6 +52,7 @@
>>>>>>>>     static bool on_flight_recorder_option(const JavaVMOption** 
>>>>>>>> option, char* delimiter);
>>>>>>>>     static bool on_start_flight_recording_option(const 
>>>>>>>> JavaVMOption** option, char* delimiter);
>>>>>>>>     static void weak_oops_do(BoolObjectClosure* is_alive, 
>>>>>>>> OopClosure*
>>>>>>>> f);
>>>>>>>> +  static void emit_leak_profiler_events(jlong cutoff_ticks, bool
>>>>>>>> + emit_all);
>>>>>>>>     static Thread* sampler_thread();
>>>>>>>>   };
>>>>>>>>
>>>>>>>> diff --git a/src/hotspot/share/utilities/debug.cpp
>>>>>>>> b/src/hotspot/share/utilities/debug.cpp
>>>>>>>> --- a/src/hotspot/share/utilities/debug.cpp
>>>>>>>> +++ b/src/hotspot/share/utilities/debug.cpp
>>>>>>>> @@ -58,6 +58,9 @@
>>>>>>>>   #include "utilities/globalDefinitions.hpp"
>>>>>>>>   #include "utilities/macros.hpp"
>>>>>>>>   #include "utilities/vmError.hpp"
>>>>>>>> +#if INCLUDE_JFR
>>>>>>>> +#include "jfr/jfr.hpp"
>>>>>>>> +#endif
>>>>>>>>
>>>>>>>>   #include <stdio.h>
>>>>>>>>
>>>>>>>> @@ -306,6 +309,8 @@
>>>>>>>>     // commands multiple times we just do it once when the 
>>>>>>>> first threads reports
>>>>>>>>     // the error.
>>>>>>>>     if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
>>>>>>>> +    JFR_ONLY(Jfr::emit_leak_profiler_events(0, true);)
>>>>>>>> +
>>>>>>>>       // create heap dump before OnOutOfMemoryError commands 
>>>>>>>> are executed
>>>>>>>>       if (HeapDumpOnOutOfMemoryError) {
>>>>>>>> tty->print_cr("java.lang.OutOfMemoryError: %s", message);
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> This should write the contents of the leak profiler at the 
>>>>>>>> first reported OOME; it will go through the regular chunk 
>>>>>>>> writing mechanism in order that it do not destroy existing dump 
>>>>>>>> logic.
>>>>>>>>
>>>>>>>> Let me know if it works for you.
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>> Markus
>>>>>>>>
>>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: Yasumasa Suenaga <yasuenag at gmail.com>
>>>>>>>> Sent: den 30 oktober 2018 02:35
>>>>>>>> To: Markus Gronlund <markus.gronlund at oracle.com>
>>>>>>>> Cc: hotspot-jfr-dev at openjdk.java.net
>>>>>>>> Subject: Re: Emergency JFR dump at OOME
>>>>>>>>
>>>>>>>> Hi Markus,
>>>>>>>>
>>>>>>>> I confirmed with GDB that Leak Profiler is called by shutdown 
>>>>>>>> hook.
>>>>>>>> I think it is very useful to obtain information when OOME 
>>>>>>>> occurs because the user might not get heap dump.
>>>>>>>>
>>>>>>>> So I want JFR to call Leak Profiler when OOME occurs before 
>>>>>>>> being destroyed problematic thread.
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>>
>>>>>>>> Yasumasa
>>>>>>>>
>>>>>>>> 2018年10月29日(月) 23:41 Markus Gronlund 
>>>>>>>> <markus.gronlund at oracle.com>:
>>>>>>>>>
>>>>>>>>> I think it is called.
>>>>>>>>>
>>>>>>>>> Remember that main thread has already exited when the shutdown 
>>>>>>>>> logic is called, the allocations in your test can already have 
>>>>>>>>> been removed by the GC at this point (marked as dead in the 
>>>>>>>>> Leak Profiler).
>>>>>>>>>
>>>>>>>>> In general, small tests like these are not representative for 
>>>>>>>>> the Leak Profiler, because it works by acquiring samples over 
>>>>>>>>> longer periods of time, and then there is the problem of the 
>>>>>>>>> main thread could already have exited at the point of dump.
>>>>>>>>>
>>>>>>>>> Please take a look at the tests located in 
>>>>>>>>> test/jdk/jdk/jfr/event/oldobject for some reference on how you 
>>>>>>>>> can take more control to increase the chances of getting samples.
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>> Markus
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> -----Original Message-----
>>>>>>>>> From: Yasumasa Suenaga <yasuenag at gmail.com>
>>>>>>>>> Sent: den 29 oktober 2018 15:13
>>>>>>>>> To: Markus Gronlund <markus.gronlund at oracle.com>
>>>>>>>>> Cc: hotspot-jfr-dev at openjdk.java.net
>>>>>>>>> Subject: Re: Emergency JFR dump at OOME
>>>>>>>>>
>>>>>>>>> Hi Markus,
>>>>>>>>>
>>>>>>>>> I tried to get flight record of OOME sample application as below:
>>>>>>>>> ---------------
>>>>>>>>> import java.util.*;
>>>>>>>>>
>>>>>>>>> public class OOME{
>>>>>>>>>     public static void main(String[] args){
>>>>>>>>>       var list = new ArrayList<byte[]>();
>>>>>>>>>       while(true){
>>>>>>>>>         list.add(new byte[1024]);
>>>>>>>>>       }
>>>>>>>>>     }
>>>>>>>>> }
>>>>>>>>> ---------------
>>>>>>>>>
>>>>>>>>> Command:
>>>>>>>>>     $ /usr/local/jdk-11.0.1/bin/java
>>>>>>>>> -XX:StartFlightRecording=filename=oome.jfr,settings=profile 
>>>>>>>>> -Xmx256m
>>>>>>>>> OOME
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I could get flight record into oome.jfr, but JMC did not show 
>>>>>>>>> any objects on "Live Objects" window.
>>>>>>>>> OOME.java will finish immidiatery. It will not invoke any 
>>>>>>>>> periodic tasks.
>>>>>>>>> So I guess LeakProfiler::emit_events() will not be called.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>>
>>>>>>>>> Yasumasa
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 2018/10/29 22:47, Markus Gronlund wrote:
>>>>>>>>>> Rotate() and / or stop() is always called as part of 
>>>>>>>>>> shutdown, indirectly by the shutdown thread asking the 
>>>>>>>>>> recorder thread in the VM.
>>>>>>>>>>
>>>>>>>>>> LeakProfiler::emit_events() will be called on shutdown if the 
>>>>>>>>>> jdk.OldObjectSample event is enabled.
>>>>>>>>>>
>>>>>>>>>> Absence of EventDumpReason implies a normal shutdown.
>>>>>>>>>>
>>>>>>>>>> Markus
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> -----Original Message-----
>>>>>>>>>> From: Yasumasa Suenaga <yasuenag at gmail.com>
>>>>>>>>>> Sent: den 29 oktober 2018 11:58
>>>>>>>>>> To: Markus Gronlund <markus.gronlund at oracle.com>
>>>>>>>>>> Cc: hotspot-jfr-dev at openjdk.java.net
>>>>>>>>>> Subject: Re: Emergency JFR dump at OOME
>>>>>>>>>>
>>>>>>>>>> Hi Markus,
>>>>>>>>>>
>>>>>>>>>>> This would screw up the logic for the registered Shutdown 
>>>>>>>>>>> hook that will run if the VM is also shutting down (which is 
>>>>>>>>>>> not implied).
>>>>>>>>>>
>>>>>>>>>> Does it mean JfrRecorderService::rotate() will be called at 
>>>>>>>>>> JfrEmergencyDump::on_vm_shutdown() ?
>>>>>>>>>> I think EventDumpReason::commit() and 
>>>>>>>>>> LeakProfiler::emit_events() should be called when OOME occurs 
>>>>>>>>>> even if it would not be treated as emergency dump. So we 
>>>>>>>>>> should add them to Universe::gen_out_of_memory_error().
>>>>>>>>>>
>>>>>>>>>> What do you think?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>>
>>>>>>>>>> Yasumasa
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 2018/10/29 17:28, Markus Gronlund wrote:
>>>>>>>>>>> Hi Yasumasa,
>>>>>>>>>>>
>>>>>>>>>>> I don't think so.
>>>>>>>>>>>
>>>>>>>>>>> Handling OOMEs is very intricate, OOMEs are thread local and 
>>>>>>>>>>> it is difficult to get it right.
>>>>>>>>>>>
>>>>>>>>>>> The suggested patch would do an emergency dump 
>>>>>>>>>>> unconditionally on the first reported OOME. This would screw 
>>>>>>>>>>> up the logic for the registered Shutdown hook that will run 
>>>>>>>>>>> if the VM is also shutting down (which is not implied).
>>>>>>>>>>> But, it is only the first invocation of 
>>>>>>>>>>> report_java_out_of_memory() that is happening here and user 
>>>>>>>>>>> code can catch OOME's. Other threads might run fine for 
>>>>>>>>>>> quite some time and might not even run into OOME's.
>>>>>>>>>>> The shutdown hook registered for dumping JFR recordings on 
>>>>>>>>>>> VM Exit is set up to attempt to handle graceful shutdown if 
>>>>>>>>>>> possible (no OOME), but if it gets an OOME, it will trigger 
>>>>>>>>>>> the OOME emergency dump logic.
>>>>>>>>>>>
>>>>>>>>>>> Remember that you will need to state you would like a 
>>>>>>>>>>> recording dumped out to disk on VM exit for the shutdown 
>>>>>>>>>>> hook logic to complete.
>>>>>>>>>>>
>>>>>>>>>>> This you can do by:
>>>>>>>>>>>
>>>>>>>>>>> -XX:StartFlightRecording:dumponexit=true
>>>>>>>>>>>
>>>>>>>>>>> Or by:
>>>>>>>>>>>
>>>>>>>>>>> -XX:StartFlightRecording:filename=myrec.jfr
>>>>>>>>>>>
>>>>>>>>>>> If the Shutdown hook gets an OOME during the exit logic, it 
>>>>>>>>>>> will take the emergency path to create a file called 
>>>>>>>>>>> hs_oom_<pid>.jfr.
>>>>>>>>>>>
>>>>>>>>>>> There is a current known issue with the fact that OOME's are 
>>>>>>>>>>> pre-allocated so they don't turn up in the recordings as 
>>>>>>>>>>> Errors (because they are pre-allocated before JFR starts). 
>>>>>>>>>>> We might want to add something to 
>>>>>>>>>>> Universe::gen_out_of_memory_error() to report this in some way.
>>>>>>>>>>>
>>>>>>>>>>> Thanks
>>>>>>>>>>> Markus
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> -----Original Message-----
>>>>>>>>>>> From: Yasumasa Suenaga <yasuenag at gmail.com>
>>>>>>>>>>> Sent: den 25 oktober 2018 12:58
>>>>>>>>>>> To: hotspot-jfr-dev at openjdk.java.net
>>>>>>>>>>> Subject: Emergency JFR dump at OOME
>>>>>>>>>>>
>>>>>>>>>>> Hi all,
>>>>>>>>>>>
>>>>>>>>>>> According to [1], I guess JFR dumps flight record to file.
>>>>>>>>>>> But current JFR don't do so.
>>>>>>>>>>>
>>>>>>>>>>> Should we fix it as below?
>>>>>>>>>>> --------------------
>>>>>>>>>>> diff -r 003c062e16ea src/hotspot/share/utilities/debug.cpp
>>>>>>>>>>> --- a/src/hotspot/share/utilities/debug.cpp Wed Oct 24 
>>>>>>>>>>> 21:17:30 2018 -0700
>>>>>>>>>>> +++ b/src/hotspot/share/utilities/debug.cpp Thu Oct 25 
>>>>>>>>>>> 19:56:54 2018 +0900
>>>>>>>>>>> @@ -58,6 +58,9 @@
>>>>>>>>>>>      #include "utilities/globalDefinitions.hpp"
>>>>>>>>>>>      #include "utilities/macros.hpp"
>>>>>>>>>>>      #include "utilities/vmError.hpp"
>>>>>>>>>>> +#if INCLUDE_JFR
>>>>>>>>>>> +#include "jfr/jfr.hpp"
>>>>>>>>>>> +#endif
>>>>>>>>>>>
>>>>>>>>>>>      #include <stdio.h>
>>>>>>>>>>>
>>>>>>>>>>> @@ -321,6 +324,8 @@
>>>>>>>>>>>            fatal("OutOfMemory encountered: %s", message);
>>>>>>>>>>>          }
>>>>>>>>>>>
>>>>>>>>>>> +    JFR_ONLY(Jfr::on_vm_shutdown(false);)
>>>>>>>>>>> +
>>>>>>>>>>>          if (ExitOnOutOfMemoryError) {
>>>>>>>>>>>            tty->print_cr("Terminating due to 
>>>>>>>>>>> java.lang.OutOfMemoryError: %s", message);
>>>>>>>>>>>            os::exit(3);
>>>>>>>>>>> --------------------
>>>>>>>>>>>
>>>>>>>>>>> I will file it to JBS and will send review request if it is 
>>>>>>>>>>> verified.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>>
>>>>>>>>>>> Yasumasa
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> [1]
>>>>>>>>>>> https://hg.openjdk.java.net/jdk/jdk/file/003c062e16ea/src/hotspot/s 
>>>>>>>>>>>
>>>>>>>>>>> hare/jfr/recorder/repository/jfrEmergencyDump.cpp#l159
>>>>>>>>>>>
>>>
>



More information about the hotspot-jfr-dev mailing list