sssssssssss37

  static const char klass[] = "jdk/jfr/internal/dcmd/DCmdCheck";
  static const char method[] = "execute";
  static const char signature[] = "(Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";
  JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
  execute_args.set_receiver(h_dcmd_instance);
  execute_args.push_jobject(name);
  execute_args.push_jobject(verbose);
  JfrJavaSupport::call_virtual(&execute_args, THREAD);
  handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrStartFlightRecordingDCmd::JfrStartFlightRecordingDCmd(outputStream* output,
                                                         bool heap) : DCmdWithParser(output, heap),
  _name("name", "Name that can be used to identify recording, e.g. \\\"My Recording\\\"", "STRING", false, NULL),
  _settings("settings", "Settings file(s), e.g. profile or default. See JRE_HOME/lib/jfr", "STRING SET", false),
  _delay("delay", "Delay recording start with (s)econds, (m)inutes), (h)ours), or (d)ays, e.g. 5h.", "NANOTIME", false, "0"),
  _duration("duration", "Duration of recording in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 300s.", "NANOTIME", false, "0"),
  _filename("filename", "Resulting recording filename, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false),
  _disk("disk", "Recording should be persisted to disk", "BOOLEAN", false),
  _maxage("maxage", "Maximum time to keep recorded data (on disk) in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit", "NANOTIME", false, "0"),
  _maxsize("maxsize", "Maximum amount of bytes to keep (on disk) in (k)B, (M)B or (G)B, e.g. 500M, or 0 for no limit", "MEMORY SIZE", false, "0"),
  _dump_on_exit("dumponexit", "Dump running recording when JVM shuts down", "BOOLEAN", false),
  _path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") {
  _dcmdparser.add_dcmd_option(&_name);
  _dcmdparser.add_dcmd_option(&_settings);
  _dcmdparser.add_dcmd_option(&_delay);
  _dcmdparser.add_dcmd_option(&_duration);
  _dcmdparser.add_dcmd_option(&_disk);
  _dcmdparser.add_dcmd_option(&_filename);
  _dcmdparser.add_dcmd_option(&_maxage);
  _dcmdparser.add_dcmd_option(&_maxsize);
  _dcmdparser.add_dcmd_option(&_dump_on_exit);
  _dcmdparser.add_dcmd_option(&_path_to_gc_roots);
};
int JfrStartFlightRecordingDCmd::num_arguments() {
  ResourceMark rm;
  JfrStartFlightRecordingDCmd* dcmd = new JfrStartFlightRecordingDCmd(NULL, false);
  if (dcmd != NULL) {
    DCmdMark mark(dcmd);
    return dcmd->_dcmdparser.num_arguments();
  }
  return 0;
}
void JfrStartFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  if (invalid_state(output(), THREAD)) {
    return;
  }
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JNIHandleBlockManager jni_handle_management(THREAD);
  JavaValue result(T_OBJECT);
  JfrJavaArguments constructor_args(&result);
  constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStart", THREAD);
  const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
  Handle h_dcmd_instance(THREAD, dcmd);
  assert(h_dcmd_instance.not_null(), "invariant");
  jstring name = NULL;
  if (_name.is_set() && _name.value() != NULL) {
    name = JfrJavaSupport::new_string(_name.value(), CHECK);
  }
  jstring filename = NULL;
  if (_filename.is_set() && _filename.value() != NULL) {
    filename = JfrJavaSupport::new_string(_filename.value(), CHECK);
  }
  jobject maxage = NULL;
  if (_maxage.is_set()) {
    maxage = JfrJavaSupport::new_java_lang_Long(_maxage.value()._nanotime, CHECK);
  }
  jobject maxsize = NULL;
  if (_maxsize.is_set()) {
    maxsize = JfrJavaSupport::new_java_lang_Long(_maxsize.value()._size, CHECK);
  }
  jobject duration = NULL;
  if (_duration.is_set()) {
    duration = JfrJavaSupport::new_java_lang_Long(_duration.value()._nanotime, CHECK);
  }
  jobject delay = NULL;
  if (_delay.is_set()) {
    delay = JfrJavaSupport::new_java_lang_Long(_delay.value()._nanotime, CHECK);
  }
  jobject disk = NULL;
  if (_disk.is_set()) {
    disk = JfrJavaSupport::new_java_lang_Boolean(_disk.value(), CHECK);
  }
  jobject dump_on_exit = NULL;
  if (_dump_on_exit.is_set()) {
    dump_on_exit = JfrJavaSupport::new_java_lang_Boolean(_dump_on_exit.value(), CHECK);
  }
  jobject path_to_gc_roots = NULL;
  if (_path_to_gc_roots.is_set()) {
    path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK);
  }
  jobjectArray settings = NULL;
  if (_settings.is_set()) {
    int length = _settings.value()->array()->length();
    if (length == 1) {
      const char* c_str = _settings.value()->array()->at(0);
      if (strcmp(c_str, "none") == 0) {
        length = 0;
      }
    }
    settings = JfrJavaSupport::new_string_array(length, CHECK);
    assert(settings != NULL, "invariant");
    for (int i = 0; i < length; ++i) {
      jobject element = JfrJavaSupport::new_string(_settings.value()->array()->at(i), CHECK);
      assert(element != NULL, "invariant");
      JfrJavaSupport::set_array_element(settings, element, i, CHECK);
    }
  } else {
    settings = JfrJavaSupport::new_string_array(1, CHECK);
    assert(settings != NULL, "invariant");
    jobject element = JfrJavaSupport::new_string("default", CHECK);
    assert(element != NULL, "invariant");
    JfrJavaSupport::set_array_element(settings, element, 0, CHECK);
  }
  static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStart";
  static const char method[] = "execute";
  static const char signature[] = "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/Long;"
    "Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/String;"
    "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/lang/String;";
  JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
  execute_args.set_receiver(h_dcmd_instance);
  execute_args.push_jobject(name);
  execute_args.push_jobject(settings);
  execute_args.push_jobject(delay);
  execute_args.push_jobject(duration);
  execute_args.push_jobject(disk);
  execute_args.push_jobject(filename);
  execute_args.push_jobject(maxage);
  execute_args.push_jobject(maxsize);
  execute_args.push_jobject(dump_on_exit);
  execute_args.push_jobject(path_to_gc_roots);
  JfrJavaSupport::call_virtual(&execute_args, THREAD);
  handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrStopFlightRecordingDCmd::JfrStopFlightRecordingDCmd(outputStream* output,
                                                       bool heap) : DCmdWithParser(output, heap),
  _name("name", "Recording text,.e.g \\\"My Recording\\\"", "STRING", true, NULL),
  _filename("filename", "Copy recording data to file, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false, NULL) {
  _dcmdparser.add_dcmd_option(&_name);
  _dcmdparser.add_dcmd_option(&_filename);
};
int JfrStopFlightRecordingDCmd::num_arguments() {
  ResourceMark rm;
  JfrStopFlightRecordingDCmd* dcmd = new JfrStopFlightRecordingDCmd(NULL, false);
  if (dcmd != NULL) {
    DCmdMark mark(dcmd);
    return dcmd->_dcmdparser.num_arguments();
  }
  return 0;
}
void JfrStopFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) {
    return;
  }
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JNIHandleBlockManager jni_handle_management(THREAD);
  JavaValue result(T_OBJECT);
  JfrJavaArguments constructor_args(&result);
  constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStop", CHECK);
  const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
  Handle h_dcmd_instance(THREAD, dcmd);
  assert(h_dcmd_instance.not_null(), "invariant");
  jstring name = NULL;
  if (_name.is_set() && _name.value()  != NULL) {
    name = JfrJavaSupport::new_string(_name.value(), CHECK);
  }
  jstring filepath = NULL;
  if (_filename.is_set() && _filename.value() != NULL) {
    filepath = JfrJavaSupport::new_string(_filename.value(), CHECK);
  }
  static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStop";
  static const char method[] = "execute";
  static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;";
  JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
  execute_args.set_receiver(h_dcmd_instance);
  execute_args.push_jobject(name);
  execute_args.push_jobject(filepath);
  JfrJavaSupport::call_virtual(&execute_args, THREAD);
  handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrConfigureFlightRecorderDCmd::JfrConfigureFlightRecorderDCmd(outputStream* output,
                                                               bool heap) : DCmdWithParser(output, heap),
  _repository_path("repositorypath", "Path to repository,.e.g \\\"My Repository\\\"", "STRING", false, NULL),
  _dump_path("dumppath", "Path to dump,.e.g \\\"My Dump path\\\"", "STRING", false, NULL),
  _stack_depth("stackdepth", "Stack Depth", "JULONG", false, "64"),
  _global_buffer_count("globalbuffercount", "Number of global buffers,", "JULONG", false, "20"),
  _global_buffer_size("globalbuffersize", "Size of a global buffers,", "MEMORY SIZE", false, "512k"),
  _thread_buffer_size("thread_buffer_size", "Size of a thread buffer", "MEMORY SIZE", false, "8k"),
  _memory_size("memorysize", "Overall memory size, ", "MEMORY SIZE", false, "10m"),
  _max_chunk_size("maxchunksize", "Size of an individual disk chunk", "MEMORY SIZE", false, "12m"),
  _sample_threads("samplethreads", "Activate Thread sampling", "BOOLEAN", false, "true") {
  _dcmdparser.add_dcmd_option(&_repository_path);
  _dcmdparser.add_dcmd_option(&_dump_path);
  _dcmdparser.add_dcmd_option(&_stack_depth);
  _dcmdparser.add_dcmd_option(&_global_buffer_count);
  _dcmdparser.add_dcmd_option(&_global_buffer_size);
  _dcmdparser.add_dcmd_option(&_thread_buffer_size);
  _dcmdparser.add_dcmd_option(&_memory_size);
  _dcmdparser.add_dcmd_option(&_max_chunk_size);
  _dcmdparser.add_dcmd_option(&_sample_threads);
};
int JfrConfigureFlightRecorderDCmd::num_arguments() {
  ResourceMark rm;
  JfrConfigureFlightRecorderDCmd* dcmd = new JfrConfigureFlightRecorderDCmd(NULL, false);
  if (dcmd != NULL) {
    DCmdMark mark(dcmd);
    return dcmd->_dcmdparser.num_arguments();
  }
  return 0;
}
void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  if (invalid_state(output(), THREAD)) {
    return;
  }
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JNIHandleBlockManager jni_handle_management(THREAD);
  JavaValue result(T_OBJECT);
  JfrJavaArguments constructor_args(&result);
  constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdConfigure", CHECK);
  const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
  Handle h_dcmd_instance(THREAD, dcmd);
  assert(h_dcmd_instance.not_null(), "invariant");
  jstring repository_path = NULL;
  if (_repository_path.is_set() && _repository_path.value() != NULL) {
    repository_path = JfrJavaSupport::new_string(_repository_path.value(), CHECK);
  }
  jstring dump_path = NULL;
  if (_dump_path.is_set() && _dump_path.value() != NULL) {
    dump_path = JfrJavaSupport::new_string(_dump_path.value(), CHECK);
  }
  jobject stack_depth = NULL;
  if (_stack_depth.is_set()) {
    stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK);
  }
  jobject global_buffer_count = NULL;
  if (_global_buffer_count.is_set()) {
    global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK);
  }
  jobject global_buffer_size = NULL;
  if (_global_buffer_size.is_set()) {
    global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK);
  }
  jobject thread_buffer_size = NULL;
  if (_thread_buffer_size.is_set()) {
    thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK);
  }
  jobject max_chunk_size = NULL;
  if (_max_chunk_size.is_set()) {
    max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK);
  }
  jobject memory_size = NULL;
  if (_memory_size.is_set()) {
    memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK);
  }
  jobject sample_threads = NULL;
  if (_sample_threads.is_set()) {
    sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK);
  }
  static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure";
  static const char method[] = "execute";
  static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;"
    "Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;"
    "Ljava/lang/Long;Ljava/lang/Boolean;)Ljava/lang/String;";
  JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
  execute_args.set_receiver(h_dcmd_instance);
  execute_args.push_jobject(repository_path);
  execute_args.push_jobject(dump_path);
  execute_args.push_jobject(stack_depth);
  execute_args.push_jobject(global_buffer_count);
  execute_args.push_jobject(global_buffer_size);
  execute_args.push_jobject(thread_buffer_size);
  execute_args.push_jobject(memory_size);
  execute_args.push_jobject(max_chunk_size);
  execute_args.push_jobject(sample_threads);
  JfrJavaSupport::call_virtual(&execute_args, THREAD);
  handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
bool register_jfr_dcmds() {
  uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export, true, false));
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export, true, false));
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export, true, false));
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export, true, false));
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export, true, false));
  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrUnlockCommercialFeaturesDCmd>(full_export, true, false));
  return true;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/dcmd/jfrDcmds.hpp
#ifndef SHARE_VM_JFR_JFRDCMDS_HPP
#define SHARE_VM_JFR_JFRDCMDS_HPP
#include "services/diagnosticCommand.hpp"
class JfrDumpFlightRecordingDCmd : public DCmdWithParser {
 protected:
  DCmdArgument<char*> _name;
  DCmdArgument<char*> _filename;
  DCmdArgument<NanoTimeArgument> _maxage;
  DCmdArgument<MemorySizeArgument> _maxsize;
  DCmdArgument<char*> _begin;
  DCmdArgument<char*> _end;
  DCmdArgument<bool>  _path_to_gc_roots;
 public:
  JfrDumpFlightRecordingDCmd(outputStream* output, bool heap);
  static const char* name() {
    return "JFR.dump";
  }
  static const char* description() {
    return "Copies contents of a JFR recording to file. Either the name or the recording id must be specified.";
  }
  static const char* impact() {
    return "Low";
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
    return p;
  }
  static int num_arguments();
  virtual void execute(DCmdSource source, TRAPS);
};
class JfrCheckFlightRecordingDCmd : public DCmdWithParser {
 protected:
  DCmdArgument<char*> _name;
  DCmdArgument<bool>  _verbose;
 public:
  JfrCheckFlightRecordingDCmd(outputStream* output, bool heap);
  static const char* name() {
    return "JFR.check";
  }
  static const char* description() {
    return "Checks running JFR recording(s)";
  }
  static const char* impact() {
    return "Low";
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
    return p;
  }
  static int num_arguments();
  virtual void execute(DCmdSource source, TRAPS);
};
class JfrStartFlightRecordingDCmd : public DCmdWithParser {
 protected:
  DCmdArgument<char*> _name;
  DCmdArgument<StringArrayArgument*> _settings;
  DCmdArgument<NanoTimeArgument> _delay;
  DCmdArgument<NanoTimeArgument> _duration;
  DCmdArgument<bool> _disk;
  DCmdArgument<char*> _filename;
  DCmdArgument<NanoTimeArgument> _maxage;
  DCmdArgument<MemorySizeArgument> _maxsize;
  DCmdArgument<bool> _dump_on_exit;
  DCmdArgument<bool> _path_to_gc_roots;
 public:
  JfrStartFlightRecordingDCmd(outputStream* output, bool heap);
  static const char* name() {
    return "JFR.start";
  }
  static const char* description() {
    return "Starts a new JFR recording";
  }
  static const char* impact() {
    return "Medium: Depending on the settings for a recording, the impact can range from low to high.";
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
    return p;
  }
  static int num_arguments();
  virtual void execute(DCmdSource source, TRAPS);
};
class JfrStopFlightRecordingDCmd : public DCmdWithParser {
 protected:
  DCmdArgument<char*> _name;
  DCmdArgument<char*> _filename;
 public:
  JfrStopFlightRecordingDCmd(outputStream* output, bool heap);
  static const char* name() {
    return "JFR.stop";
  }
  static const char* description() {
    return "Stops a JFR recording";
  }
  static const char* impact() {
    return "Low";
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
    return p;
  }
  static int num_arguments();
  virtual void execute(DCmdSource source, TRAPS);
};
class JfrRuntimeOptions;
class JfrConfigureFlightRecorderDCmd : public DCmdWithParser {
  friend class JfrOptionSet;
 protected:
  DCmdArgument<char*> _repository_path;
  DCmdArgument<char*> _dump_path;
  DCmdArgument<jlong> _stack_depth;
  DCmdArgument<jlong> _global_buffer_count;
  DCmdArgument<MemorySizeArgument> _global_buffer_size;
  DCmdArgument<MemorySizeArgument> _thread_buffer_size;
  DCmdArgument<MemorySizeArgument> _memory_size;
  DCmdArgument<MemorySizeArgument> _max_chunk_size;
  DCmdArgument<bool>  _sample_threads;
 public:
  JfrConfigureFlightRecorderDCmd(outputStream* output, bool heap);
  static const char* name() {
    return "JFR.configure";
  }
  static const char* description() {
    return "Configure JFR";
  }
  static const char* impact() {
    return "Low";
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
    return p;
  }
  static int num_arguments();
  virtual void execute(DCmdSource source, TRAPS);
};
class JfrUnlockCommercialFeaturesDCmd : public DCmd {
public:
  JfrUnlockCommercialFeaturesDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
  static const char* name() { return "VM.unlock_commercial_features"; }
  static const char* description() {
    return "Simulate commercial features unlocking for Zulu.";
  }
  static const char* impact() { return "Low"; }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission",
                        "monitor", NULL};
    return p;
  }
  static int num_arguments() { return 0; }
  virtual void execute(DCmdSource source, TRAPS) {
    UnlockCommercialFeatures = true;
  }
};
bool register_jfr_dcmds();
#endif // SHARE_VM_JFR_JFRDCMDS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/GenerateJfrFiles.java
package build.tools.jfr;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class GenerateJfrFiles {
    public static void main(String... args) throws Exception {
        if (args.length != 3) {
            System.err.println("Incorrect number of command line arguments.");
            System.err.println("Usage:");
            System.err.println("java GenerateJfrFiles[.java] <path-to-metadata.xml> <path-to-metadata.xsd> <output-directory>");
            System.exit(1);
        }
        try {
            File metadataXml = new File(args[0]);
            File metadataSchema = new File(args[1]);
            File outputDirectory = new File(args[2]);
            Metadata metadata = new Metadata(metadataXml, metadataSchema);
            metadata.verify();
            metadata.wireUpTypes();
            printJfrPeriodicHpp(metadata, outputDirectory);
            printJfrEventIdsHpp(metadata, outputDirectory);
            printJfrEventControlHpp(metadata, outputDirectory);
            printJfrTypesHpp(metadata, outputDirectory);
            printJfrEventClassesHpp(metadata, outputDirectory);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    static class XmlType {
        final String fieldType;
        final String parameterType;
        XmlType(String fieldType, String parameterType) {
            this.fieldType = fieldType;
            this.parameterType = parameterType;
        }
    }
    static class TypeElement {
        List<FieldElement> fields = new ArrayList<>();
        String name;
        String fieldType;
        String parameterType;
        boolean supportStruct;
    }
    interface TypePredicate {
        boolean isType(TypeElement type);
    }
    static class StringJoiner {
        private final CharSequence delimiter;
        private final List<CharSequence> elements;
        public StringJoiner(CharSequence delimiter) {
            this.delimiter = delimiter;
            elements = new LinkedList<CharSequence>();
        }
        public StringJoiner add(CharSequence newElement) {
            elements.add(newElement);
            return this;
        }
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            Iterator<CharSequence> i = elements.iterator();
            while (i.hasNext()) {
                builder.append(i.next());
                if (i.hasNext()) {
                    builder.append(delimiter);
                }
            }
            return builder.toString();
        }
    }
    static class Metadata {
        final Map<String, TypeElement> types = new LinkedHashMap<>();
        final Map<String, XmlType> xmlTypes = new HashMap<>();
        Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {
            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setSchema(schemaFactory.newSchema(metadataSchema));
            SAXParser sp = factory.newSAXParser();
            sp.parse(metadataXml, new MetadataHandler(this));
        }
        List<EventElement> getEvents() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == EventElement.class;
                }
            });
        }
        List<TypeElement> getEventsAndStructs() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == EventElement.class || t.supportStruct;
                }
            });
        }
        List<TypeElement> getTypesAndStructs() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == TypeElement.class || t.supportStruct;
                }
            });
        }
        @SuppressWarnings("unchecked")
        <T> List<T> getList(TypePredicate pred) {
            List<T> result = new ArrayList<>(types.size());
            for (TypeElement t : types.values()) {
                if (pred.isType(t)) {
                    result.add((T) t);
                }
            }
            return result;
        }
        List<EventElement> getPeriodicEvents() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == EventElement.class && ((EventElement) t).periodic;
                }
            });
        }
        List<TypeElement> getNonEventsAndNonStructs() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() != EventElement.class && !t.supportStruct;
                }
            });
        }
        List<TypeElement> getTypes() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == TypeElement.class && !t.supportStruct;
                }
            });
        }
        List<TypeElement> getStructs() {
            return getList(new TypePredicate() {
                @Override
                public boolean isType(TypeElement t) {
                    return t.getClass() == TypeElement.class && t.supportStruct;
                }
            });
        }
        void verify()  {
            for (TypeElement t : types.values()) {
                for (FieldElement f : t.fields) {
                    if (!xmlTypes.containsKey(f.typeName)) { // ignore primitives
                        if (!types.containsKey(f.typeName)) {
                            throw new IllegalStateException("Could not find definition of type '" + f.typeName + "' used by " + t.name + "#" + f.name);
                        }
                    }
                }
            }
        }
        void wireUpTypes() {
            for (TypeElement t : types.values()) {
                for (FieldElement f : t.fields) {
                    TypeElement type = types.get(f.typeName);
                    if (f.struct) {
                        type.supportStruct = true;
                    }
                    f.type = type;
                }
            }
        }
    }
    static class EventElement extends TypeElement {
        String representation;
        boolean thread;
        boolean stackTrace;
        boolean startTime;
        boolean periodic;
        boolean cutoff;
    }
    static class FieldElement {
        final Metadata metadata;
        TypeElement type;
        String name;
        String typeName;
        boolean struct;
        FieldElement(Metadata metadata) {
            this.metadata = metadata;
        }
        String getParameterType() {
            if (struct) {
                return "const JfrStruct" + typeName + "&";
            }
            XmlType xmlType = metadata.xmlTypes.get(typeName);
            if (xmlType != null) {
                return xmlType.parameterType;
            }
            return type != null ? "u8" : typeName;
        }
        String getParameterName() {
            return struct ? "value" : "new_value";
        }
        String getFieldType() {
            if (struct) {
                return "JfrStruct" + typeName;
            }
            XmlType xmlType = metadata.xmlTypes.get(typeName);
            if (xmlType != null) {
                return xmlType.fieldType;
            }
            return type != null ? "u8" : typeName;
        }
    }
    static class MetadataHandler extends DefaultHandler {
        final Metadata metadata;
        FieldElement currentField;
        TypeElement currentType;
        MetadataHandler(Metadata metadata) {
            this.metadata = metadata;
        }
        @Override
        public void error(SAXParseException e) throws SAXException {
          throw e;
        }
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            switch (qName) {
            case "XmlType":
                String name = attributes.getValue("name");
                String parameterType = attributes.getValue("parameterType");
                String fieldType = attributes.getValue("fieldType");
                metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType));
                break;
            case "Type":
                currentType = new TypeElement();
                currentType.name = attributes.getValue("name");
                break;
            case "Event":
                EventElement eventtType = new EventElement();
                eventtType.name = attributes.getValue("name");
                eventtType.thread = getBoolean(attributes, "thread", false);
                eventtType.stackTrace = getBoolean(attributes, "stackTrace", false);
                eventtType.startTime = getBoolean(attributes, "startTime", true);
                eventtType.periodic = attributes.getValue("period") != null;
                eventtType.cutoff = getBoolean(attributes, "cutoff", false);
                currentType = eventtType;
                break;
            case "Field":
                currentField = new FieldElement(metadata);
                currentField.struct = getBoolean(attributes, "struct", false);
                currentField.name = attributes.getValue("name");
                currentField.typeName = attributes.getValue("type");
                break;
            }
        }
        private boolean getBoolean(Attributes attributes, String name, boolean defaultValue) {
            String value = attributes.getValue(name);
            return value == null ? defaultValue : Boolean.valueOf(value);
        }
        @Override
        public void endElement(String uri, String localName, String qName) {
            switch (qName) {
            case "Type":
            case "Event":
                metadata.types.put(currentType.name, currentType);
                currentType = null;
                break;
            case "Field":
                currentType.fields.add(currentField);
                currentField = null;
                break;
            }
        }
    }
    static class Printer implements AutoCloseable {
        final PrintStream out;
        Printer(File outputDirectory, String filename) throws FileNotFoundException {
            out = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outputDirectory, filename))));
            write("/* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */");
            write("");
        }
        void write(String text) {
            out.print(text);
            out.print("\n"); // Don't use Windows line endings
        }
        @Override
        public void close() throws Exception {
            out.close();
        }
    }
    private static void printJfrPeriodicHpp(Metadata metadata, File outputDirectory) throws Exception {
        try (Printer out = new Printer(outputDirectory, "jfrPeriodic.hpp")) {
            out.write("#ifndef JFRFILES_JFRPERIODICEVENTSET_HPP");
            out.write("#define JFRFILES_JFRPERIODICEVENTSET_HPP");
            out.write("");
            out.write("#include \"utilities/macros.hpp\"");
            out.write("#if INCLUDE_JFR");
            out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
            out.write("#include \"memory/allocation.hpp\"");
            out.write("");
            out.write("class JfrPeriodicEventSet : public AllStatic {");
            out.write(" public:");
            out.write("  static void requestEvent(JfrEventId id) {");
            out.write("    switch(id) {");
            out.write("  ");
            for (EventElement e : metadata.getPeriodicEvents()) {
                out.write("      case Jfr" + e.name + "Event:");
                out.write("        request" + e.name + "();");
                out.write("        break;");
                out.write("  ");
            }
            out.write("      default:");
            out.write("        break;");
            out.write("      }");
            out.write("    }");
            out.write("");
            out.write(" private:");
            out.write("");
            for (EventElement e : metadata.getPeriodicEvents()) {
                out.write("  static void request" + e.name + "(void);");
                out.write("");
            }
            out.write("};");
            out.write("");
            out.write("#endif // INCLUDE_JFR");
            out.write("#endif // JFRFILES_JFRPERIODICEVENTSET_HPP");
        }
    }
    private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception {
        try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) {
            out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
            out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
            out.write("");
            out.write("#include \"utilities/macros.hpp\"");
            out.write("#if INCLUDE_JFR");
            out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
            out.write("");
            out.write("/**");
            out.write(" * Event setting. We add some padding so we can use our");
            out.write(" * event IDs as indexes into this.");
            out.write(" */");
            out.write("");
            out.write("struct jfrNativeEventSetting {");
            out.write("  jlong  threshold_ticks;");
            out.write("  jlong  cutoff_ticks;");
            out.write("  u1     stacktrace;");
            out.write("  u1     enabled;");
            out.write("  u1     pad[6]; // Because GCC on linux ia32 at least tries to pack this.");
            out.write("};");
            out.write("");
            out.write("union JfrNativeSettings {");
            out.write("  // Array version.");
            out.write("  jfrNativeEventSetting bits[MaxJfrEventId];");
            out.write("  // Then, to make it easy to debug,");
            out.write("  // add named struct members also.");
            out.write("  struct {");
            out.write("    jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];");
            for (TypeElement t : metadata.getEventsAndStructs()) {
                out.write("    jfrNativeEventSetting " + t.name + ";");
            }
            out.write("  } ev;");
            out.write("};");
            out.write("");
            out.write("#endif // INCLUDE_JFR");
            out.write("#endif // JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
        }
    }
    private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception {
        try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) {
            out.write("#ifndef JFRFILES_JFREVENTIDS_HPP");
            out.write("#define JFRFILES_JFREVENTIDS_HPP");
            out.write("");
            out.write("#include \"utilities/macros.hpp\"");
            out.write("#if INCLUDE_JFR");
            out.write("#include \"jfrfiles/jfrTypes.hpp\"");
            out.write("");
            out.write("/**");
            out.write(" * Enum of the event types in the JVM");
            out.write(" */");
            out.write("enum JfrEventId {");
            out.write("  _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index.");
            out.write("  ");
            out.write("  // Events -> enum entry");
            for (TypeElement t : metadata.getEventsAndStructs()) {
                out.write("  Jfr" + t.name + "Event,");
            }
            out.write("");
            out.write("  MaxJfrEventId");
            out.write("};");
            out.write("");
            out.write("/**");
            out.write(" * Struct types in the JVM");
            out.write(" */");
            out.write("enum JfrStructId {");
            for (TypeElement t : metadata.getNonEventsAndNonStructs()) {
                out.write("  Jfr" + t.name + "Struct,");
            }
            for (TypeElement t : metadata.getEventsAndStructs()) {
                out.write("  Jfr" + t.name + "Struct,");
            }
            out.write("");
            out.write("  MaxJfrStructId");
            out.write("};");
            out.write("");
            out.write("typedef enum JfrEventId JfrEventId;");
            out.write("typedef enum JfrStructId JfrStructId;");
            out.write("");
            out.write("#endif // INCLUDE_JFR");
            out.write("#endif // JFRFILES_JFREVENTIDS_HPP");
        }
    }
    private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception {
      List<String> knownTypes = Arrays.asList(new String[] {"Thread", "StackTrace", "Class", "StackFrame"});
        try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) {
            out.write("#ifndef JFRFILES_JFRTYPES_HPP");
            out.write("#define JFRFILES_JFRTYPES_HPP");
            out.write("");
            out.write("#include \"utilities/macros.hpp\"");
            out.write("#if INCLUDE_JFR");
            out.write("");
            out.write("enum JfrTypeId {");
            out.write("  TYPE_NONE             = 0,");
            out.write("  TYPE_CLASS            = 20,");
            out.write("  TYPE_STRING           = 21,");
            out.write("  TYPE_THREAD           = 22,");
            out.write("  TYPE_STACKTRACE       = 23,");
            out.write("  TYPE_BYTES            = 24,");
            out.write("  TYPE_EPOCHMILLIS      = 25,");
            out.write("  TYPE_MILLIS           = 26,");
            out.write("  TYPE_NANOS            = 27,");
            out.write("  TYPE_TICKS            = 28,");
            out.write("  TYPE_ADDRESS          = 29,");
            out.write("  TYPE_PERCENTAGE       = 30,");
            out.write("  TYPE_DUMMY,");
            out.write("  TYPE_DUMMY_1,");
            for (TypeElement type : metadata.getTypes()) {
                if (!knownTypes.contains(type.name)) {
                    out.write("  TYPE_" + type.name.toUpperCase() + ",");
                }
            }
            out.write("");
            out.write("  NUM_JFR_TYPES,");
            out.write("  TYPES_END             = 255");
            out.write("};");
            out.write("");
            out.write("enum ReservedEvent {");
            out.write("  EVENT_METADATA,");
            out.write("  EVENT_CHECKPOINT,");
            out.write("  EVENT_BUFFERLOST,");
            out.write("  NUM_RESERVED_EVENTS = TYPES_END");
            out.write("};");
            out.write("");
            out.write("#endif // INCLUDE_JFR");
            out.write("#endif // JFRFILES_JFRTYPES_HPP");
          };
    }
    private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception {
        try (Printer out = new Printer(outputDirectory, "jfrEventClasses.hpp")) {
            out.write("#ifndef JFRFILES_JFREVENTCLASSES_HPP");
            out.write("#define JFRFILES_JFREVENTCLASSES_HPP");
            out.write("");
            out.write("#include \"oops/klass.hpp\"");
            out.write("#include \"jfrfiles/jfrTypes.hpp\"");
            out.write("#include \"jfr/utilities/jfrTypes.hpp\"");
            out.write("#include \"utilities/macros.hpp\"");
            out.write("#include \"utilities/ticks.hpp\"");
            out.write("#if INCLUDE_JFR");
            out.write("#include \"jfr/recorder/service/jfrEvent.hpp\"");
            out.write("/*");
            out.write(" * Each event class has an assert member function verify() which is invoked");
            out.write(" * just before the engine writes the event and its fields to the data stream.");
            out.write(" * The purpose of verify() is to ensure that all fields in the event are initialized");
            out.write(" * and set before attempting to commit.");
            out.write(" *");
            out.write(" * We enforce this requirement because events are generally stack allocated and therefore");
            out.write(" * *not* initialized to default values. This prevents us from inadvertently committing");
            out.write(" * uninitialized values to the data stream.");
            out.write(" *");
            out.write(" * The assert message contains both the index (zero based) as well as the name of the field.");
            out.write(" */");
            out.write("");
            printTypes(out, metadata, false);
            out.write("");
            out.write("");
            out.write("#else // !INCLUDE_JFR");
            out.write("");
            out.write("template <typename T>");
            out.write("class JfrEvent {");
            out.write(" public:");
            out.write("  JfrEvent() {}");
            out.write("  void set_starttime(const Ticks&) const {}");
            out.write("  void set_endtime(const Ticks&) const {}");
            out.write("  bool should_commit() const { return false; }");
            out.write("  static bool is_enabled() { return false; }");
            out.write("  void commit() {}");
            out.write("};");
            out.write("");
            printTypes(out, metadata, true);
            out.write("");
            out.write("");
            out.write("#endif // INCLUDE_JFR");
            out.write("#endif // JFRFILES_JFREVENTCLASSES_HPP");
        }
    }
    private static void printTypes(Printer out, Metadata metadata, boolean empty) {
        for (TypeElement t : metadata.getStructs()) {
            printType(out, t, empty);
            out.write("");
        }
        for (EventElement e : metadata.getEvents()) {
            printEvent(out, e, empty);
            out.write("");
        }
    }
    private static void printType(Printer out, TypeElement t, boolean empty) {
        out.write("struct JfrStruct" + t.name);
        out.write("{");
        if (!empty) {
          out.write(" private:");
          for (FieldElement f : t.fields) {
              printField(out, f);
          }
          out.write("");
        }
        out.write(" public:");
        for (FieldElement f : t.fields) {
           printTypeSetter(out, f, empty);
        }
        out.write("");
        if (!empty) {
          printWriteData(out, t.fields);
        }
        out.write("};");
        out.write("");
    }
    private static void printEvent(Printer out, EventElement event, boolean empty) {
        out.write("class Event" + event.name + " : public JfrEvent<Event" + event.name + ">");
        out.write("{");
        if (!empty) {
          out.write(" private:");
          for (FieldElement f : event.fields) {
              printField(out, f);
          }
          out.write("");
        }
        out.write(" public:");
        if (!empty) {
          out.write("  static const bool hasThread = " + event.thread + ";");
          out.write("  static const bool hasStackTrace = " + event.stackTrace + ";");
          out.write("  static const bool isInstant = " + !event.startTime + ";");
          out.write("  static const bool hasCutoff = " + event.cutoff + ";");
          out.write("  static const bool isRequestable = " + event.periodic + ";");
          out.write("  static const JfrEventId eventId = Jfr" + event.name + "Event;");
          out.write("");
        }
        if (!empty) {
          out.write("  Event" + event.name + "(EventStartTime timing=TIMED) : JfrEvent<Event" + event.name + ">(timing) {}");
        } else {
          out.write("  Event" + event.name + "(EventStartTime timing=TIMED) {}");
        }
        out.write("");
        int index = 0;
        for (FieldElement f : event.fields) {
            out.write("  void set_" + f.name + "(" + f.getParameterType() + " " + f.getParameterName() + ") {");
            if (!empty) {
              out.write("    this->_" + f.name + " = " + f.getParameterName() + ";");
              out.write("    DEBUG_ONLY(set_field_bit(" + index++ + "));");
            }
            out.write("  }");
        }
        out.write("");
        if (!empty) {
          printWriteData(out, event.fields);
          out.write("");
        }
        out.write("  using JfrEvent<Event" + event.name + ">::commit; // else commit() is hidden by overloaded versions in this class");
        printConstructor2(out, event, empty);
        printCommitMethod(out, event, empty);
        if (!empty) {
          printVerify(out, event.fields);
        }
        out.write("};");
    }
    private static void printWriteData(Printer out, List<FieldElement> fields) {
        out.write("  template <typename Writer>");
        out.write("  void writeData(Writer& w) {");
        for (FieldElement field : fields) {
            if (field.struct) {
                out.write("    _" + field.name + ".writeData(w);");
            } else {
                out.write("    w.write(_" + field.name + ");");
            }
        }
        out.write("  }");
    }
    private static void printTypeSetter(Printer out, FieldElement field, boolean empty) {
        if (!empty) {
          out.write("  void set_" + field.name + "(" + field.getParameterType() + " new_value) { this->_" + field.name + " = new_value; }");
        } else {
          out.write("  void set_" + field.name + "(" + field.getParameterType() + " new_value) { }");
        }
    }
    private static void printVerify(Printer out, List<FieldElement> fields) {
        out.write("");
        out.write("#ifdef ASSERT");
        out.write("  void verify() const {");
        int index = 0;
        for (FieldElement f : fields) {
            out.write("    assert(verify_field_bit(" + index++ + "), \"Attempting to write an uninitialized event field: " + f.name + "\");");
        }
        out.write("  }");
        out.write("#endif");
    }
    private static void printCommitMethod(Printer out, EventElement event, boolean empty) {
        if (event.startTime) {
            StringJoiner sj = new StringJoiner(",\n              ");
            for (FieldElement f : event.fields) {
                sj.add(f.getParameterType() + " " + f.name);
            }
            out.write("");
            out.write("  void commit(" + sj.toString() + ") {");
            if (!empty) {
              out.write("    if (should_commit()) {");
              for (FieldElement f : event.fields) {
                  out.write("      set_" + f.name + "(" + f.name + ");");
              }
              out.write("      commit();");
              out.write("    }");
            }
            out.write("  }");
        }
        out.write("");
        StringJoiner sj = new StringJoiner(",\n                     ");
        if (event.startTime) {
            sj.add("const Ticks& startTicks");
            sj.add("const Ticks& endTicks");
        }
        for (FieldElement f : event.fields) {
            sj.add(f.getParameterType() + " " + f.name);
        }
        out.write("  static void commit(" + sj.toString() + ") {");
        if (!empty) {
          out.write("    Event" + event.name + " me(UNTIMED);");
          out.write("");
          out.write("    if (me.should_commit()) {");
          if (event.startTime) {
              out.write("      me.set_starttime(startTicks);");
              out.write("      me.set_endtime(endTicks);");
          }
          for (FieldElement f : event.fields) {
              out.write("      me.set_" + f.name + "(" + f.name + ");");
          }
          out.write("      me.commit();");
          out.write("    }");
        }
        out.write("  }");
    }
    private static void printConstructor2(Printer out, EventElement event, boolean empty) {
        if (!event.startTime) {
            out.write("");
            out.write("");
        }
        if (event.startTime) {
            out.write("");
            out.write("  Event" + event.name + "(");
            StringJoiner sj = new StringJoiner(",\n    ");
            for (FieldElement f : event.fields) {
                sj.add(f.getParameterType() + " " + f.name);
            }
            if (!empty) {
              out.write("    " + sj.toString() + ") : JfrEvent<Event" + event.name + ">(TIMED) {");
              out.write("    if (should_commit()) {");
              for (FieldElement f : event.fields) {
                  out.write("      set_" + f.name + "(" + f.name + ");");
              }
              out.write("    }");
            } else {
              out.write("    " + sj.toString() + ") {");
            }
            out.write("  }");
        }
    }
    private static void printField(Printer out, FieldElement field) {
        out.write("  " + field.getFieldType() + " _" + field.name + ";");
    }
}
C:\hotspot-69087d08d473\src\share\vm/jfr/instrumentation/jfrEventClassTransformer.cpp
#include "precompiled.hpp"
#include "jvm.h"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/stackMapTable.hpp"
#include "classfile/verificationType.hpp"
#include "interpreter/bytecodes.hpp"
#include "jfr/instrumentation/jfrEventClassTransformer.hpp"
#include "jfr/jfr.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrUpcalls.hpp"
#include "jfr/support/jfrEventClass.hpp"
#include "jfr/utilities/jfrBigEndian.hpp"
#include "jfr/writers/jfrBigEndianWriter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
static const u2 number_of_new_methods = 5;
static const u2 number_of_new_fields = 3;
static const int extra_stream_bytes = 0x280;
static const u2 invalid_cp_index = 0;
static const char* utf8_constants[] = {
  "Code",         // 0
  "J",            // 1
  "commit",       // 2
  "eventHandler", // 3
  "Ljdk/jfr/proxy/internal/EventHandlerProxy;", // 4
  "duration",     // 5
  "begin",        // 6
  "()V",          // 7
  "isEnabled",    // 8
  "()Z",          // 9
  "end",          // 10
  "shouldCommit", // 11
  "startTime",    // 12
  "<clinit>",     // 13
  "jdk/jfr/FlightRecorder", // 14
  "register", // 15
  "(Ljava/lang/Class;)V", // 16 // LAST_REQUIRED_UTF8
  "StackMapTable", // 17
  "Exceptions", // 18
  "LineNumberTable", // 20
  "LocalVariableTable", // 21
  "LocalVariableTypeTable", // 22
  "RuntimeVisibleAnnotation" // 23
};
enum utf8_req_symbols {
  UTF8_REQ_Code,
  UTF8_REQ_J_FIELD_DESC,
  UTF8_REQ_commit,
  UTF8_REQ_eventHandler,
  UTF8_REQ_eventHandler_FIELD_DESC,
  UTF8_REQ_duration,
  UTF8_REQ_begin,
  UTF8_REQ_EMPTY_VOID_METHOD_DESC,
  UTF8_REQ_isEnabled,
  UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC,
  UTF8_REQ_end,
  UTF8_REQ_shouldCommit,
  UTF8_REQ_startTime,
  UTF8_REQ_clinit,
  UTF8_REQ_FlightRecorder,
  UTF8_REQ_register,
  UTF8_REQ_CLASS_VOID_METHOD_DESC,
  NOF_UTF8_REQ_SYMBOLS
};
enum utf8_opt_symbols {
  UTF8_OPT_StackMapTable = NOF_UTF8_REQ_SYMBOLS,
  UTF8_OPT_Exceptions,
  UTF8_OPT_LineNumberTable,
  UTF8_OPT_LocalVariableTable,
  UTF8_OPT_LocalVariableTypeTable,
  UTF8_OPT_RuntimeVisibleAnnotation,
  NOF_UTF8_SYMBOLS
};
static u1 empty_void_method_code_attribute[] = {
  0x0,
  0x0,
  0x0,
  0xd, // attribute len
  0x0,
  0x0, // max stack
  0x0,
  0x1, // max locals
  0x0,
  0x0,
  0x0,
  0x1, // code length
  Bytecodes::_return,
  0x0,
  0x0, // ex table len
  0x0,
  0x0  // attributes_count
};
static u1 boolean_method_code_attribute[] = {
  0x0,
  0x0,
  0x0,
  0xe,
  0x0,
  0x1, // max stack
  0x0,
  0x1, // max locals
  0x0,
  0x0,
  0x0,
  0x2,
  Bytecodes::_iconst_0,
  Bytecodes::_ireturn,
  0x0,
  0x0, // ex table len
  0x0,
  0x0, // attributes_count
};
enum {  // initial annotation layout
  atype_off = 0,      // utf8 such as 'Ljava/lang/annotation/Retention;'
  count_off = 2,      // u2   such as 1 (one value)
  member_off = 4,     // utf8 such as 'value'
  tag_off = 6,        // u1   such as 'c' (type) or 'e' (enum)
  e_tag_val = 'e',
  e_type_off = 7,   // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
  e_con_off = 9,    // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
  e_size = 11,     // end of 'e' annotation
  c_tag_val = 'c',    // payload is type
  c_con_off = 7,    // utf8 payload, such as 'I'
  c_size = 9,       // end of 'c' annotation
  s_tag_val = 's',    // payload is String
  s_con_off = 7,    // utf8 payload, such as 'Ljava/lang/String;'
  s_size = 9,
  min_size = 6        // smallest possible size (zero members)
};
static int skip_annotation_value(const address, int, int); // fwd decl
static int next_annotation_index(const address buffer, int limit, int index) {
  assert(buffer != NULL, "invariant");
  index += 2;  // skip atype
  if ((index += 2) >= limit) {
    return limit;
  }
  int nof_members = JfrBigEndian::read<u2>(buffer + index - 2);
  while (--nof_members >= 0 && index < limit) {
    index += 2; // skip member
    index = skip_annotation_value(buffer, limit, index);
  }
  return index;
}
static int skip_annotation_value(const address buffer, int limit, int index) {
  assert(buffer != NULL, "invariant");
  if ((index += 1) >= limit) {
    return limit;
  }
  const u1 tag = buffer[index - 1];
  switch (tag) {
    case 'B':
    case 'C':
    case 'I':
    case 'S':
    case 'Z':
    case 'D':
    case 'F':
    case 'J':
    case 'c':
    case 's':
      index += 2;  // skip con or s_con
      break;
    case 'e':
      index += 4;  // skip e_class, e_name
      break;
    case '[':
      {
        if ((index += 2) >= limit) {
          return limit;
        }
        int nof_values = JfrBigEndian::read<u2>(buffer + index - 2);
        while (--nof_values >= 0 && index < limit) {
          index = skip_annotation_value(buffer, limit, index);
        }
      }
      break;
    case '@':
      index = next_annotation_index(buffer, limit, index);
      break;
    default:
      return limit;  //  bad tag byte
  }
  return index;
}
static const u2 number_of_elements_offset = (u2)2;
static const u2 element_name_offset = (u2)(number_of_elements_offset + 2);
static const u2 element_name_size = (u2)2;
static const u2 value_type_relative_offset = (u2)2;
static const u2 value_relative_offset = (u2)(value_type_relative_offset + 1);
class AnnotationElementIterator : public StackObj {
 private:
  const InstanceKlass* _ik;
  const address _buffer;
  const u2 _limit; // length of annotation
  mutable u2 _current; // element
  mutable u2 _next; // element
  u2 value_index() const {
    return JfrBigEndian::read<u2>(_buffer + _current + value_relative_offset);
  }
 public:
  AnnotationElementIterator(const InstanceKlass* ik, address buffer, u2 limit) : _ik(ik),
                                                                                 _buffer(buffer),
                                                                                 _limit(limit),
                                                                                 _next(element_name_offset),
                                                                                 _current(element_name_offset) {
    assert(_buffer != NULL, "invariant");
    assert(_next == element_name_offset, "invariant");
    assert(_current == element_name_offset, "invariant");
  }
  bool has_next() const {
    return _next < _limit;
  }
  void move_to_next() const {
    assert(has_next(), "invariant");
    _current = _next;
    if (_next < _limit) {
      _next = skip_annotation_value(_buffer, _limit, _next + element_name_size);
    }
    assert(_next <= _limit, "invariant");
    assert(_current <= _limit, "invariant");
  }
  u2 number_of_elements() const {
    return JfrBigEndian::read<u2>(_buffer + number_of_elements_offset);
  }
  const Symbol* name() const {
    assert(_current < _next, "invariant");
    return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current));
  }
  char value_type() const {
    return JfrBigEndian::read<u1>(_buffer + _current + value_type_relative_offset);
  }
  jint read_int() const {
    return _ik->constants()->int_at(value_index());
  }
  bool read_bool() const {
    return read_int() != 0;
  }
};
class AnnotationIterator : public StackObj {
 private:
  const InstanceKlass* _ik;
  u2 _limit; // length of annotations array
  const address _buffer;
  mutable u2 _current; // annotation
  mutable u2 _next; // annotation
 public:
  AnnotationIterator(const InstanceKlass* ik, AnnotationArray* ar) : _ik(ik),
                                                                     _current(0),
                                                                     _next(0),
                                                                     _limit(ar != NULL ? ar->length() : 0),
                                                                     _buffer(_limit > 2 ? ar->adr_at(2) : NULL) {
    if (_buffer != NULL) {
      _limit -= 2; // subtract sizeof(u2) number of annotations field
    }
  }
  bool has_next() const {
    return _next < _limit;
  }
  void move_to_next() const {
    assert(has_next(), "invariant");
    _current = _next;
    if (_next < _limit) {
      _next = next_annotation_index(_buffer, _limit, _next);
    }
    assert(_next <= _limit, "invariant");
    assert(_current <= _limit, "invariant");
  }
  const AnnotationElementIterator elements() const {
    assert(_current < _next, "invariant");
    return AnnotationElementIterator(_ik, _buffer + _current, _next - _current);
  }
  const Symbol* type() const {
    assert(_buffer != NULL, "invariant");
    assert(_current < _limit, "invariant");
    return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current));
  }
};
static unsigned int unused_hash = 0;
static const char value_name[] = "value";
static bool has_registered_annotation(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
  assert(annotation_type != NULL, "invariant");
  AnnotationArray* class_annotations = ik->class_annotations();
  if (class_annotations == NULL) {
    return false;
  }
  const AnnotationIterator annotation_iterator(ik, class_annotations);
  while (annotation_iterator.has_next()) {
    annotation_iterator.move_to_next();
    if (annotation_iterator.type() == annotation_type) {
      static const Symbol* value_symbol =
        SymbolTable::lookup_only(value_name, sizeof value_name - 1, unused_hash);
      assert(value_symbol != NULL, "invariant");
      const AnnotationElementIterator element_iterator = annotation_iterator.elements();
      while (element_iterator.has_next()) {
        element_iterator.move_to_next();
        if (value_symbol == element_iterator.name()) {
          assert('Z' == element_iterator.value_type(), "invariant");
          value = element_iterator.read_bool();
          return true;
        }
      }
    }
  }
  return false;
}
static bool registered_annotation_value(const InstanceKlass* ik, const Symbol* const registered_symbol) {
  assert(registered_symbol != NULL, "invariant");
  assert(ik != NULL, "invariant");
  assert(JdkJfrEvent::is_a(ik), "invariant");
  bool registered_value = false;
  if (has_registered_annotation(ik, registered_symbol, registered_value)) {
    return registered_value;
  }
  InstanceKlass* super = InstanceKlass::cast(ik->super());
  return registered_annotation_value(super, registered_symbol);
}
static const char registered_constant[] = "Ljdk/jfr/Registered;";
static bool should_register_klass(const InstanceKlass* ik) {
  static const Symbol* const registered_symbol = SymbolTable::lookup_only(registered_constant,
                                                                          sizeof registered_constant - 1,
                                                                          unused_hash);
  assert(registered_symbol != NULL, "invariant");
  return registered_annotation_value(ik, registered_symbol);
}
static u2 utf8_info_index(const InstanceKlass* ik, const Symbol* const target, TRAPS) {
  assert(target != NULL, "invariant");
  ConstantPool* cp = ik->constants();
  const int cp_len = cp->length();
  for (u2 index = 1; index < cp_len; ++index) {
    const constantTag tag = cp->tag_at(index);
    if (tag.is_utf8()) {
      const Symbol* const utf8_sym = cp->symbol_at(index);
      assert(utf8_sym != NULL, "invariant");
      if (utf8_sym == target) {
        return index;
      }
    }
  }
  return invalid_cp_index;
}
#ifdef ASSERT
static bool is_index_within_range(u2 index, u2 orig_cp_len, u2 new_cp_entries_len) {
  return index > 0 && index < orig_cp_len + new_cp_entries_len;
}
#endif
static u2 add_utf8_info(JfrBigEndianWriter& writer, const char* utf8_constant, u2 orig_cp_len, u2& new_cp_entries_len) {
  assert(utf8_constant != NULL, "invariant");
  writer.write<u1>(JVM_CONSTANT_Utf8);
  writer.write_utf8_u2_len(utf8_constant);
  assert(writer.is_valid(), "invariant");
  return orig_cp_len + new_cp_entries_len++;
}
static u2 add_method_ref_info(JfrBigEndianWriter& writer,
                              u2 cls_name_index,
                              u2 method_index,
                              u2 desc_index,
                              u2 orig_cp_len,
                              u2& number_of_new_constants,
                              TRAPS) {
  assert(is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants), "invariant");
  assert(is_index_within_range(method_index, orig_cp_len, number_of_new_constants), "invariant");
  assert(is_index_within_range(desc_index, orig_cp_len, number_of_new_constants), "invariant");
  writer.write<u1>(JVM_CONSTANT_Class);
  writer.write<u2>(cls_name_index);
  const u2 cls_entry_index = orig_cp_len + number_of_new_constants;
  ++number_of_new_constants;
  writer.write<u1>(JVM_CONSTANT_NameAndType);
  writer.write<u2>(method_index);
  writer.write<u2>(desc_index);
  const u2 nat_entry_index = orig_cp_len + number_of_new_constants;
  ++number_of_new_constants;
  writer.write<u1>(JVM_CONSTANT_Methodref);
  writer.write<u2>(cls_entry_index);
  writer.write<u2>(nat_entry_index);
  return orig_cp_len + number_of_new_constants++;
}
static u2 add_flr_register_method_constants(JfrBigEndianWriter& writer,
                                            const u2* utf8_indexes,
                                            u2 orig_cp_len,
                                            u2& number_of_new_constants,
                                            TRAPS) {
  assert(utf8_indexes != NULL, "invariant");
  return add_method_ref_info(writer,
                             utf8_indexes[UTF8_REQ_FlightRecorder],
                             utf8_indexes[UTF8_REQ_register],
                             utf8_indexes[UTF8_REQ_CLASS_VOID_METHOD_DESC],
                             orig_cp_len,
                             number_of_new_constants,
                             THREAD);
}
static jlong add_field_info(JfrBigEndianWriter& writer, u2 name_index, u2 desc_index, bool is_static = false) {
  assert(name_index > 0, "invariant");
  assert(desc_index > 0, "invariant");
  DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
  writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PRIVATE | (is_static ? JVM_ACC_STATIC : JVM_ACC_TRANSIENT)); // flags
  writer.write(name_index);
  writer.write(desc_index);
  writer.write((u2)0x0); // attributes_count
  assert(writer.is_valid(), "invariant");
  DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
  return writer.current_offset();
}
static u2 add_field_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes) {
  assert(utf8_indexes != NULL, "invariant");
  add_field_info(writer,
                 utf8_indexes[UTF8_REQ_eventHandler],
                 utf8_indexes[UTF8_REQ_eventHandler_FIELD_DESC],
                 true); // static
  add_field_info(writer,
                 utf8_indexes[UTF8_REQ_startTime],
                 utf8_indexes[UTF8_REQ_J_FIELD_DESC]);
  add_field_info(writer,
                 utf8_indexes[UTF8_REQ_duration],
                 utf8_indexes[UTF8_REQ_J_FIELD_DESC]);
  return number_of_new_fields;
}
static jlong add_method_info(JfrBigEndianWriter& writer,
                             u2 name_index,
                             u2 desc_index,
                             u2 code_index,
                             const u1* const code,
                             const size_t code_len) {
  assert(name_index > 0, "invariant");
  assert(desc_index > 0, "invariant");
  assert(code_index > 0, "invariant");
  DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
  writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PUBLIC); // flags
  writer.write(name_index);
  writer.write(desc_index);
  writer.write<u2>(0x1); // attributes_count ; 1 for "Code" attribute
  assert(writer.is_valid(), "invariant");
  DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
  writer.write(code_index); // "Code"
  writer.bytes(code, code_len);
  DEBUG_ONLY(assert((start_offset + 8 + 2 + (jlong)code_len) == writer.current_offset(), "invariant");)
  return writer.current_offset();
}
static u2 position_stream_after_cp(ClassFileStream* stream) {
  assert(stream != NULL, "invariant");
  assert(stream->current_offset() == 0, "invariant");
  stream->skip_u4_fast(2);  // 8 bytes skipped
  const u2 cp_len = stream->get_u2_fast();
  assert(cp_len > 0, "invariant");
  for (u2 index = 1; index < cp_len; ++index) {
    const u1 tag = stream->get_u1_fast(); // cp tag
    switch (tag) {
      case JVM_CONSTANT_Class:
      case JVM_CONSTANT_String: {
        stream->skip_u2_fast(1); // skip 2 bytes
        continue;
      }
      case JVM_CONSTANT_Fieldref:
      case JVM_CONSTANT_Methodref:
      case JVM_CONSTANT_InterfaceMethodref:
      case JVM_CONSTANT_Integer:
      case JVM_CONSTANT_Float:
      case JVM_CONSTANT_NameAndType:
      case JVM_CONSTANT_InvokeDynamic: {
        stream->skip_u4_fast(1); // skip 4 bytes
        continue;
      }
      case JVM_CONSTANT_Long:
      case JVM_CONSTANT_Double: {
        stream->skip_u4_fast(2); // skip 8 bytes
        ++index;
        continue;
      }
      case JVM_CONSTANT_Utf8: {
        u2 utf8_length = stream->get_u2_fast();
        stream->skip_u1_fast(utf8_length); // skip 2 + len bytes
        continue;
      }
      case JVM_CONSTANT_MethodHandle:
      case JVM_CONSTANT_MethodType: {
        if (tag == JVM_CONSTANT_MethodHandle) {
          stream->skip_u1_fast(1);
          stream->skip_u2_fast(1); // skip 3 bytes
        }
        else if (tag == JVM_CONSTANT_MethodType) {
          stream->skip_u2_fast(1); // skip 3 bytes
        }
      }
      continue;
      default:
        assert(false, "error in skip logic!");
        break;
    } // end switch(tag)
  }
  return cp_len;
}
static u2 position_stream_after_fields(ClassFileStream* stream) {
  assert(stream != NULL, "invariant");
  assert(stream->current_offset() > 0, "invariant");
  const u2 orig_fields_len = stream->get_u2_fast();
  for (u2 i = 0; i < orig_fields_len; ++i) {
    stream->skip_u2_fast(3);
    const u2 attrib_info_len = stream->get_u2_fast();
    for (u2 j = 0; j < attrib_info_len; ++j) {
      stream->skip_u2_fast(1);
      const u4 attrib_len = stream->get_u4_fast();
      stream->skip_u1_fast(attrib_len);
    }
  }
  return orig_fields_len;
}
static u2 position_stream_after_methods(JfrBigEndianWriter& writer,
                                        ClassFileStream* stream,
                                        const u2* utf8_indexes,
                                        bool register_klass,
                                        const Method* clinit_method,
                                        u4& orig_method_len_offset) {
  assert(stream != NULL, "invariant");
  assert(stream->current_offset() > 0, "invariant");
  assert(utf8_indexes != NULL, "invariant");
  writer.reserve(sizeof(u2));
  const u2 orig_methods_len = stream->get_u2_fast();
  orig_method_len_offset += sizeof(u2);
  for (u2 i = 0; i < orig_methods_len; ++i) {
    const u4 method_offset = stream->current_offset();
    stream->skip_u2_fast(1); // Access Flags
    const u2 name_index = stream->get_u2_fast(); // Name index
    stream->skip_u2_fast(1); // Descriptor index
    const u2 attributes_count = stream->get_u2_fast();
    for (u2 j = 0; j < attributes_count; ++j) {
      stream->skip_u2_fast(1);
      const u4 attrib_len = stream->get_u4_fast();
      stream->skip_u1_fast(attrib_len);
    }
    if (clinit_method != NULL && name_index == clinit_method->name_index()) {
      if (!register_klass) {
        continue;
      }
      writer.bytes(stream->buffer() + orig_method_len_offset,
                   method_offset - orig_method_len_offset);
      assert(writer.is_valid(), "invariant");
      orig_method_len_offset = stream->current_offset();
    }
  }
  return orig_methods_len;
}
static u2 add_method_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes) {
  assert(utf8_indexes != NULL, "invariant");
  add_method_info(writer,
                  utf8_indexes[UTF8_REQ_begin],
                  utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
                  utf8_indexes[UTF8_REQ_Code],
                  empty_void_method_code_attribute,
                  sizeof(empty_void_method_code_attribute));
  assert(writer.is_valid(), "invariant");
  add_method_info(writer,
                  utf8_indexes[UTF8_REQ_end],
                  utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
                  utf8_indexes[UTF8_REQ_Code],
                  empty_void_method_code_attribute,
                  sizeof(empty_void_method_code_attribute));
  assert(writer.is_valid(), "invariant");
  add_method_info(writer,
                  utf8_indexes[UTF8_REQ_commit],
                  utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
                  utf8_indexes[UTF8_REQ_Code],
                  empty_void_method_code_attribute,
                  sizeof(empty_void_method_code_attribute));
  assert(writer.is_valid(), "invariant");
  add_method_info(writer,
                  utf8_indexes[UTF8_REQ_isEnabled],
                  utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC],
                  utf8_indexes[UTF8_REQ_Code],
                  boolean_method_code_attribute,
                  sizeof(boolean_method_code_attribute));
  assert(writer.is_valid(), "invariant");
  add_method_info(writer,
                  utf8_indexes[UTF8_REQ_shouldCommit],
                  utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC],
                  utf8_indexes[UTF8_REQ_Code],
                  boolean_method_code_attribute,
                  sizeof(boolean_method_code_attribute));
  assert(writer.is_valid(), "invariant");
  return number_of_new_methods;
}
static void adjust_exception_table(JfrBigEndianWriter& writer, u2 bci_adjustment_offset, const Method* method, TRAPS) {
  const u2 ex_table_length = method != NULL ? (u2)method->exception_table_length() : 0;
  writer.write<u2>(ex_table_length); // Exception table length
  if (ex_table_length > 0) {
    assert(method != NULL, "invariant");
    const ExceptionTableElement* const ex_elements = method->exception_table_start();
    for (int i = 0; i < ex_table_length; ++i) {
      assert(ex_elements != NULL, "invariant");
      writer.write<u2>(ex_elements[i].start_pc + bci_adjustment_offset);
      writer.write<u2>(ex_elements[i].end_pc + bci_adjustment_offset);
      writer.write<u2>(ex_elements[i].handler_pc + bci_adjustment_offset);
      writer.write<u2>(ex_elements[i].catch_type_index); // no adjustment
    }
  }
}
enum StackMapFrameTypes {
  SAME_FRAME_BEGIN = 0,
  SAME_FRAME_END = 63,
  SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN = 64,
  SAME_LOCALS_1_STACK_ITEM_FRAME_END = 127,
  SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247,
  CHOP_FRAME_BEGIN = 248,
  CHOP_FRAME_END = 250,
  SAME_FRAME_EXTENDED = 251,
  APPEND_FRAME_BEGIN = 252,
  APPEND_FRAME_END = 254,
  FULL_FRAME = 255
};
static void adjust_stack_map(JfrBigEndianWriter& writer,
                             Array<u1>* stack_map,
                             const u2* utf8_indexes,
                             u2 bci_adjustment_offset,
                             TRAPS) {
  assert(stack_map != NULL, "invariant");
  assert(utf8_indexes != NULL, "invariant");
  writer.write<u2>(utf8_indexes[UTF8_OPT_StackMapTable]);
  const jlong stack_map_attrib_len_offset = writer.current_offset();
  writer.reserve(sizeof(u4));
  StackMapStream stream(stack_map);
  const u2 stack_map_entries = stream.get_u2(THREAD);
  writer.write<u2>(stack_map_entries); // new stack map entry added
  const u1 frame_type = stream.get_u1(THREAD);
  if (frame_type <= SAME_FRAME_END) {
    writer.write<u1>(SAME_FRAME_EXTENDED);
    writer.write<u2>(frame_type + bci_adjustment_offset);
  } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN &&
             frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) {
    writer.write<u1>(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED);
    writer.write<u2>((frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN) + bci_adjustment_offset);
  } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
      writer.write<u1>(frame_type);
      writer.write<u2>(stream.get_u2(THREAD) + bci_adjustment_offset);
  } else {
    assert(false, "stackMapFrame type is invalid");
  }
  while (!stream.at_end()) {
    writer.write<u1>(stream.get_u1(THREAD));
  }
  u4 stack_map_attrib_len = writer.current_offset() - stack_map_attrib_len_offset;
  stack_map_attrib_len -= sizeof(u4);
  writer.write_at_offset(stack_map_attrib_len, stack_map_attrib_len_offset);
}
static void adjust_line_number_table(JfrBigEndianWriter& writer,
                                     const u2* utf8_indexes,
                                     u4 bci_adjustement_offset,
                                     const Method* method,
                                     TRAPS) {
  assert(utf8_indexes != NULL, "invariant");
  assert(method != NULL, "invariant");
  assert(method->has_linenumber_table(), "invariant");
  writer.write(utf8_indexes[UTF8_OPT_LineNumberTable]);
  const jlong lnt_attributes_length_offset = writer.current_offset();
  writer.reserve(sizeof(u4));
  const jlong lnt_attributes_entries_offset = writer.current_offset();
  writer.reserve(sizeof(u2));
  u1* lnt = method->compressed_linenumber_table();
  CompressedLineNumberReadStream lnt_stream(lnt);
  u2 line_number_table_entries = 0;
  while (lnt_stream.read_pair()) {
    ++line_number_table_entries;
    const u2 bci = (u2)lnt_stream.bci();
    writer.write<u2>(bci + (u2)bci_adjustement_offset);
    writer.write<u2>((u2)lnt_stream.line());
  }
  writer.write_at_offset(line_number_table_entries, lnt_attributes_entries_offset);
  u4 lnt_table_attributes_len = writer.current_offset() - lnt_attributes_length_offset;
  lnt_table_attributes_len -= sizeof(u4);
  writer.write_at_offset(lnt_table_attributes_len, lnt_attributes_length_offset);
}
static u2 adjust_local_variable_table(JfrBigEndianWriter& writer,
                                     const u2* utf8_indexes,
                                     u2 bci_adjustment_offset,
                                     const Method* method,
                                     TRAPS) {
 assert(utf8_indexes != NULL, "invariant");
 assert(method != NULL, "invariant");
 assert(method->has_localvariable_table(), "invariant");
 writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTable]);
 const jlong lvt_attributes_length_offset = writer.current_offset();
 writer.reserve(sizeof(u4));
 const int lvt_len = method->localvariable_table_length();
 writer.write<u2>((u2)lvt_len);
 const LocalVariableTableElement* table = method->localvariable_table_start();
 assert(table != NULL, "invariant");
 u2 num_lvtt_entries = 0;
 for (int i = 0; i < lvt_len; ++i) {
   writer.write<u2>(table[i].start_bci + bci_adjustment_offset);
   writer.write<u2>(table[i].length);
   writer.write<u2>(table[i].name_cp_index);
   writer.write<u2>(table[i].descriptor_cp_index);
   writer.write<u2>(table[i].slot);
   if (table[i].signature_cp_index > 0) {
     ++num_lvtt_entries;
   }
 }
 u4 lvt_table_attributes_len = writer.current_offset() - lvt_attributes_length_offset;
 lvt_table_attributes_len -= sizeof(u4);
 writer.write_at_offset(lvt_table_attributes_len, lvt_attributes_length_offset);
 return num_lvtt_entries;
}
static void adjust_local_variable_type_table(JfrBigEndianWriter& writer,
                                           const u2* utf8_indexes,
                                           u2 bci_adjustment_offset,
                                           u2 num_lvtt_entries,
                                           const Method* method,
                                           TRAPS) {
 assert(num_lvtt_entries > 0, "invariant");
 writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTypeTable]);
 const jlong lvtt_attributes_length_offset = writer.current_offset();
 writer.reserve(sizeof(u4));
 writer.write<u2>(num_lvtt_entries);
 const LocalVariableTableElement* table = method->localvariable_table_start();
 assert(table != NULL, "invariant");
 const int lvt_len = method->localvariable_table_length();
 for (int i = 0; i < lvt_len; ++i) {
   if (table[i].signature_cp_index > 0) {
     writer.write<u2>(table[i].start_bci + bci_adjustment_offset);
     writer.write<u2>(table[i].length);
     writer.write<u2>(table[i].name_cp_index);
     writer.write<u2>(table[i].signature_cp_index);
     writer.write<u2>(table[i].slot);
   }
 }
 u4 lvtt_table_attributes_len = writer.current_offset() - lvtt_attributes_length_offset;
 lvtt_table_attributes_len -= sizeof(u4);
 writer.write_at_offset(lvtt_table_attributes_len, lvtt_attributes_length_offset);
}
static void adjust_code_attributes(JfrBigEndianWriter& writer,
                                  const u2* utf8_indexes,
                                  u2 bci_adjustment_offset,
                                  const Method* clinit_method,
                                  TRAPS) {
 assert(utf8_indexes != NULL, "invariant");
 const jlong code_attributes_offset = writer.current_offset();
 writer.reserve(sizeof(u2));
 u2 number_of_code_attributes = 0;
 if (clinit_method != NULL) {
   Array<u1>* stack_map = clinit_method->stackmap_data();
   if (stack_map != NULL) {
     ++number_of_code_attributes;
     adjust_stack_map(writer, stack_map, utf8_indexes, bci_adjustment_offset, THREAD);
     assert(writer.is_valid(), "invariant");
   }
   if (clinit_method != NULL && clinit_method->has_linenumber_table()) {
     ++number_of_code_attributes;
     adjust_line_number_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD);
     assert(writer.is_valid(), "invariant");
   }
   if (clinit_method != NULL && clinit_method->has_localvariable_table()) {
     ++number_of_code_attributes;
     const u2 num_of_lvtt_entries = adjust_local_variable_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD);
     assert(writer.is_valid(), "invariant");
     if (num_of_lvtt_entries > 0) {
       ++number_of_code_attributes;
       adjust_local_variable_type_table(writer, utf8_indexes, bci_adjustment_offset, num_of_lvtt_entries, clinit_method, THREAD);
       assert(writer.is_valid(), "invariant");
     }
   }
 }
 writer.write_at_offset(number_of_code_attributes, code_attributes_offset);
}
static jlong insert_clinit_method(const InstanceKlass* ik,
                                 ClassFileParser& parser,
                                 JfrBigEndianWriter& writer,
                                 u2 orig_constant_pool_len,
                                 const u2* utf8_indexes,
                                 const u2 register_method_ref_index,
                                 const Method* clinit_method,
                                 TRAPS) {
 assert(utf8_indexes != NULL, "invariant");
 static const u2 injected_code_length = 8;
 const u2 name_index = utf8_indexes[UTF8_REQ_clinit];
 const u2 desc_index = utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC];
 const u2 max_stack = MAX2(clinit_method != NULL ? clinit_method->verifier_max_stack() : 1, 1);
 const u2 max_locals = MAX2(clinit_method != NULL ? clinit_method->max_locals() : 0, 0);
 const u2 orig_bytecodes_length = clinit_method != NULL ? (u2)clinit_method->code_size() : 0;
 const address orig_bytecodes = clinit_method != NULL ? clinit_method->code_base() : NULL;
 const u2 new_code_length = injected_code_length + orig_bytecodes_length;
 DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
 writer.write<u2>(JVM_ACC_STATIC); // flags
 writer.write<u2>(name_index);
 writer.write<u2>(desc_index);
 writer.write<u2>((u2)0x1); // attributes_count // "Code"
 assert(writer.is_valid(), "invariant");
 DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
 writer.write<u2>(utf8_indexes[UTF8_REQ_Code]); // "Code"
 const jlong code_attribute_length_offset = writer.current_offset();
 writer.reserve(sizeof(u4));
 writer.write<u2>(max_stack); // max stack
 writer.write<u2>(max_locals); // max locals
 writer.write<u4>((u4)new_code_length); // code length
 writer.write<u1>((u1)Bytecodes::_ldc_w);
 writer.write<u2>((u2)parser.this_class_index()); // load constant "this class"
 writer.write<u1>((u1)Bytecodes::_invokestatic);
 writer.write<u2>(register_method_ref_index);
 if (clinit_method == NULL) {
   writer.write<u1>((u1)Bytecodes::_nop);
   writer.write<u1>((u1)Bytecodes::_return);
 } else {
   writer.write<u1>((u1)Bytecodes::_nop);
   writer.write<u1>((u1)Bytecodes::_nop);
   writer.bytes(orig_bytecodes, orig_bytecodes_length);
 }
 assert(writer.is_valid(), "invariant");
 adjust_exception_table(writer, injected_code_length, clinit_method, THREAD);
 assert(writer.is_valid(), "invariant");
 adjust_code_attributes(writer, utf8_indexes, injected_code_length, clinit_method, THREAD);
 assert(writer.is_valid(), "invariant");
 u4 code_attribute_len = writer.current_offset() - code_attribute_length_offset;
 code_attribute_len -= sizeof(u4);
 writer.write_at_offset(code_attribute_len, code_attribute_length_offset);
 return writer.current_offset();
}
static ClassFileStream* create_new_bytes_for_event_klass(const InstanceKlass* ik, const ClassFileParser& parser, TRAPS) {
 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
 static const u2 public_final_flag_mask = JVM_ACC_PUBLIC | JVM_ACC_FINAL;
 ClassFileStream* const orig_stream = parser.clone_stream();
 const int orig_stream_length = orig_stream->length();
 u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, orig_stream_length);
 if (new_buffer == NULL) {
   return NULL;
 }
 assert(new_buffer != NULL, "invariant");
 memcpy(new_buffer, orig_stream->buffer(), orig_stream_length);
 const u2 orig_cp_len = position_stream_after_cp(orig_stream);
 assert(orig_cp_len > 0, "invariant");
 assert(orig_stream->current_offset() > 0, "invariant");
 orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index
 const u2 iface_len = orig_stream->get_u2_fast();
 orig_stream->skip_u2_fast(iface_len);
 const u2 orig_fields_len = orig_stream->get_u2_fast();
 for (u2 i = 0; i < orig_fields_len; ++i) {
   orig_stream->skip_u2_fast(3);
   const u2 attrib_info_len = orig_stream->get_u2_fast();
   for (u2 j = 0; j < attrib_info_len; ++j) {
     orig_stream->skip_u2_fast(1);
     const u4 attrib_len = orig_stream->get_u4_fast();
     orig_stream->skip_u1_fast(attrib_len);
   }
 }
 const u2 orig_methods_len = orig_stream->get_u2_fast();
 for (u2 i = 0; i < orig_methods_len; ++i) {
   const u4 access_flag_offset = orig_stream->current_offset();
   const u2 flags = orig_stream->get_u2_fast();
   if (public_final_flag_mask == flags) {
     JfrBigEndianWriter accessflagsrewriter(new_buffer + access_flag_offset, sizeof(u2));
     accessflagsrewriter.write<u2>(JVM_ACC_PUBLIC);
     assert(accessflagsrewriter.is_valid(), "invariant");
   }
   orig_stream->skip_u2_fast(2);
   const u2 attributes_count = orig_stream->get_u2_fast();
   for (u2 j = 0; j < attributes_count; ++j) {
     orig_stream->skip_u2_fast(1);
     const u4 attrib_len = orig_stream->get_u4_fast();
     orig_stream->skip_u1_fast(attrib_len);
   }
 }
 return new ClassFileStream(new_buffer, orig_stream_length, NULL);
}
static u2 find_or_add_utf8_info(JfrBigEndianWriter& writer,
                               const InstanceKlass* ik,
                               const char* const utf8_constant,
                               u2 orig_cp_len,
                               u2& added_cp_entries,
                               TRAPS) {
 assert(utf8_constant != NULL, "invariant");
 TempNewSymbol utf8_sym = SymbolTable::new_symbol(utf8_constant, THREAD);
 const int utf8_orig_idx = utf8_info_index(ik, utf8_sym, THREAD);
 if (utf8_orig_idx != invalid_cp_index) {
   return utf8_orig_idx;
 }
 assert(invalid_cp_index == utf8_orig_idx, "invariant");
 return add_utf8_info(writer, utf8_constant, orig_cp_len, added_cp_entries);
}
static u2 resolve_utf8_indexes(JfrBigEndianWriter& writer,
                              const InstanceKlass* ik,
                              u2* const utf8_indexes,
                              u2 orig_cp_len,
                              const Method* clinit_method,
                              TRAPS) {
 assert(utf8_indexes != NULL, "invariant");
 u2 added_cp_entries = 0;
 for (u2 index = 0; index < NOF_UTF8_REQ_SYMBOLS; ++index) {
   utf8_indexes[index] = find_or_add_utf8_info(writer,
                                               ik,
                                               utf8_constants[index],
                                               orig_cp_len,
                                               added_cp_entries,
                                               THREAD);
 }
 if (clinit_method != NULL && clinit_method->has_stackmap_table()) {
   utf8_indexes[UTF8_OPT_StackMapTable] =
     find_or_add_utf8_info(writer,
                           ik,
                           utf8_constants[UTF8_OPT_StackMapTable],
                           orig_cp_len,
                           added_cp_entries,
                           THREAD);
 } else {
   utf8_indexes[UTF8_OPT_StackMapTable] = invalid_cp_index;
 }
 if (clinit_method != NULL && clinit_method->has_linenumber_table()) {
   utf8_indexes[UTF8_OPT_LineNumberTable] =
     find_or_add_utf8_info(writer,
                           ik,
                           utf8_constants[UTF8_OPT_LineNumberTable],
                           orig_cp_len,
                           added_cp_entries,
                           THREAD);
 } else {
   utf8_indexes[UTF8_OPT_LineNumberTable] = invalid_cp_index;
 }
 if (clinit_method != NULL && clinit_method->has_localvariable_table()) {
   utf8_indexes[UTF8_OPT_LocalVariableTable] =
     find_or_add_utf8_info(writer,
                           ik,
                           utf8_constants[UTF8_OPT_LocalVariableTable],
                           orig_cp_len,
                           added_cp_entries,
                           THREAD);
   utf8_indexes[UTF8_OPT_LocalVariableTypeTable] =
     find_or_add_utf8_info(writer,
                           ik,
                           utf8_constants[UTF8_OPT_LocalVariableTypeTable],
                           orig_cp_len,
                           added_cp_entries,
                           THREAD);
 } else {
   utf8_indexes[UTF8_OPT_LocalVariableTable] = invalid_cp_index;
   utf8_indexes[UTF8_OPT_LocalVariableTypeTable] = invalid_cp_index;
 }
 return added_cp_entries;
}
static u1* new_bytes_for_lazy_instrumentation(InstanceKlass* ik,
                                             ClassFileParser& parser,
                                             jint& size_of_new_bytes,
                                             TRAPS) {
 assert(ik != NULL, "invariant");
 const Method* clinit_method = ik->class_initializer();
 const bool register_klass = should_register_klass(ik);
 ClassFileStream* const orig_stream = parser.clone_stream();
 const int orig_stream_size = orig_stream->length();
 assert(orig_stream->current_offset() == 0, "invariant");
 const u2 orig_cp_len = position_stream_after_cp(orig_stream);
 assert(orig_cp_len > 0, "invariant");
 assert(orig_stream->current_offset() > 0, "invariant");
 const jint new_buffer_size = extra_stream_bytes + orig_stream_size;
 u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, new_buffer_size);
 if (new_buffer == NULL) {
   if (true) tty->print_cr ("Thread local allocation (native) for " SIZE_FORMAT
     " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)new_buffer_size);
   return NULL;
 }
 assert(new_buffer != NULL, "invariant");
 JfrBigEndianWriter writer(new_buffer, new_buffer_size);
 assert(writer.current_offset() == 0, "invariant");
 const u4 orig_access_flag_offset = orig_stream->current_offset();
 writer.bytes(orig_stream->buffer(), orig_access_flag_offset);
 assert(writer.is_valid(), "invariant");
 assert(writer.current_offset() == (intptr_t)orig_access_flag_offset, "invariant"); // same positions
 u2 utf8_indexes[NOF_UTF8_SYMBOLS];
 u2 number_of_new_constants = resolve_utf8_indexes(writer, ik, utf8_indexes, orig_cp_len, clinit_method, THREAD);
 const u2 flr_register_method_ref_index =
   register_klass ?
     add_flr_register_method_constants(writer,
                                       utf8_indexes,
                                       orig_cp_len,
                                       number_of_new_constants,
                                       THREAD) :  invalid_cp_index;
 writer.write_at_offset<u2>(orig_cp_len + number_of_new_constants, 8);
 assert(writer.is_valid(), "invariant");
 orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index
 const u2 iface_len = orig_stream->get_u2_fast(); // interfaces
 orig_stream->skip_u2_fast(iface_len);
 const u4 orig_fields_len_offset = orig_stream->current_offset();
 writer.bytes(orig_stream->buffer() + orig_access_flag_offset,
              orig_fields_len_offset - orig_access_flag_offset);
 assert(writer.is_valid(), "invariant");
 const jlong new_fields_len_offset = writer.current_offset();
 const u2 orig_fields_len = position_stream_after_fields(orig_stream);
 u4 orig_method_len_offset = orig_stream->current_offset();
 writer.bytes(orig_stream->buffer() + orig_fields_len_offset, orig_method_len_offset - orig_fields_len_offset);
 assert(writer.is_valid(), "invariant");
 const u2 number_of_new_fields = add_field_infos(writer, utf8_indexes);
 assert(writer.is_valid(), "invariant");
 const jlong new_method_len_offset = writer.current_offset();
 writer.write_at_offset<u2>(orig_fields_len + number_of_new_fields, new_fields_len_offset);
 assert(writer.is_valid(), "invariant");
 const u2 orig_methods_len = position_stream_after_methods(writer,
                                                           orig_stream,
                                                           utf8_indexes,
                                                           register_klass,
                                                           clinit_method,
                                                           orig_method_len_offset);
 const u4 orig_attributes_count_offset = orig_stream->current_offset();
 writer.bytes(orig_stream->buffer() + orig_method_len_offset, orig_attributes_count_offset - orig_method_len_offset);
 assert(writer.is_valid(), "invariant");
 u2 number_of_new_methods = add_method_infos(writer, utf8_indexes);
 if (register_klass) {
   insert_clinit_method(ik, parser, writer, orig_cp_len, utf8_indexes, flr_register_method_ref_index, clinit_method, THREAD);
 }
 number_of_new_methods += clinit_method != NULL ? 0 : register_klass ? 1 : 0;
 writer.write_at_offset<u2>(orig_methods_len + number_of_new_methods, new_method_len_offset);
 assert(writer.is_valid(), "invariant");
 writer.bytes(orig_stream->buffer() + orig_attributes_count_offset, orig_stream_size - orig_attributes_count_offset);
 assert(writer.is_valid(), "invariant");
 assert(writer.current_offset() > orig_stream->length(), "invariant");
 size_of_new_bytes = (jint)writer.current_offset();
 return new_buffer;
}
static void log_pending_exception(oop throwable) {
 assert(throwable != NULL, "invariant");
 oop msg = java_lang_Throwable::message(throwable);
 if (msg != NULL) {
   char* text = java_lang_String::as_utf8_string(msg);
   if (text != NULL) {
     if (true) tty->print_cr ("%s", text);
   }
 }
}
static bool should_force_instrumentation() {
 return !JfrOptionSet::allow_event_retransforms() || JfrEventClassTransformer::is_force_instrumentation();
}
static ClassFileStream* create_new_bytes_for_subklass(InstanceKlass* ik, ClassFileParser& parser, Thread* t) {
 assert(JdkJfrEvent::is_a(ik), "invariant");
 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t));
 jint size_of_new_bytes = 0;
 u1* new_bytes = new_bytes_for_lazy_instrumentation(ik, parser, size_of_new_bytes, t);
 if (new_bytes == NULL) {
   return NULL;
 }
 assert(new_bytes != NULL, "invariant");
 assert(size_of_new_bytes > 0, "invariant");
 bool force_instrumentation = should_force_instrumentation();
 if (Jfr::is_recording() || force_instrumentation) {
   jint size_instrumented_data = 0;
   unsigned char* instrumented_data = NULL;
   const jclass super = (jclass)JNIHandles::make_local(ik->super()->java_mirror());
   JfrUpcalls::new_bytes_eager_instrumentation(TRACE_ID(ik),
                                               force_instrumentation,
                                               super,
                                               size_of_new_bytes,
                                               new_bytes,
                                               &size_instrumented_data,
                                               &instrumented_data,
                                               t);
   if (t->has_pending_exception()) {
     log_pending_exception(t->pending_exception());
     t->clear_pending_exception();
     return NULL;
   }
   assert(instrumented_data != NULL, "invariant");
   assert(size_instrumented_data > 0, "invariant");
   return new ClassFileStream(instrumented_data, size_instrumented_data, NULL);
 }
 return new ClassFileStream(new_bytes, size_of_new_bytes, NULL);
}
static bool cache_bytes(InstanceKlass* ik, ClassFileStream* new_stream, InstanceKlass* new_ik, TRAPS) {
 assert(ik != NULL, "invariant");
 assert(new_ik != NULL, "invariant");
 assert(new_ik->name() != NULL, "invariant");
 assert(new_stream != NULL, "invariant");
 assert(!HAS_PENDING_EXCEPTION, "invariant");
 static const bool can_retransform = JfrOptionSet::allow_retransforms();
 if (!can_retransform) {
   return true;
 }
 const jint stream_len = new_stream->length();
 JvmtiCachedClassFileData* p =
   (JvmtiCachedClassFileData*)NEW_C_HEAP_ARRAY_RETURN_NULL(u1, offset_of(JvmtiCachedClassFileData, data) + stream_len, mtInternal);
 if (p == NULL) {
   if (true) tty->print_cr("Allocation using C_HEAP_ARRAY for " SIZE_FORMAT
     " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)offset_of(JvmtiCachedClassFileData, data) + stream_len);
   return false;
 }
 p->length = stream_len;
 memcpy(p->data, new_stream->buffer(), stream_len);
 new_ik->set_cached_class_file(p);
 JvmtiCachedClassFileData* const cached_class_data = ik->get_cached_class_file();
 if (cached_class_data != NULL) {
   os::free(cached_class_data);
   ik->set_cached_class_file(NULL);
 }
 return true;
}
static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPS) {
 assert(stream != NULL, "invariant");
 ResourceMark rm(THREAD);
TempNewSymbol parsed_name = NULL;
 ClassLoaderData* const cld = ik->class_loader_data();
 Handle pd(THREAD, ik->protection_domain());
 Symbol* const class_name = ik->name();
 const char* const klass_name = class_name != NULL ? class_name->as_C_string() : "";
 InstanceKlass* const new_ik = ClassFileParser(stream).parseClassFile(
                            class_name,
                            cld,
                            pd,
                            NULL, // host klass
                            NULL, // cp_patches
                            parsed_name,
                            true, // need_verify
                            THREAD)();
 if (HAS_PENDING_EXCEPTION) {
   log_pending_exception(PENDING_EXCEPTION);
   CLEAR_PENDING_EXCEPTION;
   return NULL;
 }
 assert(new_ik != NULL, "invariant");
 assert(new_ik->name() != NULL, "invariant");
 assert(strncmp(ik->name()->as_C_string(), new_ik->name()->as_C_string(), strlen(ik->name()->as_C_string())) == 0, "invariant");
 return cache_bytes(ik, stream, new_ik, THREAD) ? new_ik : NULL;
}
static void rewrite_klass_pointer(InstanceKlass*& ik, InstanceKlass* new_ik, ClassFileParser& parser, TRAPS) {
 assert(ik != NULL, "invariant");
 assert(new_ik != NULL, "invariant");
 assert(new_ik->name() != NULL, "invariant");
 assert(JdkJfrEvent::is(new_ik) || JdkJfrEvent::is_subklass(new_ik), "invariant");
 assert(!HAS_PENDING_EXCEPTION, "invariant");
 parser.set_klass_to_deallocate(ik);
 ik = new_ik;
}
static void copy_method_trace_flags(const InstanceKlass* the_original_klass, const InstanceKlass* the_scratch_klass) {
  assert(the_original_klass != NULL, "invariant");
  assert(the_scratch_klass != NULL, "invariant");
  assert(the_original_klass->name() == the_scratch_klass->name(), "invariant");
  const Array<Method*>* old_methods = the_original_klass->methods();
  const Array<Method*>* new_methods = the_scratch_klass->methods();
  const bool equal_array_length = old_methods->length() == new_methods->length();
  for (int i = 0; i < old_methods->length(); ++i) {
    const Method* const old_method = old_methods->at(i);
    Method* const new_method = equal_array_length ? new_methods->at(i) :
      the_scratch_klass->find_method(old_method->name(), old_method->signature());
    assert(new_method != NULL, "invariant");
    assert(new_method->name() == old_method->name(), "invariant");
    assert(new_method->signature() == old_method->signature(), "invariant");
    assert(new_method->trace_flags() == old_method->trace_flags(), "invariant");
  }
}
static bool is_retransforming(const InstanceKlass* ik, TRAPS) {
  assert(ik != NULL, "invariant");
  assert(JdkJfrEvent::is_a(ik), "invariant");
  Symbol* const name = ik->name();
  assert(name != NULL, "invariant");
  Handle class_loader(THREAD, ik->class_loader());
  Handle protection_domain(THREAD, ik->protection_domain());
  const InstanceKlass* prev_ik = (const InstanceKlass*)SystemDictionary::find(name, class_loader, protection_domain, THREAD);
  if (prev_ik == NULL) {
    return false;
  }
  assert(prev_ik != NULL, "invariant");
  assert(JdkJfrEvent::is_a(prev_ik), "invariant");
  copy_method_trace_flags(prev_ik, ik);
  return true;
}
void JfrEventClassTransformer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS) {
 assert(ik != NULL, "invariant");
 if (JdkJfrEvent::is(ik)) {
   ResourceMark rm(THREAD);
   HandleMark hm(THREAD);
   ClassFileStream* new_stream = create_new_bytes_for_event_klass(ik, parser, THREAD);
   if (new_stream == NULL) {
     if (true) tty->print_cr("JfrClassAdapter: unable to create ClassFileStream");
     return;
   }
   assert(new_stream != NULL, "invariant");
   InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD);
   if (new_ik == NULL) {
     if (true) tty->print_cr("JfrClassAdapter: unable to create InstanceKlass");
     return;
   }
   assert(new_ik != NULL, "invariant");
   assert(!JdkJfrEvent::is(new_ik), "invariant");
   JdkJfrEvent::tag_as(new_ik);
   assert(JdkJfrEvent::is(new_ik), "invariant");
   rewrite_klass_pointer(ik, new_ik, parser, THREAD);
   return;
 }
 assert(JdkJfrEvent::is_subklass(ik), "invariant");
 if (is_retransforming(ik, THREAD)) {
   return;
 }
 if (ik->is_abstract()) {
   return;
 }
 ResourceMark rm(THREAD);
 HandleMark hm(THREAD);
 ClassFileStream* const new_stream = create_new_bytes_for_subklass(ik, parser, THREAD);
 if (NULL == new_stream) {
   if (true) tty->print_cr("JfrClassAdapter: unable to create ClassFileStream");
   return;
 }
 assert(new_stream != NULL, "invariant");
 InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD);
 if (new_ik == NULL) {
   if (true) tty->print_cr("JfrClassAdapter: unable to create InstanceKlass");
   return;
 }
 assert(new_ik != NULL, "invariant");
 assert(JdkJfrEvent::is_subklass(new_ik), "invariant");
 traceid id = ik->trace_id();
 ik->set_trace_id(0);
 new_ik->set_trace_id(id);
 rewrite_klass_pointer(ik, new_ik, parser, THREAD);
}
static bool _force_instrumentation = false;
void JfrEventClassTransformer::set_force_instrumentation(bool force_instrumentation) {
  _force_instrumentation = force_instrumentation;
}
bool JfrEventClassTransformer::is_force_instrumentation() {
  return _force_instrumentation;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/instrumentation/jfrEventClassTransformer.hpp
#ifndef SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP
#define SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP
#include "memory/allocation.hpp"
#include "utilities/exceptions.hpp"
class ClassFileParser;
class InstanceKlass;
class JfrEventClassTransformer : AllStatic {
 public:
  static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS);
  static void set_force_instrumentation(bool force_instrumentation);
  static bool is_force_instrumentation();
};
#endif // SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/instrumentation/jfrJvmtiAgent.cpp
#include "precompiled.hpp"
#include "jvm.h"
#include "jfr/instrumentation/jfrJvmtiAgent.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrUpcalls.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/support/jfrEventClass.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
static const size_t ERROR_MSG_BUFFER_SIZE = 256;
static JfrJvmtiAgent* agent = NULL;
static jvmtiEnv* jfr_jvmti_env = NULL;
static void check_jvmti_error(jvmtiEnv* jvmti, jvmtiError errnum, const char* str) {
  if (errnum != JVMTI_ERROR_NONE) {
    char* errnum_str = NULL;
    jvmti->GetErrorName(errnum, &errnum_str);
    if (true) tty->print_cr("ERROR: JfrJvmtiAgent: " INT32_FORMAT " (%s): %s\n",
                           errnum,
                           NULL == errnum_str ? "Unknown" : errnum_str,
                           NULL == str ? "" : str);
  }
}
static jvmtiError set_event_notification_mode(jvmtiEventMode mode,
                                              jvmtiEvent event,
                                              jthread event_thread,
                                              ...) {
  if (jfr_jvmti_env == NULL) {
    return JVMTI_ERROR_NONE;
  }
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventNotificationMode(mode, event, event_thread);
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventNotificationMode");
  return jvmti_ret_code;
}
static jvmtiError update_class_file_load_hook_event(jvmtiEventMode mode) {
  return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
}
static JavaThread* current_java_thread() {
  Thread* this_thread = Thread::current();
  assert(this_thread != NULL && this_thread->is_Java_thread(), "invariant");
  return static_cast<JavaThread*>(this_thread);
}
extern "C" void JNICALL jfr_on_class_file_load_hook(jvmtiEnv *jvmti_env,
                                                    JNIEnv* jni_env,
                                                    jclass class_being_redefined,
                                                    jobject loader,
                                                    const char* name,
                                                    jobject protection_domain,
                                                    jint class_data_len,
                                                    const unsigned char* class_data,
                                                    jint* new_class_data_len,
                                                    unsigned char** new_class_data) {
  if (class_being_redefined == NULL) {
    return;
  }
  JavaThread* jt = JavaThread::thread_from_jni_environment(jni_env);
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));;
  ThreadInVMfromNative tvmfn(jt);
  JfrUpcalls::on_retransform(JfrTraceId::get(class_being_redefined),
                             class_being_redefined,
                             class_data_len,
                             class_data,
                             new_class_data_len,
                             new_class_data,
                             jt);
}
static jclass* create_classes_array(jint classes_count, TRAPS) {
  assert(classes_count > 0, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
  ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
  jclass* const classes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jclass, classes_count);
  if (NULL == classes) {
    char error_buffer[ERROR_MSG_BUFFER_SIZE];
    jio_snprintf(error_buffer, ERROR_MSG_BUFFER_SIZE,
      "Thread local allocation (native) of " SIZE_FORMAT " bytes failed "
      "in retransform classes", sizeof(jclass) * classes_count);
    if (true) tty->print_cr("%s", error_buffer);
    JfrJavaSupport::throw_out_of_memory_error(error_buffer, CHECK_NULL);
  }
  return classes;
}
static void log_and_throw(TRAPS) {
  if (!HAS_PENDING_EXCEPTION) {
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
    if (true) tty->print_cr("JfrJvmtiAgent::retransformClasses failed");
    JfrJavaSupport::throw_class_format_error("JfrJvmtiAgent::retransformClasses failed", THREAD);
  }
}
static void check_exception_and_log(JNIEnv* env, TRAPS) {
  assert(env != NULL, "invariant");
  if (env->ExceptionOccurred()) {
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
    ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
    if (true) tty->print_cr("GetObjectArrayElement threw an exception");
    return;
  }
}
void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) {
  assert(env != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
  if (classes_array == NULL) {
    return;
  }
  const jint classes_count = env->GetArrayLength(classes_array);
  if (classes_count <= 0) {
    return;
  }
  ResourceMark rm(THREAD);
  jclass* const classes = create_classes_array(classes_count, CHECK);
  assert(classes != NULL, "invariant");
  for (jint i = 0; i < classes_count; i++) {
    jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i);
    check_exception_and_log(env, THREAD);
    {
      ThreadInVMfromNative transition((JavaThread*)THREAD);
      if (JdkJfrEvent::is_a(clz)) {
        assert(JdkJfrEvent::is_subklass(clz), "invariant");
      } else {
        JdkJfrEvent::tag_as_host(clz);
      }
    }
    classes[i] = clz;
  }
  if (jfr_jvmti_env->RetransformClasses(classes_count, classes) != JVMTI_ERROR_NONE) {
    log_and_throw(THREAD);
  }
}
static jvmtiError register_callbacks(JavaThread* jt) {
  assert(jfr_jvmti_env != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
  jvmtiEventCallbacks callbacks;
  memset(&callbacks, 0, sizeof(callbacks));
  callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook;
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
  return jvmti_ret_code;
}
static jvmtiError register_capabilities(JavaThread* jt) {
  assert(jfr_jvmti_env != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
  jvmtiCapabilities capabilities;
  (void)memset(&capabilities, 0, sizeof(capabilities));
  capabilities.can_retransform_classes = 1;
  capabilities.can_retransform_any_class = 1;
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities);
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities");
  return jvmti_ret_code;
}
static jint create_jvmti_env(JavaThread* jt) {
  assert(jfr_jvmti_env == NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
  extern struct JavaVM_ main_vm;
  JavaVM* vm = &main_vm;
  return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION);
}
static jvmtiError unregister_callbacks(JavaThread* jt) {
  if (jfr_jvmti_env == NULL) {
    return JVMTI_ERROR_NONE;
  }
  jvmtiEventCallbacks callbacks;
  memset(&callbacks, 0, sizeof(callbacks));
  const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
  check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
  return jvmti_ret_code;
}
JfrJvmtiAgent::JfrJvmtiAgent() {}
JfrJvmtiAgent::~JfrJvmtiAgent() {
  JavaThread* jt = current_java_thread();
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
  ThreadToNativeFromVM transition(jt);
  update_class_file_load_hook_event(JVMTI_DISABLE);
  unregister_callbacks(jt);
  if (jfr_jvmti_env != NULL) {
    jfr_jvmti_env->DisposeEnvironment();
    jfr_jvmti_env = NULL;
  }
  agent = NULL;
}
static bool initialize() {
  JavaThread* const jt = current_java_thread();
  assert(jt != NULL, "invariant");
  assert(jt->thread_state() == _thread_in_vm, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
  ThreadToNativeFromVM transition(jt);
  if (create_jvmti_env(jt) != JNI_OK) {
    assert(jfr_jvmti_env == NULL, "invariant");
    return false;
  }
  assert(jfr_jvmti_env != NULL, "invariant");
  if (register_capabilities(jt) != JVMTI_ERROR_NONE) {
    return false;
  }
  if (register_callbacks(jt) != JVMTI_ERROR_NONE) {
    return false;
  }
  if (update_class_file_load_hook_event(JVMTI_ENABLE) != JVMTI_ERROR_NONE) {
    return false;
  }
  return true;
}
bool JfrJvmtiAgent::create() {
  assert(jfr_jvmti_env == NULL, "invariant");
  agent = new JfrJvmtiAgent();
  if (agent == NULL) {
    return false;
  }
  if (!initialize()) {
    delete agent;
    agent = NULL;
    return false;
  }
  return true;
}
void JfrJvmtiAgent::destroy() {
  if (agent != NULL) {
    delete agent;
    agent = NULL;
  }
}
C:\hotspot-69087d08d473\src\share\vm/jfr/instrumentation/jfrJvmtiAgent.hpp
#ifndef SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP
#define SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP
#include "jfr/utilities/jfrAllocation.hpp"
class JfrJvmtiAgent : public JfrCHeapObj {
  friend class JfrRecorder;
 private:
  JfrJvmtiAgent();
  ~JfrJvmtiAgent();
  static bool create();
  static void destroy();
 public:
  static void retransform_classes(JNIEnv* env, jobjectArray classes, TRAPS);
};
#endif // SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jfr.cpp
#include "precompiled.hpp"
#include "jfr/jfr.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/java.hpp"
bool Jfr::is_enabled() {
  return JfrRecorder::is_enabled();
}
bool Jfr::is_disabled() {
  return JfrRecorder::is_disabled();
}
bool Jfr::is_recording() {
  return JfrRecorder::is_recording();
}
void Jfr::on_vm_init() {
  if (!JfrRecorder::on_vm_init()) {
    vm_exit_during_initialization("Failure when starting JFR on_vm_init");
  }
}
void Jfr::on_vm_start() {
  if (!JfrRecorder::on_vm_start()) {
    vm_exit_during_initialization("Failure when starting JFR on_vm_start");
  }
}
void Jfr::on_unloading_classes() {
  if (JfrRecorder::is_created()) {
    JfrCheckpointManager::write_type_set_for_unloaded_classes();
  }
}
void Jfr::on_thread_start(Thread* t) {
  JfrThreadLocal::on_start(t);
}
void Jfr::on_thread_exit(Thread* t) {
  JfrThreadLocal::on_exit(t);
}
void Jfr::on_java_thread_dismantle(JavaThread* jt) {
  if (JfrRecorder::is_recording()) {
    JfrCheckpointManager::write_thread_checkpoint(jt);
  }
}
void Jfr::on_vm_shutdown(bool exception_handler) {
  JfrRecorder::set_is_shutting_down();
  if (JfrRecorder::is_recording()) {
    JfrEmergencyDump::on_vm_shutdown(exception_handler);
  }
}
void Jfr::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
  LeakProfiler::oops_do(is_alive, f);
}
void Jfr::weak_oops_do(OopClosure* f) {
  AlwaysTrueClosure always_true;
  LeakProfiler::oops_do(&always_true, f);
}
bool Jfr::on_flight_recorder_option(const JavaVMOption** option, char* delimiter) {
  return JfrOptionSet::parse_flight_recorder_option(option, delimiter);
}
bool Jfr::on_start_flight_recording_option(const JavaVMOption** option, char* delimiter) {
  return JfrOptionSet::parse_start_flight_recording_option(option, delimiter);
}
Thread* Jfr::sampler_thread() {
  return JfrThreadSampling::sampler_thread();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jfr.hpp
#ifndef SHARE_VM_JFR_JFR_HPP
#define SHARE_VM_JFR_JFR_HPP
#include "jni.h"
#include "memory/allocation.hpp"
class BoolObjectClosure;
class JavaThread;
class OopClosure;
class Thread;
extern "C" void JNICALL jfr_register_natives(JNIEnv*, jclass);
class Jfr : AllStatic {
 public:
  static bool is_enabled();
  static bool is_disabled();
  static bool is_recording();
  static void on_vm_init();
  static void on_vm_start();
  static void on_unloading_classes();
  static void on_thread_start(Thread* thread);
  static void on_thread_exit(Thread* thread);
  static void on_java_thread_dismantle(JavaThread* jt);
  static void on_vm_shutdown(bool exception_handler = false);
  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 weak_oops_do(OopClosure* f);
  static Thread* sampler_thread();
};
#endif // SHARE_VM_JFR_JFR_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jfrEvents.hpp
#ifndef SHARE_VM_JFR_JFREVENTS_HPP
#define SHARE_VM_JFR_JFREVENTS_HPP
#include "jfrfiles/jfrEventClasses.hpp"
#include "jfrfiles/jfrEventIds.hpp"
#endif // SHARE_VM_JFR_JFREVENTS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrGetAllEventClasses.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "jfr/jni/jfrGetAllEventClasses.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/support/jfrEventClass.hpp"
#include "oops/instanceKlass.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/stack.inline.hpp"
static jlong unloaded_event_classes = 0;
jlong JfrEventClasses::unloaded_event_classes_count() {
  return unloaded_event_classes;
}
void JfrEventClasses::increment_unloaded_event_class() {
  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
  ++unloaded_event_classes;
}
static jobject empty_java_util_arraylist = NULL;
static oop new_java_util_arraylist(TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, "java/util/ArrayList", "<init>", "()V", CHECK_NULL);
  JfrJavaSupport::new_object(&args, CHECK_NULL);
  return (oop)result.get_jobject();
}
static bool initialize(TRAPS) {
  static bool initialized = false;
  if (!initialized) {
    unloaded_event_classes = 0;
    assert(NULL == empty_java_util_arraylist, "invariant");
    const oop array_list = new_java_util_arraylist(CHECK_false);
    empty_java_util_arraylist = JfrJavaSupport::global_jni_handle(array_list, THREAD);
    initialized = empty_java_util_arraylist != NULL;
  }
  return initialized;
}
static bool is_whitelisted(const Klass* k) {
  assert(k != NULL, "invariant");
  return !(k->is_abstract() || k->should_be_initialized());
}
static void fill_klasses(GrowableArray<const void*>& event_subklasses, const Klass* event_klass, Thread* thread) {
  assert(event_subklasses.length() == 0, "invariant");
  assert(event_klass != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
  Stack<const Klass*, mtTracing> mark_stack;
  MutexLocker ml(Compile_lock, thread);
  mark_stack.push(event_klass->subklass());
  while (!mark_stack.is_empty()) {
    const Klass* const current = mark_stack.pop();
    assert(current != NULL, "null element in stack!");
    if (is_whitelisted(current)) {
      event_subklasses.append(current);
    }
    const Klass* next_klass = current->subklass();
    if (next_klass != NULL) {
      mark_stack.push(next_klass);
    }
    next_klass = current->next_sibling();
    if (next_klass != NULL) {
      mark_stack.push(next_klass);
    }
  }
  assert(mark_stack.is_empty(), "invariant");
}
 static void transform_klasses_to_local_jni_handles(GrowableArray<const void*>& event_subklasses, Thread* thread) {
  assert(event_subklasses.is_nonempty(), "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
  for (int i = 0; i < event_subklasses.length(); ++i) {
    const InstanceKlass* k = static_cast<const InstanceKlass*>(event_subklasses.at(i));
    assert(is_whitelisted(k), "invariant");
    event_subklasses.at_put(i, JfrJavaSupport::local_jni_handle(k->java_mirror(), thread));
  }
}
static const int initial_size_growable_array = 64;
jobject JfrEventClasses::get_all_event_classes(TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  initialize(THREAD);
  assert(empty_java_util_arraylist != NULL, "should have been setup already!");
  static const char jdk_jfr_event_name[] = "jdk/jfr/Event";
  unsigned int unused_hash = 0;
  Symbol* const event_klass_name = SymbolTable::lookup_only(jdk_jfr_event_name, sizeof jdk_jfr_event_name - 1, unused_hash);
  if (NULL == event_klass_name) {
    return empty_java_util_arraylist;
  }
  const Klass* const klass = SystemDictionary::resolve_or_null(event_klass_name, THREAD);
  assert(klass != NULL, "invariant");
  assert(JdkJfrEvent::is(klass), "invariant");
  if (klass->subklass() == NULL) {
    return empty_java_util_arraylist;
  }
  ResourceMark rm(THREAD);
  GrowableArray<const void*> event_subklasses(THREAD, initial_size_growable_array);
  fill_klasses(event_subklasses, klass, THREAD);
  if (event_subklasses.is_empty()) {
    return empty_java_util_arraylist;
  }
  transform_klasses_to_local_jni_handles(event_subklasses, THREAD);
  Handle h_array_list(THREAD, new_java_util_arraylist(THREAD));
  assert(h_array_list.not_null(), "invariant");
  static const char add_method_name[] = "add";
  static const char add_method_signature[] = "(Ljava/lang/Object;)Z";
  const Klass* const array_list_klass = JfrJavaSupport::klass(empty_java_util_arraylist);
  assert(array_list_klass != NULL, "invariant");
  const Symbol* const add_method_sym = SymbolTable::lookup(add_method_name, sizeof add_method_name - 1, THREAD);
  assert(add_method_sym != NULL, "invariant");
  const Symbol* const add_method_sig_sym = SymbolTable::lookup(add_method_signature, sizeof add_method_signature - 1, THREAD);
  assert(add_method_signature != NULL, "invariant");
  JavaValue result(T_BOOLEAN);
  for (int i = 0; i < event_subklasses.length(); ++i) {
    const jclass clazz = (const jclass)event_subklasses.at(i);
    assert(JdkJfrEvent::is_subklass(clazz), "invariant");
    JfrJavaArguments args(&result, array_list_klass, add_method_sym, add_method_sig_sym);
    args.set_receiver(h_array_list());
    args.push_jobject(clazz);
    JfrJavaSupport::call_virtual(&args, THREAD);
    if (HAS_PENDING_EXCEPTION || JNI_FALSE == result.get_jboolean()) {
      return empty_java_util_arraylist;
    }
  }
  return JfrJavaSupport::local_jni_handle(h_array_list(), THREAD);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrGetAllEventClasses.hpp
#ifndef SHARE_VM_JFR_JNI_JFRGETALLEVENTCLASSES_HPP
#define SHARE_VM_JFR_JNI_JFRGETALLEVENTCLASSES_HPP
#include "jni.h"
#include "memory/allocation.hpp"
#include "utilities/exceptions.hpp"
class JfrEventClasses : AllStatic {
 public:
  static void increment_unloaded_event_class();
  static jlong unloaded_event_classes_count();
  static jobject get_all_event_classes(TRAPS);
};
#endif // SHARE_VM_JFR_JNI_JFRGETALLEVENTCLASSES_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJavaCall.cpp
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "jfr/jni/jfrJavaCall.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef ASSERT
static bool is_large_value(const JavaValue& value) {
  return value.get_type() == T_LONG || value.get_type() == T_DOUBLE;
}
#endif // ASSERT
static Symbol* resolve(const char* str, TRAPS) {
  assert(str != NULL, "invariant");
  return SymbolTable::lookup(str, (int)strlen(str), THREAD);
}
static Klass* resolve(Symbol* k_sym, TRAPS) {
  assert(k_sym != NULL, "invariant");
  return SystemDictionary::resolve_or_fail(k_sym, true, THREAD);
}
JfrJavaArguments::Parameters::Parameters() : _storage_index(0), _java_stack_slots(0) {
  JavaValue value(T_VOID);
  push(value);
}
void JfrJavaArguments::Parameters::push(const JavaValue& value) {
  assert(_storage != NULL, "invariant");
  assert(!is_large_value(value), "invariant");
  assert(_storage_index < SIZE, "invariant");
  _storage[_storage_index++] = value;
  _java_stack_slots++;
}
void JfrJavaArguments::Parameters::push_large(const JavaValue& value) {
  assert(_storage != NULL, "invariant");
  assert(is_large_value(value), "invariant");
  assert(_storage_index < SIZE, "invariant");
  _storage[_storage_index++] = value;
  _java_stack_slots += 2;
}
void JfrJavaArguments::Parameters::set_receiver(const oop receiver) {
  assert(_storage != NULL, "invariant");
  assert(receiver != NULL, "invariant");
  JavaValue value(T_OBJECT);
  value.set_jobject((jobject)receiver);
  _storage[0] = value;
}
void JfrJavaArguments::Parameters::set_receiver(Handle receiver) {
  set_receiver(receiver());
}
oop JfrJavaArguments::Parameters::receiver() const {
  assert(has_receiver(), "invariant");
  assert(_storage[0].get_type() == T_OBJECT, "invariant");
  return (oop)_storage[0].get_jobject();
}
bool JfrJavaArguments::Parameters::has_receiver() const {
  assert(_storage != NULL, "invariant");
  assert(_storage_index >= 1, "invariant");
  assert(_java_stack_slots >= 1, "invariant");
  return _storage[0].get_type() == T_OBJECT;
}
void JfrJavaArguments::Parameters::push_oop(const oop obj) {
  JavaValue value(T_OBJECT);
  value.set_jobject((jobject)obj);
  push(value);
}
void JfrJavaArguments::Parameters::push_oop(Handle h_obj) {
  push_oop(h_obj());
}
void JfrJavaArguments::Parameters::push_jobject(jobject h) {
  JavaValue value(T_ADDRESS);
  value.set_jobject(h);
  push(value);
}
void JfrJavaArguments::Parameters::push_jint(jint i) {
  JavaValue value(T_INT);
  value.set_jint(i);
  push(value);
}
void JfrJavaArguments::Parameters::push_jfloat(jfloat f) {
  JavaValue value(T_FLOAT);
  value.set_jfloat(f);
  push(value);
}
void JfrJavaArguments::Parameters::push_jdouble(jdouble d) {
  JavaValue value(T_DOUBLE);
  value.set_jdouble(d);
  push_large(value);
}
void JfrJavaArguments::Parameters::push_jlong(jlong l) {
  JavaValue value(T_LONG);
  value.set_jlong(l);
  push_large(value);
}
inline int JfrJavaArguments::Parameters::length() const {
  assert(_storage_index >= 1, "invariant");
  return _storage_index;
}
inline int JfrJavaArguments::Parameters::java_stack_slots() const {
  return _java_stack_slots;
}
const JavaValue& JfrJavaArguments::Parameters::values(int idx) const {
  assert(idx >= 0, "invariant");
  assert(idx < SIZE, "invariant");
  return _storage[idx];
}
void JfrJavaArguments::Parameters::copy(JavaCallArguments& args, TRAPS) const {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  if (has_receiver()) {
    args.set_receiver(Handle(THREAD, receiver()));
  }
  for (int i = 1; i < length(); ++i) {
    switch(values(i).get_type()) {
      case T_BOOLEAN:
      case T_CHAR:
      case T_SHORT:
      case T_INT:
        args.push_int(values(i).get_jint());
        break;
      case T_LONG:
        args.push_long(values(i).get_jlong());
        break;
      case T_FLOAT:
        args.push_float(values(i).get_jfloat());
        break;
      case T_DOUBLE:
        args.push_double(values(i).get_jdouble());
        break;
      case T_OBJECT:
        args.push_oop(Handle(THREAD, (oop)values(i).get_jobject()));
        break;
      case T_ADDRESS:
        args.push_oop(Handle(THREAD, JNIHandles::resolve(values(i).get_jobject())));
        break;
      default:
        ShouldNotReachHere();
    }
  }
}
JfrJavaArguments::JfrJavaArguments(JavaValue* result) : _result(result), _klass(NULL), _name(NULL), _signature(NULL), _array_length(-1) {
  assert(result != NULL, "invariant");
}
JfrJavaArguments::JfrJavaArguments(JavaValue* result, const char* klass_name, const char* name, const char* signature, TRAPS) :
  _result(result),
  _klass(NULL),
  _name(NULL),
  _signature(NULL),
  _array_length(-1) {
  assert(result != NULL, "invariant");
  if (klass_name != NULL) {
    set_klass(klass_name, CHECK);
  }
  if (name != NULL) {
    set_name(name, CHECK);
  }
  if (signature != NULL) {
    set_signature(signature, THREAD);
  }
}
JfrJavaArguments::JfrJavaArguments(JavaValue* result, const Klass* klass, const Symbol* name, const Symbol* signature) : _result(result),
  _klass(NULL),
  _name(NULL),
  _signature(NULL),
  _array_length(-1) {
  assert(result != NULL, "invariant");
  if (klass != NULL) {
    set_klass(klass);
  }
  if (name != NULL) {
    set_name(name);
  }
  if (signature != NULL) {
    set_signature(signature);
  }
}
Klass* JfrJavaArguments::klass() const {
  assert(_klass != NULL, "invariant");
  return const_cast<Klass*>(_klass);
}
void JfrJavaArguments::set_klass(const char* klass_name, TRAPS) {
  assert(klass_name != NULL, "invariant");
  Symbol* const k_sym = resolve(klass_name, CHECK);
  assert(k_sym != NULL, "invariant");
  const Klass* const klass = resolve(k_sym, CHECK);
  set_klass(klass);
}
void JfrJavaArguments::set_klass(const Klass* klass) {
  assert(klass != NULL, "invariant");
  _klass = klass;
}
Symbol* JfrJavaArguments::name() const {
  assert(_name != NULL, "invariant");
  return const_cast<Symbol*>(_name);
}
void JfrJavaArguments::set_name(const char* name, TRAPS) {
  assert(name != NULL, "invariant");
  const Symbol* const sym = resolve(name, CHECK);
  set_name(sym);
}
void JfrJavaArguments::set_name(const Symbol* name) {
  assert(name != NULL, "invariant");
  _name = name;
}
Symbol* JfrJavaArguments::signature() const {
  assert(_signature != NULL, "invariant");
  return const_cast<Symbol*>(_signature);
}
void JfrJavaArguments::set_signature(const char* signature, TRAPS) {
  assert(signature != NULL, "invariant");
  const Symbol* const sym = resolve(signature, CHECK);
  set_signature(sym);
}
void JfrJavaArguments::set_signature(const Symbol* signature) {
  assert(signature != NULL, "invariant");
  _signature = signature;
}
int JfrJavaArguments::array_length() const {
  return _array_length;
}
void JfrJavaArguments::set_array_length(int length) {
  assert(length >= 0, "invariant");
  _array_length = length;
}
JavaValue* JfrJavaArguments::result() const {
  assert(_result != NULL, "invariant");
  return const_cast<JavaValue*>(_result);
}
int JfrJavaArguments::length() const {
  return _params.length();
}
bool JfrJavaArguments::has_receiver() const {
  return _params.has_receiver();
}
oop JfrJavaArguments::receiver() const {
  return _params.receiver();
}
void JfrJavaArguments::set_receiver(const oop receiver) {
  _params.set_receiver(receiver);
}
void JfrJavaArguments::set_receiver(Handle receiver) {
  _params.set_receiver(receiver);
}
void JfrJavaArguments::push_oop(const oop obj) {
  _params.push_oop(obj);
}
void JfrJavaArguments::push_oop(Handle h_obj) {
  _params.push_oop(h_obj);
}
void JfrJavaArguments::push_jobject(jobject h) {
  _params.push_jobject(h);
}
void JfrJavaArguments::push_int(jint i) {
  _params.push_jint(i);
}
void JfrJavaArguments::push_float(jfloat f) {
  _params.push_jfloat(f);
}
void JfrJavaArguments::push_double(jdouble d) {
  _params.push_jdouble(d);
}
void JfrJavaArguments::push_long(jlong l) {
  _params.push_jlong(l);
}
const JavaValue& JfrJavaArguments::param(int idx) const {
  return _params.values(idx);
}
int JfrJavaArguments::java_call_arg_slots() const {
  return _params.java_stack_slots();
}
void JfrJavaArguments::copy(JavaCallArguments& args, TRAPS) {
  _params.copy(args, THREAD);
}
void JfrJavaCall::call_static(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JavaCallArguments jcas(args->java_call_arg_slots());
  args->copy(jcas, CHECK);
  JavaCalls::call_static(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD);
}
void JfrJavaCall::call_special(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  assert(args->has_receiver(), "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JavaCallArguments jcas(args->java_call_arg_slots());
  args->copy(jcas, CHECK);
  JavaCalls::call_special(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD);
}
void JfrJavaCall::call_virtual(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  assert(args->has_receiver(), "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  ResourceMark rm(THREAD);
  HandleMark hm(THREAD);
  JavaCallArguments jcas(args->java_call_arg_slots());
  args->copy(jcas, CHECK);
  JavaCalls::call_virtual(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJavaCall.hpp
#ifndef SHARE_VM_JFR_JNI_JFRJAVACALL_HPP
#define SHARE_VM_JFR_JNI_JFRJAVACALL_HPP
#include "jni.h"
#include "jfr/utilities/jfrAllocation.hpp"
#include "utilities/exceptions.hpp"
class JavaCallArguments;
class JavaThread;
class JavaValue;
class Klass;
class Symbol;
class JfrJavaArguments : public StackObj {
  friend class JfrJavaCall;
 public:
  JfrJavaArguments(JavaValue* result);
  JfrJavaArguments(JavaValue* result, const char* klass_name, const char* name, const char* signature, TRAPS);
  JfrJavaArguments(JavaValue* result, const Klass* klass, const Symbol* name, const Symbol* signature);
  Klass* klass() const;
  void set_klass(const char* klass_name, TRAPS);
  void set_klass(const Klass* klass);
  Symbol* name() const;
  void set_name(const char* name, TRAPS);
  void set_name(const Symbol* name);
  Symbol* signature() const;
  void set_signature(const char* signature, TRAPS);
  void set_signature(const Symbol* signature);
  int array_length() const;
  void set_array_length(int length);
  JavaValue* result() const;
  bool has_receiver() const;
  void set_receiver(const oop receiver);
  void set_receiver(Handle receiver);
  oop receiver() const;
  void push_oop(const oop obj);
  void push_oop(Handle h_obj);
  void push_jobject(jobject h);
  void push_int(jint i);
  void push_double(jdouble d);
  void push_long(jlong l);
  void push_float(jfloat f);
  int length() const;
  const JavaValue& param(int idx) const;
 private:
  class Parameters {
    friend class JfrJavaArguments;
   private:
    enum { SIZE = 16};
    JavaValue _storage[SIZE];
    int _storage_index;
    int _java_stack_slots;
    Parameters();
    Parameters(const Parameters&); // no impl
    Parameters& operator=(const Parameters&); // no impl
    void push(const JavaValue& value);
    void push_large(const JavaValue& value);
    void push_oop(const oop obj);
    void push_oop(Handle h_obj);
    void push_jobject(jobject h);
    void push_jint(jint i);
    void push_jdouble(jdouble d);
    void push_jlong(jlong l);
    void push_jfloat(jfloat f);
    bool has_receiver() const;
    void set_receiver(const oop receiver);
    void set_receiver(Handle receiver);
    oop receiver() const;
    int length() const;
    int java_stack_slots() const;
    void copy(JavaCallArguments& args, TRAPS) const;
    const JavaValue& values(int idx) const;
  };
  Parameters _params;
  const JavaValue* const _result;
  const Klass* _klass;
  const Symbol* _name;
  const Symbol* _signature;
  int _array_length;
  int java_call_arg_slots() const;
  void copy(JavaCallArguments& args, TRAPS);
};
class JfrJavaCall : public AllStatic {
  friend class JfrJavaSupport;
 private:
  static void call_static(JfrJavaArguments* args, TRAPS);
  static void call_special(JfrJavaArguments* args, TRAPS);
  static void call_virtual(JfrJavaArguments* args, TRAPS);
};
#endif // SHARE_VM_JFR_JNI_JFRJAVACALL_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJavaSupport.cpp
#include "precompiled.hpp"
#include "jni.h"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "jfr/jni/jfrJavaCall.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/support/jfrThreadId.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/java.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
#ifdef ASSERT
void JfrJavaSupport::check_java_thread_in_vm(Thread* t) {
  assert(t != NULL, "invariant");
  assert(t->is_Java_thread(), "invariant");
  assert(((JavaThread*)t)->thread_state() == _thread_in_vm, "invariant");
}
void JfrJavaSupport::check_java_thread_in_native(Thread* t) {
  assert(t != NULL, "invariant");
  assert(t->is_Java_thread(), "invariant");
  assert(((JavaThread*)t)->thread_state() == _thread_in_native, "invariant");
}
#endif
jobject JfrJavaSupport::local_jni_handle(const oop obj, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  return t->active_handles()->allocate_handle(obj);
}
jobject JfrJavaSupport::local_jni_handle(const jobject handle, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  const oop obj = JNIHandles::resolve(handle);
  return obj == NULL ? NULL : local_jni_handle(obj, t);
}
void JfrJavaSupport::destroy_local_jni_handle(jobject handle) {
  JNIHandles::destroy_local(handle);
}
jobject JfrJavaSupport::global_jni_handle(const oop obj, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  HandleMark hm(t);
  return JNIHandles::make_global(Handle(t, obj));
}
jobject JfrJavaSupport::global_jni_handle(const jobject handle, Thread* t) {
  const oop obj = JNIHandles::resolve(handle);
  return obj == NULL ? NULL : global_jni_handle(obj, t);
}
void JfrJavaSupport::destroy_global_jni_handle(const jobject handle) {
  JNIHandles::destroy_global(handle);
}
oop JfrJavaSupport::resolve_non_null(jobject obj) {
  return JNIHandles::resolve_non_null(obj);
}
void JfrJavaSupport::call_static(JfrJavaArguments* args, TRAPS) {
  JfrJavaCall::call_static(args, THREAD);
}
void JfrJavaSupport::call_special(JfrJavaArguments* args, TRAPS) {
  JfrJavaCall::call_special(args, THREAD);
}
void JfrJavaSupport::call_virtual(JfrJavaArguments* args, TRAPS) {
  JfrJavaCall::call_virtual(args, THREAD);
}
void JfrJavaSupport::notify_all(jobject object, TRAPS) {
  assert(object != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  HandleMark hm(THREAD);
  Handle h_obj(THREAD, resolve_non_null(object));
  assert(h_obj.not_null(), "invariant");
  ObjectSynchronizer::jni_enter(h_obj, THREAD);
  ObjectSynchronizer::notifyall(h_obj, THREAD);
  ObjectSynchronizer::jni_exit(h_obj(), THREAD);
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
}
static void object_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, TRAPS) {
  assert(args != NULL, "invariant");
  assert(result != NULL, "invariant");
  assert(klass != NULL, "invariant");
  assert(klass->is_initialized(), "invariant");
  HandleMark hm(THREAD);
  instanceOop obj = klass->allocate_instance(CHECK);
  instanceHandle h_obj(THREAD, obj);
  assert(h_obj.not_null(), "invariant");
  args->set_receiver(h_obj);
  result->set_type(T_VOID); // constructor result type
  JfrJavaSupport::call_special(args, CHECK);
  result->set_type(T_OBJECT); // set back to original result type
  result->set_jobject((jobject)h_obj());
}
static void array_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, int array_length, TRAPS) {
  assert(args != NULL, "invariant");
  assert(result != NULL, "invariant");
  assert(klass != NULL, "invariant");
  assert(klass->is_initialized(), "invariant");
  Klass* const ak = klass->array_klass(THREAD);
  ObjArrayKlass::cast(ak)->initialize(THREAD);
  HandleMark hm(THREAD);
  objArrayOop arr = ObjArrayKlass::cast(ak)->allocate(array_length, CHECK);
  result->set_jobject((jobject)arr);
}
static void create_object(JfrJavaArguments* args, JavaValue* result, TRAPS) {
  assert(args != NULL, "invariant");
  assert(result != NULL, "invariant");
  assert(result->get_type() == T_OBJECT, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
  klass->initialize(CHECK);
  const int array_length = args->array_length();
  if (array_length >= 0) {
    array_construction(args, result, klass, array_length, CHECK);
  } else {
    object_construction(args, result, klass, THREAD);
  }
}
static void handle_result(JavaValue* result, bool global_ref, Thread* t) {
  assert(result != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t));
  const oop result_oop = (const oop)result->get_jobject();
  if (result_oop == NULL) {
    return;
  }
  result->set_jobject(global_ref ?
                      JfrJavaSupport::global_jni_handle(result_oop, t) :
                      JfrJavaSupport::local_jni_handle(result_oop, t));
}
void JfrJavaSupport::new_object(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  create_object(args, args->result(), THREAD);
}
void JfrJavaSupport::new_object_local_ref(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue* const result = args->result();
  assert(result != NULL, "invariant");
  create_object(args, result, CHECK);
  handle_result(result, false, THREAD);
}
void JfrJavaSupport::new_object_global_ref(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue* const result = args->result();
  assert(result != NULL, "invariant");
  create_object(args, result, CHECK);
  handle_result(result, true, THREAD);
}
jstring JfrJavaSupport::new_string(const char* c_str, TRAPS) {
  assert(c_str != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  const oop result = java_lang_String::create_oop_from_str(c_str, THREAD);
  return (jstring)local_jni_handle(result, THREAD);
}
jobjectArray JfrJavaSupport::new_string_array(int length, TRAPS) {
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, "java/lang/String", "<init>", "()V", CHECK_NULL);
  args.set_array_length(length);
  new_object_local_ref(&args, THREAD);
  return (jobjectArray)args.result()->get_jobject();
}
jobject JfrJavaSupport::new_java_lang_Boolean(bool value, TRAPS) {
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, "java/lang/Boolean", "<init>", "(Z)V", CHECK_NULL);
  args.push_int(value ? (jint)JNI_TRUE : (jint)JNI_FALSE);
  new_object_local_ref(&args, THREAD);
  return args.result()->get_jobject();
}
jobject JfrJavaSupport::new_java_lang_Integer(jint value, TRAPS) {
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, "java/lang/Integer", "<init>", "(I)V", CHECK_NULL);
  args.push_int(value);
  new_object_local_ref(&args, THREAD);
  return args.result()->get_jobject();
}
jobject JfrJavaSupport::new_java_lang_Long(jlong value, TRAPS) {
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, "java/lang/Long", "<init>", "(J)V", CHECK_NULL);
  args.push_long(value);
  new_object_local_ref(&args, THREAD);
  return args.result()->get_jobject();
}
void JfrJavaSupport::set_array_element(jobjectArray arr, jobject element, int index, Thread* t) {
  assert(arr != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(t));
  HandleMark hm(t);
  objArrayHandle a(t, (objArrayOop)resolve_non_null(arr));
  a->obj_at_put(index, resolve_non_null(element));
}
static void write_int_field(const Handle& h_oop, fieldDescriptor* fd, jint value) {
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  h_oop->int_field_put(fd->offset(), value);
}
static void write_float_field(const Handle& h_oop, fieldDescriptor* fd, jfloat value) {
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  h_oop->float_field_put(fd->offset(), value);
}
static void write_double_field(const Handle& h_oop, fieldDescriptor* fd, jdouble value) {
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  h_oop->double_field_put(fd->offset(), value);
}
static void write_long_field(const Handle& h_oop, fieldDescriptor* fd, jlong value) {
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  h_oop->long_field_put(fd->offset(), value);
}
static void write_oop_field(const Handle& h_oop, fieldDescriptor* fd, const oop value) {
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  h_oop->obj_field_put(fd->offset(), value);
}
static void write_specialized_field(JfrJavaArguments* args, const Handle& h_oop, fieldDescriptor* fd, bool static_field) {
  assert(args != NULL, "invariant");
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  assert(fd->offset() > 0, "invariant");
  assert(args->length() >= 1, "invariant");
  assert(args->param(1).get_type() != T_VOID, "invariant");
  switch(fd->field_type()) {
    case T_BOOLEAN:
    case T_CHAR:
    case T_SHORT:
    case T_INT:
      write_int_field(h_oop, fd, args->param(1).get_jint());
      break;
    case T_FLOAT:
      write_float_field(h_oop, fd, args->param(1).get_jfloat());
      break;
    case T_DOUBLE:
      write_double_field(h_oop, fd, args->param(1).get_jdouble());
      break;
    case T_LONG:
      write_long_field(h_oop, fd, args->param(1).get_jlong());
      break;
    case T_OBJECT:
      write_oop_field(h_oop, fd, (oop)args->param(1).get_jobject());
      break;
    case T_ADDRESS:
      write_oop_field(h_oop, fd, JfrJavaSupport::resolve_non_null(args->param(1).get_jobject()));
      break;
    default:
      ShouldNotReachHere();
  }
}
static void read_specialized_field(JavaValue* result, const Handle& h_oop, fieldDescriptor* fd) {
  assert(result != NULL, "invariant");
  assert(h_oop.not_null(), "invariant");
  assert(fd != NULL, "invariant");
  assert(fd->offset() > 0, "invariant");
  switch(fd->field_type()) {
    case T_BOOLEAN:
    case T_CHAR:
    case T_SHORT:
    case T_INT:
      result->set_jint(h_oop->int_field(fd->offset()));
      break;
    case T_FLOAT:
      result->set_jfloat(h_oop->float_field(fd->offset()));
      break;
    case T_DOUBLE:
      result->set_jdouble(h_oop->double_field(fd->offset()));
      break;
    case T_LONG:
      result->set_jlong(h_oop->long_field(fd->offset()));
      break;
    case T_OBJECT:
      result->set_jobject((jobject)h_oop->obj_field(fd->offset()));
      break;
    default:
      ShouldNotReachHere();
  }
}
static bool find_field(InstanceKlass* ik,
                       Symbol* name_symbol,
                       Symbol* signature_symbol,
                       fieldDescriptor* fd,
                       bool is_static = false,
                       bool allow_super = false) {
  if (allow_super || is_static) {
    return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL;
  }
  return ik->find_local_field(name_symbol, signature_symbol, fd);
}
static void lookup_field(JfrJavaArguments* args, InstanceKlass* klass, fieldDescriptor* fd, bool static_field) {
  assert(args != NULL, "invariant");
  assert(klass != NULL, "invariant");
  assert(klass->is_initialized(), "invariant");
  assert(fd != NULL, "invariant");
  find_field(klass, args->name(), args->signature(), fd, static_field, true);
}
static void read_field(JfrJavaArguments* args, JavaValue* result, TRAPS) {
  assert(args != NULL, "invariant");
  assert(result != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
  klass->initialize(CHECK);
  const bool static_field = !args->has_receiver();
  fieldDescriptor fd;
  lookup_field(args, klass, &fd, static_field);
  assert(fd.offset() > 0, "invariant");
  HandleMark hm(THREAD);
  Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver()));
  read_specialized_field(result, h_oop, &fd);
}
static void write_field(JfrJavaArguments* args, JavaValue* result, TRAPS) {
  assert(args != NULL, "invariant");
  assert(result != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
  klass->initialize(CHECK);
  const bool static_field = !args->has_receiver();
  fieldDescriptor fd;
  lookup_field(args, klass, &fd, static_field);
  assert(fd.offset() > 0, "invariant");
  HandleMark hm(THREAD);
  Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver()));
  write_specialized_field(args, h_oop, &fd, static_field);
}
void JfrJavaSupport::set_field(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  write_field(args, args->result(), THREAD);
}
void JfrJavaSupport::get_field(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  read_field(args, args->result(), THREAD);
}
void JfrJavaSupport::get_field_local_ref(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue* const result = args->result();
  assert(result != NULL, "invariant");
  assert(result->get_type() == T_OBJECT, "invariant");
  read_field(args, result, CHECK);
  const oop obj = (const oop)result->get_jobject();
  if (obj != NULL) {
    result->set_jobject(local_jni_handle(obj, THREAD));
  }
}
void JfrJavaSupport::get_field_global_ref(JfrJavaArguments* args, TRAPS) {
  assert(args != NULL, "invariant");
  DEBUG_ONLY(check_java_thread_in_vm(THREAD));
  JavaValue* const result = args->result();
  assert(result != NULL, "invariant");
  assert(result->get_type() == T_OBJECT, "invariant");
  read_field(args, result, CHECK);
  const oop obj = (const oop)result->get_jobject();
  if (obj != NULL) {
    result->set_jobject(global_jni_handle(obj, THREAD));
  }
}
Klass* JfrJavaSupport::klass(const jobject handle) {
  const oop obj = resolve_non_null(handle);
  assert(obj != NULL, "invariant");
  return obj->klass();
}
const char* JfrJavaSupport::c_str(jstring string, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  if (string == NULL) {
    return NULL;
  }
  const char* temp = NULL;
  const oop java_string = resolve_non_null(string);
  if (java_lang_String::value(java_string) != NULL) {
    const size_t length = java_lang_String::utf8_length(java_string);
    temp = NEW_RESOURCE_ARRAY_IN_THREAD(t, const char, (length + 1));
    if (temp == NULL) {
       JfrJavaSupport::throw_out_of_memory_error("Unable to allocate thread local native memory", t);
       return NULL;
    }
    assert(temp != NULL, "invariant");
    java_lang_String::as_utf8_string(java_string, const_cast<char*>(temp), (int) length + 1);
  }
  return temp;
}
static void create_and_throw(Symbol* name, const char* message, TRAPS) {
  assert(name != NULL, "invariant");
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  assert(!HAS_PENDING_EXCEPTION, "invariant");
  THROW_MSG(name, message);
}
void JfrJavaSupport::throw_illegal_state_exception(const char* message, TRAPS) {
  create_and_throw(vmSymbols::java_lang_IllegalStateException(), message, THREAD);
}
void JfrJavaSupport::throw_internal_error(const char* message, TRAPS) {
  create_and_throw(vmSymbols::java_lang_InternalError(), message, THREAD);
}
void JfrJavaSupport::throw_illegal_argument_exception(const char* message, TRAPS) {
  create_and_throw(vmSymbols::java_lang_IllegalArgumentException(), message, THREAD);
}
void JfrJavaSupport::throw_out_of_memory_error(const char* message, TRAPS) {
  create_and_throw(vmSymbols::java_lang_OutOfMemoryError(), message, THREAD);
}
void JfrJavaSupport::throw_class_format_error(const char* message, TRAPS) {
  create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD);
}
void JfrJavaSupport::abort(jstring errorMsg, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  ResourceMark rm(t);
  const char* const error_msg = c_str(errorMsg, t);
  if (error_msg != NULL) {
    if (true) tty->print_cr("%s",error_msg);
  }
  if (true) tty->print_cr("%s", "An irrecoverable error in Jfr. Shutting down VM...");
  vm_abort();
}
JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR;
void JfrJavaSupport::set_cause(jthrowable throwable, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  HandleMark hm(t);
  Handle ex(t, JNIHandles::resolve_external_guard(throwable));
  if (ex.is_null()) {
    return;
  }
  if (ex->is_a(SystemDictionary::OutOfMemoryError_klass())) {
    _cause = OUT_OF_MEMORY;
    return;
  }
  if (ex->is_a(SystemDictionary::StackOverflowError_klass())) {
    _cause = STACK_OVERFLOW;
    return;
  }
  if (ex->is_a(SystemDictionary::Error_klass())) {
    _cause = VM_ERROR;
    return;
  }
  if (ex->is_a(SystemDictionary::RuntimeException_klass())) {
    _cause = RUNTIME_EXCEPTION;
    return;
  }
  if (ex->is_a(SystemDictionary::Exception_klass())) {
    _cause = UNKNOWN;
    return;
  }
}
void JfrJavaSupport::uncaught_exception(jthrowable throwable, Thread* t) {
  DEBUG_ONLY(check_java_thread_in_vm(t));
  assert(throwable != NULL, "invariant");
  set_cause(throwable, t);
}
JfrJavaSupport::CAUSE JfrJavaSupport::cause() {
  return _cause;
}
jlong JfrJavaSupport::jfr_thread_id(jobject target_thread) {
  JavaThread* native_thread = java_lang_Thread::thread(JNIHandles::resolve_non_null(target_thread));
  return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJavaSupport.hpp
#ifndef SHARE_VM_JFR_JNI_JFRJAVASUPPORT_HPP
#define SHARE_VM_JFR_JNI_JFRJAVASUPPORT_HPP
#include "jfr/jni/jfrJavaCall.hpp"
#include "utilities/exceptions.hpp"
class Klass;
class JavaThread;
class outputStream;
class JfrJavaSupport : public AllStatic {
 public:
  static jobject local_jni_handle(const oop obj, Thread* t);
  static jobject local_jni_handle(const jobject handle, Thread* t);
  static void destroy_local_jni_handle(const jobject handle);
  static jobject global_jni_handle(const oop obj, Thread* t);
  static jobject global_jni_handle(const jobject handle, Thread* t);
  static void destroy_global_jni_handle(const jobject handle);
  static oop resolve_non_null(jobject obj);
  static void notify_all(jobject obj, TRAPS);
  static void set_array_element(jobjectArray arr, jobject element, int index, Thread* t);
  static void call_static(JfrJavaArguments* args, TRAPS);
  static void call_special(JfrJavaArguments* args, TRAPS);
  static void call_virtual(JfrJavaArguments* args, TRAPS);
  static void set_field(JfrJavaArguments* args, TRAPS);
  static void get_field(JfrJavaArguments* args, TRAPS);
  static void new_object(JfrJavaArguments* args, TRAPS);
  static void new_object_global_ref(JfrJavaArguments* args, TRAPS);
  static void get_field_global_ref(JfrJavaArguments* args, TRAPS);
  static void new_object_local_ref(JfrJavaArguments* args, TRAPS);
  static void get_field_local_ref(JfrJavaArguments* args, TRAPS);
  static jstring new_string(const char* c_str, TRAPS);
  static jobjectArray new_string_array(int length, TRAPS);
  static jobject new_java_lang_Boolean(bool value, TRAPS);
  static jobject new_java_lang_Integer(jint value, TRAPS);
  static jobject new_java_lang_Long(jlong value, TRAPS);
  static Klass* klass(const jobject handle);
  static const char* c_str(jstring string, Thread* jt);
  static void throw_illegal_state_exception(const char* message, TRAPS);
  static void throw_illegal_argument_exception(const char* message, TRAPS);
  static void throw_internal_error(const char* message, TRAPS);
  static void throw_out_of_memory_error(const char* message, TRAPS);
  static void throw_class_format_error(const char* message, TRAPS);
  static jlong jfr_thread_id(jobject target_thread);
  static void abort(jstring errorMsg, TRAPS);
  static void uncaught_exception(jthrowable throwable, Thread* t);
  DEBUG_ONLY(static void check_java_thread_in_vm(Thread* t);)
  DEBUG_ONLY(static void check_java_thread_in_native(Thread* t);)
  enum CAUSE {
    VM_ERROR,
    OUT_OF_MEMORY,
    STACK_OVERFLOW,
    RUNTIME_EXCEPTION,
    UNKNOWN,
    NOF_CAUSES
  };
  static CAUSE cause();
 private:
  static CAUSE _cause;
  static void set_cause(jthrowable throwable, Thread* t);
};
#endif // SHARE_VM_JFR_JNI_JFRJAVASUPPORT_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJniMethod.cpp
#include "precompiled.hpp"
#include "jni.h"
#include "jvm.h"
#include "jfr/jfr.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/recorder/jfrEventSetting.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/repository/jfrRepository.hpp"
#include "jfr/recorder/repository/jfrChunkRotation.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/recorder/stringpool/jfrStringPool.hpp"
#include "jfr/jni/jfrGetAllEventClasses.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrJniMethodRegistration.hpp"
#include "jfr/instrumentation/jfrEventClassTransformer.hpp"
#include "jfr/instrumentation/jfrJvmtiAgent.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/utilities/jfrJavaLog.hpp"
#include "jfr/utilities/jfrTimeConverter.hpp"
#include "jfr/utilities/jfrTime.hpp"
#include "jfr/writers/jfrJavaEventWriter.hpp"
#include "jfrfiles/jfrPeriodic.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/debug.hpp"
#define NO_TRANSITION(result_type, header) extern "C" { result_type JNICALL header {
#define NO_TRANSITION_END } }
NO_TRANSITION(void, jfr_register_natives(JNIEnv* env, jclass jvmclass))
  JfrJniMethodRegistration register_native_methods(env);
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_is_enabled())
  return Jfr::is_enabled() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_is_disabled())
  return Jfr::is_disabled() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_is_started())
  return JfrRecorder::is_created() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jstring, jfr_get_pid(JNIEnv* env, jobject jvm))
  char pid_buf[32] = { 0 };
  jio_snprintf(pid_buf, sizeof(pid_buf), "%d", os::current_process_id());
  jstring pid_string = env->NewStringUTF(pid_buf);
  return pid_string; // exception pending if NULL
NO_TRANSITION_END
NO_TRANSITION(jlong, jfr_elapsed_frequency(JNIEnv* env, jobject jvm))
  return JfrTime::frequency();
NO_TRANSITION_END
NO_TRANSITION(jlong, jfr_elapsed_counter(JNIEnv* env, jobject jvm))
  return JfrTicks::now();
NO_TRANSITION_END
NO_TRANSITION(void, jfr_retransform_classes(JNIEnv* env, jobject jvm, jobjectArray classes))
  JfrJvmtiAgent::retransform_classes(env, classes, JavaThread::thread_from_jni_environment(env));
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_enabled(JNIEnv* env, jobject jvm, jlong event_type_id, jboolean enabled))
  JfrEventSetting::set_enabled(event_type_id, JNI_TRUE == enabled);
  if (EventOldObjectSample::eventId == event_type_id) {
    ThreadInVMfromNative transition(JavaThread::thread_from_jni_environment(env));
    if (JNI_TRUE == enabled) {
      LeakProfiler::start(JfrOptionSet::old_object_queue_size());
    } else {
      LeakProfiler::stop();
    }
  }
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong threshold))
  JfrChunkRotation::set_threshold((intptr_t)threshold);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads))
  JfrOptionSet::set_sample_threads(sampleThreads);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_stack_depth(JNIEnv* env, jobject jvm, jint depth))
  JfrOptionSet::set_stackdepth((jlong)depth);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_stacktrace_enabled(JNIEnv* env, jobject jvm, jlong event_type_id, jboolean enabled))
  JfrEventSetting::set_stacktrace(event_type_id, JNI_TRUE == enabled);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_global_buffer_count(JNIEnv* env, jobject jvm, jlong count))
  JfrOptionSet::set_num_global_buffers(count);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_global_buffer_size(JNIEnv* env, jobject jvm, jlong size))
JfrOptionSet::set_global_buffer_size(size);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_thread_buffer_size(JNIEnv* env, jobject jvm, jlong size))
  JfrOptionSet::set_thread_buffer_size(size);
NO_TRANSITION_END
NO_TRANSITION(void, jfr_set_memory_size(JNIEnv* env, jobject jvm, jlong size))
  JfrOptionSet::set_memory_size(size);
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_set_threshold(JNIEnv* env, jobject jvm, jlong event_type_id, jlong thresholdTicks))
  return JfrEventSetting::set_threshold(event_type_id, thresholdTicks) ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_allow_event_retransforms(JNIEnv* env, jobject jvm))
  return JfrOptionSet::allow_event_retransforms() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_is_available(JNIEnv* env, jclass jvm))
  return !Jfr::is_disabled() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jlong, jfr_get_epoch_address(JNIEnv* env, jobject jvm))
  return JfrTraceIdEpoch::epoch_address();
NO_TRANSITION_END
NO_TRANSITION(jlong, jfr_get_unloaded_event_classes_count(JNIEnv* env, jobject jvm))
  return JfrEventClasses::unloaded_event_classes_count();
NO_TRANSITION_END
NO_TRANSITION(jdouble, jfr_time_conv_factor(JNIEnv* env, jobject jvm))
  return (jdouble)JfrTimeConverter::nano_to_counter_multiplier();
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_set_cutoff(JNIEnv* env, jobject jvm, jlong event_type_id, jlong cutoff_ticks))
  return JfrEventSetting::set_cutoff(event_type_id, cutoff_ticks) ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
NO_TRANSITION(jboolean, jfr_should_rotate_disk(JNIEnv* env, jobject jvm))
  return JfrChunkRotation::should_rotate() ? JNI_TRUE : JNI_FALSE;
NO_TRANSITION_END
JVM_ENTRY_NO_ENV(jboolean, jfr_create_jfr(JNIEnv* env, jobject jvm, jboolean simulate_failure))
  if (JfrRecorder::is_created()) {
    return JNI_TRUE;
  }
  if (!JfrRecorder::create(simulate_failure == JNI_TRUE)) {
    JfrJavaSupport::throw_illegal_state_exception("Unable to start Jfr", thread);
    return JNI_FALSE;
  }
  return JNI_TRUE;
JVM_END
JVM_ENTRY_NO_ENV(jboolean, jfr_destroy_jfr(JNIEnv* env, jobject jvm))
  JfrRecorder::destroy();
  return JNI_TRUE;
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_begin_recording(JNIEnv* env, jobject jvm))
  if (JfrRecorder::is_recording()) {
    return;
  }
  JfrRecorder::start_recording();
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_end_recording(JNIEnv* env, jobject jvm))
  if (!JfrRecorder::is_recording()) {
    return;
  }
  JfrRecorder::stop_recording();
JVM_END
JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when))
  JfrPeriodicEventSet::requestEvent((JfrEventId)eventTypeId);
  return thread->has_pending_exception() ? JNI_FALSE : JNI_TRUE;
JVM_END
JVM_ENTRY_NO_ENV(jobject, jfr_get_all_event_classes(JNIEnv* env, jobject jvm))
  return JfrEventClasses::get_all_event_classes(thread);
JVM_END
JVM_ENTRY_NO_ENV(jlong, jfr_class_id(JNIEnv* env, jclass jvm, jclass jc))
  return JfrTraceId::use(jc);
JVM_END
JVM_ENTRY_NO_ENV(jlong, jfr_stacktrace_id(JNIEnv* env, jobject jvm, jint skip))
  return JfrStackTraceRepository::record(thread, skip);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_log(JNIEnv* env, jobject jvm, jint tag_set, jint level, jstring message))
 JfrJavaLog::log(tag_set, level, message, thread);
JVM_END
JVM_ENTRY_NO_ENV(jboolean, jfr_should_log(JNIEnv* env, jobject jvm, jint level))
 return JfrJavaLog::should_log(level, thread) ? JNI_TRUE : JNI_FALSE;
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_subscribe_log_level(JNIEnv* env, jobject jvm, jobject log_tag, jint id))
 JfrJavaLog::subscribe_log_level(log_tag, id, thread);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_set_output(JNIEnv* env, jobject jvm, jstring path))
  JfrRepository::set_chunk_path(path, thread);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_set_method_sampling_interval(JNIEnv* env, jobject jvm, jlong type, jlong intervalMillis))
  if (intervalMillis < 0) {
    intervalMillis = 0;
  }
  JfrEventId typed_event_id = (JfrEventId)type;
  assert(EventExecutionSample::eventId == typed_event_id || EventNativeMethodSample::eventId == typed_event_id, "invariant");
  if (intervalMillis > 0) {
    JfrEventSetting::set_enabled(typed_event_id, true); // ensure sampling event is enabled
  }
  if (EventExecutionSample::eventId == type) {
    JfrThreadSampling::set_java_sample_interval(intervalMillis);
  } else {
    JfrThreadSampling::set_native_sample_interval(intervalMillis);
  }
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_store_metadata_descriptor(JNIEnv* env, jobject jvm, jbyteArray descriptor))
  JfrMetadataEvent::update(descriptor);
JVM_END
JVM_ENTRY_NO_ENV(jlong, jfr_id_for_thread(JNIEnv* env, jobject jvm, jobject t))
  return JfrJavaSupport::jfr_thread_id(t);
JVM_END
JVM_ENTRY_NO_ENV(jobject, jfr_get_event_writer(JNIEnv* env, jclass cls))
  return JfrJavaEventWriter::event_writer(thread);
JVM_END
JVM_ENTRY_NO_ENV(jobject, jfr_new_event_writer(JNIEnv* env, jclass cls))
  return JfrJavaEventWriter::new_event_writer(thread);
JVM_END
JVM_ENTRY_NO_ENV(jboolean, jfr_event_writer_flush(JNIEnv* env, jclass cls, jobject writer, jint used_size, jint requested_size))
  return JfrJavaEventWriter::flush(writer, used_size, requested_size, thread);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_set_repository_location(JNIEnv* env, jobject repo, jstring location))
  return JfrRepository::set_path(location, thread);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_uncaught_exception(JNIEnv* env, jobject jvm, jobject t, jthrowable throwable))
  JfrJavaSupport::uncaught_exception(throwable, thread);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_abort(JNIEnv* env, jobject jvm, jstring errorMsg))
  JfrJavaSupport::abort(errorMsg, thread);
JVM_END
JVM_ENTRY_NO_ENV(jlong, jfr_type_id(JNIEnv* env, jobject jvm, jclass jc))
  return JfrTraceId::get(jc);
JVM_END
JVM_ENTRY_NO_ENV(jboolean, jfr_add_string_constant(JNIEnv* env, jclass jvm, jboolean epoch, jlong id, jstring string))
  return JfrStringPool::add(epoch == JNI_TRUE, id, string, thread) ? JNI_TRUE : JNI_FALSE;
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jobject jvm, jboolean force_instrumentation))
  JfrEventClassTransformer::set_force_instrumentation(force_instrumentation == JNI_TRUE);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_emit_old_object_samples(JNIEnv* env, jobject jvm, jlong cutoff_ticks, jboolean emit_all))
  LeakProfiler::emit_events(cutoff_ticks, emit_all == JNI_TRUE);
JVM_END
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJniMethod.hpp
#ifndef SHARE_VM_JFR_JNI_JFRJNIMETHOD_HPP
#define SHARE_VM_JFR_JNI_JFRJNIMETHOD_HPP
#include "jni.h"
#ifdef __cplusplus
extern "C" {
#endif
jboolean JNICALL jfr_is_enabled();
jboolean JNICALL jfr_is_disabled();
jboolean JNICALL jfr_is_started();
jlong JNICALL jfr_elapsed_counter(JNIEnv* env, jobject jvm);
jboolean JNICALL jfr_create_jfr(JNIEnv* env, jobject jvm, jboolean simulate_failure);
jboolean JNICALL jfr_destroy_jfr(JNIEnv* env, jobject jvm);
void JNICALL jfr_begin_recording(JNIEnv* env, jobject jvm);
void JNICALL jfr_end_recording(JNIEnv* env, jobject jvm);
jboolean JNICALL jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when);
jobject JNICALL jfr_get_all_event_classes(JNIEnv* env, jobject jvm);
jlong JNICALL jfr_class_id(JNIEnv* env, jclass jvm, jclass jc);
jstring JNICALL jfr_get_pid(JNIEnv* env, jobject jvm);
jlong JNICALL jfr_stacktrace_id(JNIEnv* env, jobject jvm, jint skip);
jlong JNICALL jfr_elapsed_frequency(JNIEnv* env, jobject jvm);
void JNICALL jfr_subscribe_log_level(JNIEnv* env, jobject jvm, jobject log_tag, jint id);
void JNICALL jfr_log(JNIEnv* env, jobject jvm, jint tag_set, jint level, jstring message);
jboolean JNICALL jfr_should_log(JNIEnv* env, jobject jvm, jint level);
void JNICALL jfr_retransform_classes(JNIEnv* env, jobject jvm, jobjectArray classes);
void JNICALL jfr_set_enabled(JNIEnv* env, jobject jvm, jlong event_type_id, jboolean enabled);
void JNICALL jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong delta);
void JNICALL jfr_set_global_buffer_count(JNIEnv* env, jobject jvm, jlong count);
void JNICALL jfr_set_global_buffer_size(JNIEnv* env, jobject jvm, jlong size);
void JNICALL jfr_set_method_sampling_interval(JNIEnv* env, jobject jvm, jlong type, jlong intervalMillis);
void JNICALL jfr_set_output(JNIEnv* env, jobject jvm, jstring path);
void JNICALL jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads);
void JNICALL jfr_set_stack_depth(JNIEnv* env, jobject jvm, jint depth);
void JNICALL jfr_set_stacktrace_enabled(JNIEnv* env, jobject jvm, jlong event_type_id, jboolean enabled);
void JNICALL jfr_set_thread_buffer_size(JNIEnv* env, jobject jvm, jlong size);
void JNICALL jfr_set_memory_size(JNIEnv* env, jobject jvm, jlong size);
jboolean JNICALL jfr_set_threshold(JNIEnv* env, jobject jvm, jlong event_type_id, jlong thresholdTicks);
void JNICALL jfr_store_metadata_descriptor(JNIEnv* env, jobject jvm, jbyteArray descriptor);
jlong JNICALL jfr_id_for_thread(JNIEnv* env, jobject jvm, jobject t);
jboolean JNICALL jfr_allow_event_retransforms(JNIEnv* env, jobject jvm);
jboolean JNICALL jfr_is_available(JNIEnv* env, jclass jvm);
jdouble JNICALL jfr_time_conv_factor(JNIEnv* env, jobject jvm);
jlong JNICALL jfr_type_id(JNIEnv* env, jobject jvm, jclass jc);
void JNICALL jfr_set_repository_location(JNIEnv* env, jobject repo, jstring location);
jobject JNICALL jfr_get_event_writer(JNIEnv* env, jclass cls);
jobject JNICALL jfr_new_event_writer(JNIEnv* env, jclass cls);
jboolean JNICALL jfr_event_writer_flush(JNIEnv* env, jclass cls, jobject writer, jint used_size, jint requested_size);
void JNICALL jfr_abort(JNIEnv* env, jobject jvm, jstring errorMsg);
jlong JNICALL jfr_get_epoch_address(JNIEnv* env, jobject jvm);
jboolean JNICALL jfr_add_string_constant(JNIEnv* env, jclass jvm, jboolean epoch, jlong id, jstring string);
void JNICALL jfr_uncaught_exception(JNIEnv* env, jobject jvm, jobject thread, jthrowable throwable);
void JNICALL jfr_set_force_instrumentation(JNIEnv* env, jobject jvm, jboolean force);
jlong JNICALL jfr_get_unloaded_event_classes_count(JNIEnv* env, jobject jvm);
jboolean JNICALL jfr_set_cutoff(JNIEnv* env, jobject jvm, jlong event_type_id, jlong cutoff_ticks);
void JNICALL jfr_emit_old_object_samples(JNIEnv* env, jobject jvm, jlong cutoff_ticks, jboolean);
jboolean JNICALL jfr_should_rotate_disk(JNIEnv* env, jobject jvm);
#ifdef __cplusplus
}
#endif
#endif // SHARE_VM_JFR_JNI_JFRJNIMETHOD_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJniMethodRegistration.cpp
#include "precompiled.hpp"
#include "jfr/jni/jfrJniMethod.hpp"
#include "jfr/jni/jfrJniMethodRegistration.hpp"
#include "jfr/utilities/jfrJavaLog.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/thread.hpp"
#include "utilities/exceptions.hpp"
JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
  assert(env != NULL, "invariant");
  jclass jfr_clz = env->FindClass("jdk/jfr/internal/JVM");
  if (jfr_clz != NULL) {
    JNINativeMethod method[] = {
      (char*)"beginRecording", (char*)"()V", (void*)jfr_begin_recording,
      (char*)"endRecording", (char*)"()V", (void*)jfr_end_recording,
      (char*)"counterTime", (char*)"()J", (void*)jfr_elapsed_counter,
      (char*)"createJFR", (char*)"(Z)Z", (void*)jfr_create_jfr,
      (char*)"destroyJFR", (char*)"()Z", (void*)jfr_destroy_jfr,
      (char*)"emitEvent", (char*)"(JJJ)Z", (void*)jfr_emit_event,
      (char*)"getAllEventClasses", (char*)"()Ljava/util/List;", (void*)jfr_get_all_event_classes,
      (char*)"getClassIdNonIntrinsic", (char*)"(Ljava/lang/Class;)J", (void*)jfr_class_id,
      (char*)"getPid", (char*)"()Ljava/lang/String;", (void*)jfr_get_pid,
      (char*)"getStackTraceId", (char*)"(I)J", (void*)jfr_stacktrace_id,
      (char*)"getThreadId", (char*)"(Ljava/lang/Thread;)J", (void*)jfr_id_for_thread,
      (char*)"getTicksFrequency", (char*)"()J", (void*)jfr_elapsed_frequency,
      (char*)"subscribeLogLevel", (char*)"(Ljdk/jfr/internal/LogTag;I)V", (void*)jfr_subscribe_log_level,
      (char*)"log", (char*)"(IILjava/lang/String;)V", (void*)jfr_log,
      (char*)"shouldLog", (char*)"(I)Z", (void*)jfr_should_log,
      (char*)"retransformClasses", (char*)"([Ljava/lang/Class;)V", (void*)jfr_retransform_classes,
      (char*)"setEnabled", (char*)"(JZ)V", (void*)jfr_set_enabled,
      (char*)"setFileNotification", (char*)"(J)V", (void*)jfr_set_file_notification,
      (char*)"setGlobalBufferCount", (char*)"(J)V", (void*)jfr_set_global_buffer_count,
      (char*)"setGlobalBufferSize", (char*)"(J)V", (void*)jfr_set_global_buffer_size,
      (char*)"setMethodSamplingInterval", (char*)"(JJ)V", (void*)jfr_set_method_sampling_interval,
      (char*)"setOutput", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_output,
      (char*)"setSampleThreads", (char*)"(Z)V", (void*)jfr_set_sample_threads,
      (char*)"setStackDepth", (char*)"(I)V", (void*)jfr_set_stack_depth,
      (char*)"setStackTraceEnabled", (char*)"(JZ)V", (void*)jfr_set_stacktrace_enabled,
      (char*)"setThreadBufferSize", (char*)"(J)V", (void*)jfr_set_thread_buffer_size,
      (char*)"setMemorySize", (char*)"(J)V", (void*)jfr_set_memory_size,
      (char*)"setThreshold", (char*)"(JJ)Z", (void*)jfr_set_threshold,
      (char*)"storeMetadataDescriptor", (char*)"([B)V", (void*)jfr_store_metadata_descriptor,
      (char*)"getAllowedToDoEventRetransforms", (char*)"()Z", (void*)jfr_allow_event_retransforms,
      (char*)"isAvailable", (char*)"()Z", (void*)jfr_is_available,
      (char*)"getTimeConversionFactor", (char*)"()D", (void*)jfr_time_conv_factor,
      (char*)"getTypeId", (char*)"(Ljava/lang/Class;)J", (void*)jfr_type_id,
      (char*)"getEventWriter", (char*)"()Ljava/lang/Object;", (void*)jfr_get_event_writer,
      (char*)"newEventWriter", (char*)"()Ljdk/jfr/internal/EventWriter;", (void*)jfr_new_event_writer,
      (char*)"flush", (char*)"(Ljdk/jfr/internal/EventWriter;II)Z", (void*)jfr_event_writer_flush,
      (char*)"setRepositoryLocation", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_repository_location,
      (char*)"abort", (char*)"(Ljava/lang/String;)V", (void*)jfr_abort,
      (char*)"getEpochAddress", (char*)"()J",(void*)jfr_get_epoch_address,
      (char*)"addStringConstant", (char*)"(ZJLjava/lang/String;)Z", (void*)jfr_add_string_constant,
      (char*)"uncaughtException", (char*)"(Ljava/lang/Thread;Ljava/lang/Throwable;)V", (void*)jfr_uncaught_exception,
      (char*)"setForceInstrumentation", (char*)"(Z)V", (void*)jfr_set_force_instrumentation,
      (char*)"getUnloadedEventClassCount", (char*)"()J", (void*)jfr_get_unloaded_event_classes_count,
      (char*)"setCutoff", (char*)"(JJ)Z", (void*)jfr_set_cutoff,
      (char*)"emitOldObjectSamples", (char*)"(JZ)V", (void*)jfr_emit_old_object_samples,
      (char*)"shouldRotateDisk", (char*)"()Z", (void*)jfr_should_rotate_disk
    };
    const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);
    if (env->RegisterNatives(jfr_clz, method, (jint)method_array_length) != JNI_OK) {
      JavaThread* jt = JavaThread::thread_from_jni_environment(env);
      assert(jt != NULL, "invariant");
      assert(jt->thread_state() == _thread_in_native, "invariant");
      ThreadInVMfromNative transition(jt);
      if (true) tty->print_cr("RegisterNatives for JVM class failed!");
    }
    env->DeleteLocalRef(jfr_clz);
  }
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrJniMethodRegistration.hpp
#ifndef SHARE_VM_JFR_JNI_JFRJNIMETHODREGISTRATION_HPP
#define SHARE_VM_JFR_JNI_JFRJNIMETHODREGISTRATION_HPP
#include "jni.h"
#include "memory/allocation.hpp"
class JfrJniMethodRegistration : public StackObj {
 public:
  JfrJniMethodRegistration(JNIEnv* env);
};
#endif // SHARE_VM_JFR_JNI_JFRJNIMETHODREGISTRATION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrUpcalls.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrUpcalls.hpp"
#include "jfr/support/jfrEventClass.hpp"
#include "memory/oopFactory.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
static Symbol* jvm_upcalls_class_sym = NULL;
static Symbol* on_retransform_method_sym = NULL;
static Symbol* on_retransform_signature_sym = NULL;
static Symbol* bytes_for_eager_instrumentation_sym = NULL;
static Symbol* bytes_for_eager_instrumentation_sig_sym = NULL;
static bool initialize(TRAPS) {
  static bool initialized = false;
  if (!initialized) {
    DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
    jvm_upcalls_class_sym = SymbolTable::new_permanent_symbol("jdk/jfr/internal/JVMUpcalls", CHECK_false);
    on_retransform_method_sym = SymbolTable::new_permanent_symbol("onRetransform", CHECK_false);
    on_retransform_signature_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B", CHECK_false);
    bytes_for_eager_instrumentation_sym = SymbolTable::new_permanent_symbol("bytesForEagerInstrumentation", CHECK_false);
    bytes_for_eager_instrumentation_sig_sym = SymbolTable::new_permanent_symbol("(JZLjava/lang/Class;[B)[B", THREAD);
    initialized = bytes_for_eager_instrumentation_sig_sym != NULL;
  }
  return initialized;
}
static const typeArrayOop invoke(jlong trace_id,
                                 jboolean force_instrumentation,
                                 jclass class_being_redefined,
                                 jint class_data_len,
                                 const unsigned char* class_data,
                                 Symbol* method_sym,
                                 Symbol* signature_sym,
                                 jint& new_bytes_length,
                                 TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  const Klass* klass = SystemDictionary::resolve_or_fail(jvm_upcalls_class_sym, true, CHECK_NULL);
  assert(klass != NULL, "invariant");
  typeArrayOop old_byte_array = oopFactory::new_byteArray(class_data_len, CHECK_NULL);
  memcpy(old_byte_array->byte_at_addr(0), class_data, class_data_len);
  JavaValue result(T_OBJECT);
  JfrJavaArguments args(&result, klass, method_sym, signature_sym);
  args.push_long(trace_id);
  args.push_int(force_instrumentation);
  args.push_jobject(class_being_redefined);
  args.push_oop(old_byte_array);
  JfrJavaSupport::call_static(&args, THREAD);
  if (HAS_PENDING_EXCEPTION) {
    if (true) tty->print_cr("JfrUpcall failed");
    return NULL;
  }
  const oop res = (oop)result.get_jobject();
  assert(res != NULL, "invariant");
  assert(res->is_typeArray(), "invariant");
  assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "invariant");
  const typeArrayOop new_byte_array = typeArrayOop(res);
  new_bytes_length = (jint)new_byte_array->length();
  return new_byte_array;
}
static const size_t ERROR_MSG_BUFFER_SIZE = 256;
static void log_error_and_throw_oom(jint new_bytes_length, TRAPS) {
  char error_buffer[ERROR_MSG_BUFFER_SIZE];
  jio_snprintf(error_buffer, ERROR_MSG_BUFFER_SIZE,
    "Thread local allocation (native) for " SIZE_FORMAT " bytes failed in JfrUpcalls", (size_t)new_bytes_length);
  if (true) tty->print_cr("%s", error_buffer);
  JfrJavaSupport::throw_out_of_memory_error(error_buffer, CHECK);
}
void JfrUpcalls::on_retransform(jlong trace_id,
                                jclass class_being_redefined,
                                jint class_data_len,
                                const unsigned char* class_data,
                                jint* new_class_data_len,
                                unsigned char** new_class_data,
                                TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  assert(class_being_redefined != NULL, "invariant");
  assert(class_data != NULL, "invariant");
  assert(new_class_data_len != NULL, "invariant");
  assert(new_class_data != NULL, "invariant");
  if (!JdkJfrEvent::is_visible(class_being_redefined)) {
    return;
  }
  jint new_bytes_length = 0;
  initialize(THREAD);
  const typeArrayOop new_byte_array = invoke(trace_id,
                                             false,
                                             class_being_redefined,
                                             class_data_len,
                                             class_data,
                                             on_retransform_method_sym,
                                             on_retransform_signature_sym,
                                             new_bytes_length,
                                             CHECK);
  assert(new_byte_array != NULL, "invariant");
  assert(new_bytes_length > 0, "invariant");
  unsigned char* const new_bytes = (unsigned char* const)os::malloc(new_bytes_length, mtInternal);
  if (new_bytes == NULL) {
    log_error_and_throw_oom(new_bytes_length, THREAD); // unwinds
  }
  assert(new_bytes != NULL, "invariant");
  memcpy(new_bytes, new_byte_array->byte_at_addr(0), (size_t)new_bytes_length);
}
void JfrUpcalls::new_bytes_eager_instrumentation(jlong trace_id,
                                                 jboolean force_instrumentation,
                                                 jclass super,
                                                 jint class_data_len,
                                                 const unsigned char* class_data,
                                                 jint* new_class_data_len,
                                                 unsigned char** new_class_data,
                                                 TRAPS) {
  DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
  assert(super != NULL, "invariant");
  assert(class_data != NULL, "invariant");
  assert(new_class_data_len != NULL, "invariant");
  assert(new_class_data != NULL, "invariant");
  jint new_bytes_length = 0;
  initialize(THREAD);
  const typeArrayOop new_byte_array = invoke(trace_id,
                                             force_instrumentation,
                                             super,
                                             class_data_len,
                                             class_data,
                                             bytes_for_eager_instrumentation_sym,
                                             bytes_for_eager_instrumentation_sig_sym,
                                             new_bytes_length,
                                             CHECK);
  assert(new_byte_array != NULL, "invariant");
  assert(new_bytes_length > 0, "invariant");
  unsigned char* const new_bytes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, unsigned char, new_bytes_length);
  if (new_bytes == NULL) {
    log_error_and_throw_oom(new_bytes_length, THREAD); // this unwinds
  }
  assert(new_bytes != NULL, "invariant");
  memcpy(new_bytes, new_byte_array->byte_at_addr(0), (size_t)new_bytes_length);
}
instanceKlassHandle JfrUpcalls::load_event_handler_proxy_class(TRAPS) {
  JavaValue result(T_OBJECT);
  JfrJavaArguments call_args(&result, "jdk/jfr/internal/JVMUpcalls",
          "getEventHandlerProxyClass", "()Ljava/lang/Class;", CHECK_NULL);
  JfrJavaSupport::call_static(&call_args, CHECK_NULL);
  assert(result.get_type() == T_OBJECT, "invariant");
  instanceHandle h_java_proxy(THREAD, (instanceOop)result.get_jobject());
  assert(h_java_proxy.not_null(), "invariant");
  return java_lang_Class::as_Klass(h_java_proxy());
}
C:\hotspot-69087d08d473\src\share\vm/jfr/jni/jfrUpcalls.hpp
#ifndef SHARE_VM_JFR_JNI_JFRUPCALLS_HPP
#define SHARE_VM_JFR_JNI_JFRUPCALLS_HPP
#include "jni.h"
#include "jfr/utilities/jfrAllocation.hpp"
#include "utilities/exceptions.hpp"
class JavaThread;
class JfrUpcalls : AllStatic {
 public:
  static void new_bytes_eager_instrumentation(jlong trace_id,
                                              jboolean force_instrumentation,
                                              jclass super,
                                              jint class_data_len,
                                              const unsigned char* class_data,
                                              jint* new_class_data_len,
                                              unsigned char** new_class_data,
                                              TRAPS);
  static void on_retransform(jlong trace_id,
                             jclass class_being_redefined,
                             jint class_data_len,
                             const unsigned char* class_data,
                             jint* new_class_data_len,
                             unsigned char** new_class_data,
                             TRAPS);
  static instanceKlassHandle load_event_handler_proxy_class(TRAPS);
};
#endif // SHARE_VM_JFR_JNI_JFRUPCALLS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/bfsClosure.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/chains/bitset.hpp"
#include "jfr/leakprofiler/chains/bfsClosure.hpp"
#include "jfr/leakprofiler/chains/dfsClosure.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
#include "jfr/leakprofiler/utilities/granularTimer.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/align.hpp"
BFSClosure::BFSClosure(EdgeQueue* edge_queue, EdgeStore* edge_store, BitSet* mark_bits) :
  _edge_queue(edge_queue),
  _edge_store(edge_store),
  _mark_bits(mark_bits),
  _current_parent(NULL),
  _current_frontier_level(0),
  _next_frontier_idx(0),
  _prev_frontier_idx(0),
  _dfs_fallback_idx(0),
  _use_dfs(false) {
}
static void log_frontier_level_summary(size_t level,
                                       size_t high_idx,
                                       size_t low_idx,
                                       size_t edge_size) {
  const size_t nof_edges_in_frontier = high_idx - low_idx;
  if (LogJFR && Verbose) tty->print_cr(
      "BFS front: " SIZE_FORMAT " edges: " SIZE_FORMAT " size: " SIZE_FORMAT " [KB]",
      level,
      nof_edges_in_frontier,
      (nof_edges_in_frontier * edge_size) / K
                        );
}
void BFSClosure::log_completed_frontier() const {
  log_frontier_level_summary(_current_frontier_level,
                             _next_frontier_idx,
                             _prev_frontier_idx,
                             _edge_queue->sizeof_edge());
}
void BFSClosure::log_dfs_fallback() const {
  const size_t edge_size = _edge_queue->sizeof_edge();
  log_frontier_level_summary(_current_frontier_level,
                             _next_frontier_idx,
                             _prev_frontier_idx,
                             edge_size);
  log_frontier_level_summary(_current_frontier_level + 1,
                             _edge_queue->bottom(),
                             _next_frontier_idx,
                             edge_size);
  if (LogJFR && Verbose) tty->print_cr(
      "BFS front: " SIZE_FORMAT " filled edge queue at edge: " SIZE_FORMAT,
      _current_frontier_level,
      _dfs_fallback_idx
                        );
  const size_t nof_dfs_completed_edges = _edge_queue->bottom() - _dfs_fallback_idx;
  if (LogJFR && Verbose) tty->print_cr(
      "DFS to complete " SIZE_FORMAT " edges size: " SIZE_FORMAT " [KB]",
      nof_dfs_completed_edges,
      (nof_dfs_completed_edges * edge_size) / K
                        );
}
void BFSClosure::process() {
  process_root_set();
  process_queue();
}
void BFSClosure::process_root_set() {
  for (size_t idx = _edge_queue->bottom(); idx < _edge_queue->top(); ++idx) {
    const Edge* edge = _edge_queue->element_at(idx);
    assert(edge->parent() == NULL, "invariant");
    process(edge->reference(), edge->pointee());
  }
}
void BFSClosure::process(const oop* reference, const oop pointee) {
  closure_impl(reference, pointee);
}
void BFSClosure::closure_impl(const oop* reference, const oop pointee) {
  assert(reference != NULL, "invariant");
  assert(UnifiedOop::dereference(reference) == pointee, "invariant");
  if (GranularTimer::is_finished()) {
     return;
  }
  if (_use_dfs) {
    assert(_current_parent != NULL, "invariant");
    DFSClosure::find_leaks_from_edge(_edge_store, _mark_bits, _current_parent);
    return;
  }
  if (!_mark_bits->is_marked(pointee)) {
    _mark_bits->mark_obj(pointee);
    if (NULL == pointee->mark()) {
      add_chain(reference, pointee);
    }
    if (_current_parent != NULL) {
      _edge_queue->add(_current_parent, reference);
    }
    if (_edge_queue->is_full()) {
      dfs_fallback();
    }
  }
}
void BFSClosure::add_chain(const oop* reference, const oop pointee) {
  assert(pointee != NULL, "invariant");
  assert(NULL == pointee->mark(), "invariant");
  Edge leak_edge(_current_parent, reference);
  _edge_store->put_chain(&leak_edge, _current_parent == NULL ? 1 : _current_frontier_level + 2);
}
void BFSClosure::dfs_fallback() {
  assert(_edge_queue->is_full(), "invariant");
  _use_dfs = true;
  _dfs_fallback_idx = _edge_queue->bottom();
  while (!_edge_queue->is_empty()) {
    const Edge* edge = _edge_queue->remove();
    if (edge->pointee() != NULL) {
      DFSClosure::find_leaks_from_edge(_edge_store, _mark_bits, edge);
    }
  }
}
void BFSClosure::process_queue() {
  assert(_current_frontier_level == 0, "invariant");
  assert(_next_frontier_idx == 0, "invariant");
  assert(_prev_frontier_idx == 0, "invariant");
  _next_frontier_idx = _edge_queue->top();
  while (!is_complete()) {
    iterate(_edge_queue->remove()); // edge_queue.remove() increments bottom
  }
}
void BFSClosure::step_frontier() const {
  log_completed_frontier();
  ++_current_frontier_level;
  _prev_frontier_idx = _next_frontier_idx;
  _next_frontier_idx = _edge_queue->top();
}
bool BFSClosure::is_complete() const {
  if (_edge_queue->bottom() < _next_frontier_idx) {
    return false;
  }
  if (_edge_queue->bottom() > _next_frontier_idx) {
    assert(_dfs_fallback_idx >= _prev_frontier_idx, "invariant");
    assert(_dfs_fallback_idx < _next_frontier_idx, "invariant");
    log_dfs_fallback();
    return true;
  }
  assert(_edge_queue->bottom() == _next_frontier_idx, "invariant");
  if (_edge_queue->is_empty()) {
    return true;
  }
  step_frontier();
  return false;
}
void BFSClosure::iterate(const Edge* parent) {
  assert(parent != NULL, "invariant");
  const oop pointee = parent->pointee();
  assert(pointee != NULL, "invariant");
  _current_parent = parent;
  pointee->oop_iterate(this);
}
void BFSClosure::do_oop(oop* ref) {
  assert(ref != NULL, "invariant");
  assert(is_aligned(ref, HeapWordSize), "invariant");
  const oop pointee = *ref;
  if (pointee != NULL) {
    closure_impl(ref, pointee);
  }
}
void BFSClosure::do_oop(narrowOop* ref) {
  assert(ref != NULL, "invariant");
  assert(is_aligned(ref, sizeof(narrowOop)), "invariant");
  const oop pointee = oopDesc::load_decode_heap_oop(ref);
  if (pointee != NULL) {
    closure_impl(UnifiedOop::encode(ref), pointee);
  }
}
void BFSClosure::do_root(const oop* ref) {
  assert(ref != NULL, "invariant");
  if (!_edge_queue->is_full()) {
    _edge_queue->add(NULL, ref);
  }
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/bfsClosure.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_BFSCLOSURE_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_BFSCLOSURE_HPP
#include "memory/iterator.hpp"
class BitSet;
class Edge;
class EdgeStore;
class EdgeQueue;
class BFSClosure : public ExtendedOopClosure { // XXX BasicOopIterateClosure
 private:
  EdgeQueue* _edge_queue;
  EdgeStore* _edge_store;
  BitSet* _mark_bits;
  const Edge* _current_parent;
  mutable size_t _current_frontier_level;
  mutable size_t _next_frontier_idx;
  mutable size_t _prev_frontier_idx;
  size_t _dfs_fallback_idx;
  bool _use_dfs;
  void log_completed_frontier() const;
  void log_dfs_fallback() const;
  bool is_complete() const;
  void step_frontier() const;
  void closure_impl(const oop* reference, const oop pointee);
  void add_chain(const oop* reference, const oop pointee);
  void dfs_fallback();
  void iterate(const Edge* parent);
  void process(const oop* reference, const oop pointee);
  void process_root_set();
  void process_queue();
 public:
  BFSClosure(EdgeQueue* edge_queue, EdgeStore* edge_store, BitSet* mark_bits);
  void process();
  void do_root(const oop* ref);
  virtual void do_oop(oop* ref);
  virtual void do_oop(narrowOop* ref);
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_BFSCLOSURE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/bitset.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/chains/bitset.hpp"
#include "jfr/recorder/storage/jfrVirtualMemory.hpp"
#include "memory/memRegion.hpp"
BitSet::BitSet(const MemRegion& covered_region) :
  _vmm(NULL),
  _region_start(covered_region.start()),
  _region_size(covered_region.word_size()) {
}
BitSet::~BitSet() {
  delete _vmm;
}
bool BitSet::initialize() {
  assert(_vmm == NULL, "invariant");
  _vmm = new JfrVirtualMemory();
  if (_vmm == NULL) {
    return false;
  }
  const BitMap::idx_t bits = _region_size >> LogMinObjAlignment;
  const size_t words = bits / BitsPerWord;
  const size_t raw_bytes = words * sizeof(BitMap::idx_t);
  BitMap::bm_word_t* map = (BitMap::bm_word_t*)_vmm->initialize(raw_bytes, raw_bytes);
  if (map == NULL) {
    return false;
  }
  _bits = BitMap(map, bits);
  return true;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/bitset.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_BITSET_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_BITSET_HPP
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/bitMap.inline.hpp"
class JfrVirtualMemory;
class MemRegion;
class BitSet : public CHeapObj<mtTracing> {
 private:
  JfrVirtualMemory* _vmm;
  const HeapWord* const _region_start;
  BitMap _bits;
  const size_t _region_size;
 public:
  BitSet(const MemRegion& covered_region);
  ~BitSet();
  bool initialize();
  BitMap::idx_t mark_obj(const HeapWord* addr) {
    const BitMap::idx_t bit = addr_to_bit(addr);
    _bits.set_bit(bit);
    return bit;
  }
  BitMap::idx_t mark_obj(oop obj) {
    return mark_obj((HeapWord*)obj);
  }
  bool is_marked(const HeapWord* addr) const {
    return is_marked(addr_to_bit(addr));
  }
  bool is_marked(oop obj) const {
    return is_marked((HeapWord*)obj);
  }
  BitMap::idx_t size() const {
    return _bits.size();
  }
  BitMap::idx_t addr_to_bit(const HeapWord* addr) const {
    return pointer_delta(addr, _region_start) >> LogMinObjAlignment;
  }
  bool is_marked(const BitMap::idx_t bit) const {
    return _bits.at(bit);
  }
};
#endif  // SHARE_VM_JFR_LEAKPROFILER_CHAINS_BITSET_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/dfsClosure.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/chains/bitset.hpp"
#include "jfr/leakprofiler/chains/dfsClosure.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
#include "jfr/leakprofiler/utilities/granularTimer.hpp"
#include "jfr/leakprofiler/utilities/rootType.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/align.hpp"
static const size_t max_dfs_depth = 5000;
EdgeStore* DFSClosure::_edge_store = NULL;
BitSet* DFSClosure::_mark_bits = NULL;
const Edge* DFSClosure::_start_edge = NULL;
size_t DFSClosure::_max_depth = max_dfs_depth;
bool DFSClosure::_ignore_root_set = false;
DFSClosure::DFSClosure() :
  _parent(NULL),
  _reference(NULL),
  _depth(0) {
}
DFSClosure::DFSClosure(DFSClosure* parent, size_t depth) :
  _parent(parent),
  _reference(NULL),
  _depth(depth) {
}
void DFSClosure::find_leaks_from_edge(EdgeStore* edge_store,
                                      BitSet* mark_bits,
                                      const Edge* start_edge) {
  assert(edge_store != NULL, "invariant");
  assert(mark_bits != NULL," invariant");
  assert(start_edge != NULL, "invariant");
  _edge_store = edge_store;
  _mark_bits = mark_bits;
  _start_edge = start_edge;
  _ignore_root_set = false;
  assert(_max_depth == max_dfs_depth, "invariant");
  DFSClosure dfs;
  start_edge->pointee()->oop_iterate(&dfs);
}
void DFSClosure::find_leaks_from_root_set(EdgeStore* edge_store,
                                          BitSet* mark_bits) {
  assert(edge_store != NULL, "invariant");
  assert(mark_bits != NULL, "invariant");
  _edge_store = edge_store;
  _mark_bits = mark_bits;
  _start_edge = NULL;
  _max_depth = 1;
  _ignore_root_set = false;
  DFSClosure dfs;
  RootSetClosure<DFSClosure> rs(&dfs);
  rs.process();
  _max_depth = max_dfs_depth;
  _ignore_root_set = true;
  assert(_start_edge == NULL, "invariant");
  rs.process();
}
void DFSClosure::closure_impl(const oop* reference, const oop pointee) {
  assert(pointee != NULL, "invariant");
  assert(reference != NULL, "invariant");
  if (GranularTimer::is_finished()) {
     return;
  }
  if (_depth == 0 && _ignore_root_set) {
    assert(_mark_bits->is_marked(pointee), "invariant");
  } else {
    if (_mark_bits->is_marked(pointee)) {
      return;
    }
  }
  _reference = reference;
  _mark_bits->mark_obj(pointee);
  assert(_mark_bits->is_marked(pointee), "invariant");
  if (NULL == pointee->mark()) {
    add_chain();
  }
  assert(_max_depth >= 1, "invariant");
  if (_depth < _max_depth - 1) {
    DFSClosure next_level(this, _depth + 1);
    pointee->oop_iterate(&next_level);
  }
}
void DFSClosure::add_chain() {
  const size_t array_length = _depth + 2;
  ResourceMark rm;
  Edge* const chain = NEW_RESOURCE_ARRAY(Edge, array_length);
  size_t idx = 0;
  const DFSClosure* c = this;
  while (c != NULL) {
    const size_t next = idx + 1;
    chain[idx++] = Edge(&chain[next], c->reference());
    c = c->parent();
  }
  assert(_depth + 1 == idx, "invariant");
  assert(array_length == idx + 1, "invariant");
  if (_start_edge != NULL) {
    chain[idx++] = *_start_edge;
  } else {
    chain[idx - 1] = Edge(NULL, chain[idx - 1].reference());
  }
  _edge_store->put_chain(chain, idx + (_start_edge != NULL ? _start_edge->distance_to_root() : 0));
}
void DFSClosure::do_oop(oop* ref) {
  assert(ref != NULL, "invariant");
  assert(is_aligned(ref, HeapWordSize), "invariant");
  const oop pointee = *ref;
  if (pointee != NULL) {
    closure_impl(ref, pointee);
  }
}
void DFSClosure::do_oop(narrowOop* ref) {
  assert(ref != NULL, "invariant");
  assert(is_aligned(ref, sizeof(narrowOop)), "invariant");
  const oop pointee = oopDesc::load_decode_heap_oop(ref);
  if (pointee != NULL) {
    closure_impl(UnifiedOop::encode(ref), pointee);
  }
}
void DFSClosure::do_root(const oop* ref) {
  assert(ref != NULL, "invariant");
  const oop pointee = UnifiedOop::dereference(ref);
  assert(pointee != NULL, "invariant");
  closure_impl(ref, pointee);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/dfsClosure.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_DFSCLOSURE_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_DFSCLOSURE_HPP
#include "memory/iterator.hpp"
class BitSet;
class Edge;
class EdgeStore;
class EdgeQueue;
class DFSClosure : public ExtendedOopClosure { // XXX BasicOopIterateClosure
 private:
  static EdgeStore* _edge_store;
  static BitSet*    _mark_bits;
  static const Edge*_start_edge;
  static size_t _max_depth;
  static bool _ignore_root_set;
  DFSClosure* _parent;
  const oop* _reference;
  size_t _depth;
  void add_chain();
  void closure_impl(const oop* reference, const oop pointee);
  DFSClosure* parent() const { return _parent; }
  const oop* reference() const { return _reference; }
  DFSClosure(DFSClosure* parent, size_t depth);
  DFSClosure();
 public:
  static void find_leaks_from_edge(EdgeStore* edge_store, BitSet* mark_bits, const Edge* start_edge);
  static void find_leaks_from_root_set(EdgeStore* edge_store, BitSet* mark_bits);
  void do_root(const oop* ref);
  virtual void do_oop(oop* ref);
  virtual void do_oop(narrowOop* ref);
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_DFSCLOSURE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edge.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
Edge::Edge() : _parent(NULL), _reference(NULL) {}
Edge::Edge(const Edge* parent, const oop* reference) : _parent(parent),
                                                       _reference(reference) {}
const oop Edge::pointee() const {
  return UnifiedOop::dereference(_reference);
}
const oop Edge::reference_owner() const {
  return is_root() ? (oop)NULL : UnifiedOop::dereference(_parent->reference());
}
static const Klass* resolve_klass(const oop obj) {
  assert(obj != NULL, "invariant");
  return java_lang_Class::is_instance(obj) ?
    java_lang_Class::as_Klass(obj) : obj->klass();
}
const Klass* Edge::pointee_klass() const {
  return resolve_klass(pointee());
}
const Klass* Edge::reference_owner_klass() const {
  const oop ref_owner = reference_owner();
  return ref_owner != NULL ? resolve_klass(ref_owner) : NULL;
}
size_t Edge::distance_to_root() const {
  size_t depth = 0;
  const Edge* current = _parent;
  while (current != NULL) {
    depth++;
    current = current->parent();
  }
  return depth;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edge.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGE_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGE_HPP
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
class Edge {
 protected:
  const Edge* _parent;
  const oop* _reference;
 public:
  Edge();
  Edge(const Edge* parent, const oop* reference);
  const oop* reference() const {
    return _reference;
  }
  const Edge* parent() const {
    return _parent;
  }
  bool is_root() const {
    return _parent == NULL;
  }
  const oop pointee() const;
  const Klass* pointee_klass() const;
  const oop reference_owner() const;
  const Klass* reference_owner_klass() const;
  size_t distance_to_root() const;
  void* operator new (size_t sz, void* here) {
    return here;
  }
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeQueue.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
#include "jfr/recorder/storage/jfrVirtualMemory.hpp"
EdgeQueue::EdgeQueue(size_t reservation_size_bytes, size_t commit_block_size_bytes) :
  _vmm(NULL),
  _reservation_size_bytes(reservation_size_bytes),
  _commit_block_size_bytes(commit_block_size_bytes),
  _top_index(0),
  _bottom_index(0) {
}
bool EdgeQueue::initialize() {
  assert(_reservation_size_bytes >= _commit_block_size_bytes, "invariant");
  assert(_vmm == NULL, "invariant");
  _vmm = new JfrVirtualMemory();
  return _vmm != NULL && _vmm->initialize(_reservation_size_bytes, _commit_block_size_bytes, sizeof(Edge));
}
EdgeQueue::~EdgeQueue() {
  delete _vmm;
}
void EdgeQueue::add(const Edge* parent, const oop* ref) {
  assert(ref != NULL, "Null objects not allowed in EdgeQueue");
  assert(!is_full(), "EdgeQueue is full. Check is_full before adding another Edge");
  assert(!_vmm->is_full(), "invariant");
  void* const allocation = _vmm->new_datum();
  assert(allocation != NULL, "invariant");
  new (allocation)Edge(parent, ref);
  _top_index++;
  assert(_vmm->count() == _top_index, "invariant");
}
size_t EdgeQueue::top() const {
  return _top_index;
}
size_t EdgeQueue::bottom() const {
  return EdgeQueue::_bottom_index;
}
bool EdgeQueue::is_empty() const {
  return _top_index == _bottom_index;
}
bool EdgeQueue::is_full() const {
  return _vmm->is_full();
}
const Edge* EdgeQueue::remove() const {
  assert(!is_empty(), "EdgeQueue is empty. Check if empty before removing Edge");
  assert(!_vmm->is_empty(), "invariant");
  return (const Edge*)_vmm->get(_bottom_index++);
}
const Edge* EdgeQueue::element_at(size_t index) const {
  assert(index >= _bottom_index, "invariant");
  assert(index <_top_index, "invariant");
  return (Edge*)_vmm->get(index);
}
size_t EdgeQueue::reserved_size() const {
  assert(_vmm != NULL, "invariant");
  return _vmm->reserved_size();
}
size_t EdgeQueue::live_set() const {
  assert(_vmm != NULL, "invariant");
  return _vmm->live_set();
}
size_t EdgeQueue::sizeof_edge() const {
  assert(_vmm != NULL, "invariant");
  return _vmm->aligned_datum_size_bytes();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeQueue.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGEQUEUE_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGEQUEUE_HPP
#include "memory/allocation.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
class JfrVirtualMemory;
class EdgeQueue : public CHeapObj<mtTracing> {
 private:
  JfrVirtualMemory* _vmm;
  const size_t _reservation_size_bytes;
  const size_t _commit_block_size_bytes;
  mutable size_t _top_index;
  mutable size_t _bottom_index;
 public:
  EdgeQueue(size_t reservation_size_bytes, size_t commit_block_size_bytes);
  ~EdgeQueue();
  bool initialize();
  void add(const Edge* parent, const oop* ref);
  const Edge* remove() const;
  const Edge* element_at(size_t index) const;
  size_t top() const;
  size_t bottom() const;
  bool is_empty() const;
  bool is_full() const;
  size_t reserved_size() const;
  size_t live_set() const;
  size_t sizeof_edge() const; // with alignments
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_EDGEQUEUE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeStore.cpp
#include "precompiled.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/edgeUtils.hpp"
#include "oops/oop.inline.hpp"
StoredEdge::StoredEdge() : Edge() {}
StoredEdge::StoredEdge(const Edge* parent, const oop* reference) : Edge(parent, reference), _gc_root_id(0), _skip_length(0) {}
StoredEdge::StoredEdge(const Edge& edge) : Edge(edge), _gc_root_id(0), _skip_length(0) {}
StoredEdge::StoredEdge(const StoredEdge& edge) : Edge(edge), _gc_root_id(edge._gc_root_id), _skip_length(edge._skip_length) {}
void StoredEdge::operator=(const StoredEdge& edge) {
  Edge::operator=(edge);
  _gc_root_id = edge._gc_root_id;
  _skip_length = edge._skip_length;
}
traceid EdgeStore::_edge_id_counter = 0;
EdgeStore::EdgeStore() : _edges(NULL) {
  _edges = new EdgeHashTable(this);
}
EdgeStore::~EdgeStore() {
  assert(_edges != NULL, "invariant");
  delete _edges;
}
bool EdgeStore::is_empty() const {
  return !_edges->has_entries();
}
void EdgeStore::assign_id(EdgeEntry* entry) {
  assert(entry != NULL, "invariant");
  assert(entry->id() == 0, "invariant");
  entry->set_id(++_edge_id_counter);
}
bool EdgeStore::equals(const Edge& query, uintptr_t hash, const EdgeEntry* entry) {
  assert(entry != NULL, "invariant");
  assert(entry->hash() == hash, "invariant");
  return true;
}
#ifdef ASSERT
bool EdgeStore::contains(const oop* reference) const {
  return get(reference) != NULL;
}
#endif
StoredEdge* EdgeStore::get(const oop* reference) const {
  assert(reference != NULL, "invariant");
  const StoredEdge e(NULL, reference);
  EdgeEntry* const entry = _edges->lookup_only(e, (uintptr_t)reference);
  return entry != NULL ? entry->literal_addr() : NULL;
}
StoredEdge* EdgeStore::put(const oop* reference) {
  assert(reference != NULL, "invariant");
  const StoredEdge e(NULL, reference);
  assert(NULL == _edges->lookup_only(e, (uintptr_t)reference), "invariant");
  EdgeEntry& entry = _edges->put(e, (uintptr_t)reference);
  return entry.literal_addr();
}
traceid EdgeStore::get_id(const Edge* edge) const {
  assert(edge != NULL, "invariant");
  EdgeEntry* const entry = _edges->lookup_only(*edge, (uintptr_t)edge->reference());
  assert(entry != NULL, "invariant");
  return entry->id();
}
traceid EdgeStore::gc_root_id(const Edge* edge) const {
  assert(edge != NULL, "invariant");
  const traceid gc_root_id = static_cast<const StoredEdge*>(edge)->gc_root_id();
  if (gc_root_id != 0) {
    return gc_root_id;
  }
  assert(edge != NULL, "invariant");
  const Edge* const root = EdgeUtils::root(*edge);
  assert(root != NULL, "invariant");
  assert(root->parent() == NULL, "invariant");
  return get_id(root);
}
static const Edge* get_skip_ancestor(const Edge** current, size_t distance_to_root, size_t* skip_length) {
  assert(distance_to_root >= EdgeUtils::root_context, "invariant");
  assert(*skip_length == 0, "invariant");
  const Edge* const target = EdgeUtils::ancestor(**current, *skip_length);
  assert(target != NULL, "invariant");
  assert(target->distance_to_root() + 1 == EdgeUtils::root_context, "invariant");
  return target;
}
bool EdgeStore::put_skip_edge(StoredEdge** previous, const Edge** current, size_t distance_to_root) {
  assert(*previous != NULL, "invariant");
  assert((*previous)->parent() == NULL, "invariant");
  assert(*current != NULL, "invariant");
  assert((*current)->distance_to_root() == distance_to_root, "invariant");
  if (distance_to_root < EdgeUtils::root_context) {
    return false;
  }
  size_t skip_length = 0;
  const Edge* const skip_ancestor = get_skip_ancestor(current, distance_to_root, &skip_length);
  assert(skip_ancestor != NULL, "invariant");
  (*previous)->set_skip_length(skip_length);
  StoredEdge* stored_target = get(skip_ancestor->reference());
  if (stored_target != NULL) {
    (*previous)->set_parent(stored_target);
    return true;
  }
  assert(stored_target == NULL, "invariant");
  stored_target = put(skip_ancestor->reference());
  assert(stored_target != NULL, "invariant");
  (*previous)->set_parent(stored_target);
  return false;
}
static void link_edge(const StoredEdge* current_stored, StoredEdge** previous) {
  assert(current_stored != NULL, "invariant");
  assert(*previous != NULL, "invariant");
  assert((*previous)->parent() == NULL, "invariant");
  (*previous)->set_parent(current_stored);
}
static const StoredEdge* find_closest_skip_edge(const StoredEdge* edge, size_t* distance) {
  assert(edge != NULL, "invariant");
  assert(distance != NULL, "invariant");
  const StoredEdge* current = edge;
  while (current != NULL && !current->is_skip_edge()) {
    ++(*distance);
    current = current->parent();
  }
  return current;
}
void EdgeStore::link_with_existing_chain(const StoredEdge* current_stored, StoredEdge** previous, size_t previous_length) {
  assert(current_stored != NULL, "invariant");
  assert((*previous)->parent() == NULL, "invariant");
  size_t distance_to_skip_edge; // including the skip edge itself
  const StoredEdge* const closest_skip_edge = find_closest_skip_edge(current_stored, &distance_to_skip_edge);
  if (closest_skip_edge == NULL) {
    if (distance_to_skip_edge + previous_length <= EdgeUtils::max_ref_chain_depth) {
      link_edge(current_stored, previous);
      return;
    }
    assert(current_stored->distance_to_root() == distance_to_skip_edge - 2, "invariant");
    put_skip_edge(previous, reinterpret_cast<const Edge**>(&current_stored), distance_to_skip_edge - 2);
    return;
  }
  assert(closest_skip_edge->is_skip_edge(), "invariant");
  if (distance_to_skip_edge + previous_length <= EdgeUtils::leak_context) {
    link_edge(current_stored, previous);
    return;
  }
  (*previous)->set_skip_length(distance_to_skip_edge + closest_skip_edge->skip_length());
  (*previous)->set_parent(closest_skip_edge->parent());
}
StoredEdge* EdgeStore::link_new_edge(StoredEdge** previous, const Edge** current) {
  assert(*previous != NULL, "invariant");
  assert((*previous)->parent() == NULL, "invariant");
  assert(*current != NULL, "invariant");
  assert(!contains((*current)->reference()), "invariant");
  StoredEdge* const stored_edge = put((*current)->reference());
  assert(stored_edge != NULL, "invariant");
  link_edge(stored_edge, previous);
  return stored_edge;
}
bool EdgeStore::put_edges(StoredEdge** previous, const Edge** current, size_t limit) {
  assert(*previous != NULL, "invariant");
  assert(*current != NULL, "invariant");
  size_t depth = 1;
  while (*current != NULL && depth < limit) {
    StoredEdge* stored_edge = get((*current)->reference());
    if (stored_edge != NULL) {
      link_with_existing_chain(stored_edge, previous, depth);
      return true;
    }
    stored_edge = link_new_edge(previous, current);
    assert((*previous)->parent() != NULL, "invariant");
    ++depth;
  }
  return NULL == *current;
}
StoredEdge* EdgeStore::associate_leak_context_with_candidate(const Edge* edge) {
  assert(edge != NULL, "invariant");
  assert(!contains(edge->reference()), "invariant");
  StoredEdge* const leak_context_edge = put(edge->reference());
  oop sample_object = edge->pointee();
  assert(sample_object != NULL, "invariant");
  assert(NULL == sample_object->mark(), "invariant");
  sample_object->set_mark(markOop(leak_context_edge));
  return leak_context_edge;
}
void EdgeStore::put_chain(const Edge* chain, size_t length) {
  assert(chain != NULL, "invariant");
  assert(chain->distance_to_root() + 1 == length, "invariant");
  StoredEdge* const leak_context_edge = associate_leak_context_with_candidate(chain);
  assert(leak_context_edge != NULL, "invariant");
  assert(leak_context_edge->parent() == NULL, "invariant");
  if (1 == length) {
    return;
  }
  const Edge* current = chain->parent();
  assert(current != NULL, "invariant");
  StoredEdge* previous = leak_context_edge;
  if (put_edges(&previous, &current, EdgeUtils::leak_context)) {
    assert(previous != NULL, "invariant");
    put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
    return;
  }
  const size_t distance_to_root = length > EdgeUtils::leak_context ? length - 1 - EdgeUtils::leak_context : length - 1;
  assert(current->distance_to_root() == distance_to_root, "invariant");
  if (put_skip_edge(&previous, &current, distance_to_root)) {
    assert(previous != NULL, "invariant");
    assert(previous->is_skip_edge(), "invariant");
    assert(previous->parent() != NULL, "invariant");
    put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous->parent()));
    return;
  }
  assert(current->distance_to_root() < EdgeUtils::root_context, "invariant");
  put_edges(&previous, &current, EdgeUtils::root_context);
  assert(previous != NULL, "invariant");
  put_chain_epilogue(leak_context_edge, EdgeUtils::root(*previous));
}
void EdgeStore::put_chain_epilogue(StoredEdge* leak_context_edge, const Edge* root) const {
  assert(leak_context_edge != NULL, "invariant");
  assert(root != NULL, "invariant");
  store_gc_root_id_in_leak_context_edge(leak_context_edge, root);
  assert(leak_context_edge->distance_to_root() + 1 <= EdgeUtils::max_ref_chain_depth, "invariant");
}
void EdgeStore::store_gc_root_id_in_leak_context_edge(StoredEdge* leak_context_edge, const Edge* root) const {
  assert(leak_context_edge != NULL, "invariant");
  assert(leak_context_edge->gc_root_id() == 0, "invariant");
  assert(root != NULL, "invariant");
  assert(root->parent() == NULL, "invariant");
  assert(root->distance_to_root() == 0, "invariant");
  const StoredEdge* const stored_root = static_cast<const StoredEdge*>(root);
  traceid root_id = stored_root->gc_root_id();
  if (root_id == 0) {
    root_id = get_id(root);
    stored_root->set_gc_root_id(root_id);
  }
  assert(root_id != 0, "invariant");
  leak_context_edge->set_gc_root_id(root_id);
  assert(leak_context_edge->gc_root_id() == stored_root->gc_root_id(), "invariant");
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeStore.hpp
#ifndef SHARE_VM_LEAKPROFILER_CHAINS_EDGESTORE_HPP
#define SHARE_VM_LEAKPROFILER_CHAINS_EDGESTORE_HPP
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/utilities/jfrHashtable.hpp"
#include "memory/allocation.hpp"
typedef u8 traceid;
class StoredEdge : public Edge {
 private:
  mutable traceid _gc_root_id;
  size_t _skip_length;
 public:
  StoredEdge();
  StoredEdge(const Edge* parent, const oop* reference);
  StoredEdge(const Edge& edge);
  StoredEdge(const StoredEdge& edge);
  void operator=(const StoredEdge& edge);
  traceid gc_root_id() const { return _gc_root_id; }
  void set_gc_root_id(traceid root_id) const { _gc_root_id = root_id; }
  bool is_skip_edge() const { return _skip_length != 0; }
  size_t skip_length() const { return _skip_length; }
  void set_skip_length(size_t length) { _skip_length = length; }
  void set_parent(const Edge* edge) { this->_parent = edge; }
  StoredEdge* parent() const {
    return const_cast<StoredEdge*>(static_cast<const StoredEdge*>(Edge::parent()));
  }
};
class EdgeStore : public CHeapObj<mtTracing> {
  typedef HashTableHost<StoredEdge, traceid, Entry, EdgeStore> EdgeHashTable;
  typedef EdgeHashTable::HashEntry EdgeEntry;
  template <typename,
            typename,
            template<typename, typename> class,
            typename,
            size_t>
  friend class HashTableHost;
  friend class EventEmitter;
  friend class ObjectSampleWriter;
  friend class ObjectSampleCheckpoint;
 private:
  static traceid _edge_id_counter;
  EdgeHashTable* _edges;
  void assign_id(EdgeEntry* entry);
  bool equals(const Edge& query, uintptr_t hash, const EdgeEntry* entry);
  StoredEdge* get(const oop* reference) const;
  StoredEdge* put(const oop* reference);
  traceid gc_root_id(const Edge* edge) const;
  bool put_edges(StoredEdge** previous, const Edge** current, size_t length);
  bool put_skip_edge(StoredEdge** previous, const Edge** current, size_t distance_to_root);
  void put_chain_epilogue(StoredEdge* leak_context_edge, const Edge* root) const;
  StoredEdge* associate_leak_context_with_candidate(const Edge* edge);
  void store_gc_root_id_in_leak_context_edge(StoredEdge* leak_context_edge, const Edge* root) const;
  StoredEdge* link_new_edge(StoredEdge** previous, const Edge** current);
  void link_with_existing_chain(const StoredEdge* current_stored, StoredEdge** previous, size_t previous_length);
  template <typename T>
  void iterate(T& functor) const { _edges->iterate_value<T>(functor); }
  DEBUG_ONLY(bool contains(const oop* reference) const;)
 public:
  EdgeStore();
  ~EdgeStore();
  bool is_empty() const;
  traceid get_id(const Edge* edge) const;
  void put_chain(const Edge* chain, size_t length);
};
#endif // SHARE_VM_LEAKPROFILER_CHAINS_EDGESTORE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeUtils.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/edgeUtils.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/handles.inline.hpp"
bool EdgeUtils::is_leak_edge(const Edge& edge) {
  return (const Edge*)edge.pointee()->mark() == &edge;
}
static int field_offset(const StoredEdge& edge) {
  assert(!edge.is_root(), "invariant");
  const oop ref_owner = edge.reference_owner();
  assert(ref_owner != NULL, "invariant");
  const oop* reference = UnifiedOop::decode(edge.reference());
  assert(reference != NULL, "invariant");
  assert(!UnifiedOop::is_narrow(reference), "invariant");
  assert(!ref_owner->is_array(), "invariant");
  assert(ref_owner->is_instance(), "invariant");
  const int offset = (int)pointer_delta(reference, ref_owner, sizeof(char));
  assert(offset < (ref_owner->size() * HeapWordSize), "invariant");
  return offset;
}
static const InstanceKlass* field_type(const StoredEdge& edge) {
  assert(!edge.is_root() || !EdgeUtils::is_array_element(edge), "invariant");
  return (const InstanceKlass*)edge.reference_owner_klass();
}
const Symbol* EdgeUtils::field_name_symbol(const Edge& edge) {
  assert(!edge.is_root(), "invariant");
  assert(!is_array_element(edge), "invariant");
  const int offset = field_offset(edge);
  const InstanceKlass* ik = field_type(edge);
  while (ik != NULL) {
    JavaFieldStream jfs(ik);
    while (!jfs.done()) {
      if (offset == jfs.offset()) {
        return jfs.name();
      }
      jfs.next();
    }
    ik = (InstanceKlass*)ik->super();
  }
  return NULL;
}
jshort EdgeUtils::field_modifiers(const Edge& edge) {
  const int offset = field_offset(edge);
  const InstanceKlass* ik = field_type(edge);
  while (ik != NULL) {
    JavaFieldStream jfs(ik);
    while (!jfs.done()) {
      if (offset == jfs.offset()) {
        return jfs.access_flags().as_short();
      }
      jfs.next();
    }
    ik = (InstanceKlass*)ik->super();
  }
  return 0;
}
bool EdgeUtils::is_array_element(const Edge& edge) {
  assert(!edge.is_root(), "invariant");
  const oop ref_owner = edge.reference_owner();
  assert(ref_owner != NULL, "invariant");
  return ref_owner->is_objArray();
}
static int array_offset(const Edge& edge) {
  assert(!edge.is_root(), "invariant");
  const oop ref_owner = edge.reference_owner();
  assert(ref_owner != NULL, "invariant");
  const oop* reference = UnifiedOop::decode(edge.reference());
  assert(reference != NULL, "invariant");
  assert(!UnifiedOop::is_narrow(reference), "invariant");
  assert(ref_owner->is_array(), "invariant");
  const objArrayOop ref_owner_array = static_cast<const objArrayOop>(ref_owner);
  const int offset = (int)pointer_delta(reference, ref_owner_array->base(), heapOopSize);
  assert(offset >= 0 && offset < ref_owner_array->length(), "invariant");
  return offset;
}
int EdgeUtils::array_index(const Edge& edge) {
  return is_array_element(edge) ? array_offset(edge) : 0;
}
int EdgeUtils::array_size(const Edge& edge) {
  if (is_array_element(edge)) {
    const oop ref_owner = edge.reference_owner();
    assert(ref_owner != NULL, "invariant");
    assert(ref_owner->is_objArray(), "invariant");
    return ((objArrayOop)(ref_owner))->length();
  }
  return 0;
}
const Edge* EdgeUtils::root(const Edge& edge) {
  const Edge* current = &edge;
  const Edge* parent = current->parent();
  while (parent != NULL) {
    current = parent;
    parent = current->parent();
  }
  assert(current != NULL, "invariant");
  return current;
}
const Edge* EdgeUtils::ancestor(const Edge& edge, size_t distance) {
  const Edge* current = &edge;
  const Edge* parent = current->parent();
  size_t seek = 0;
  while (parent != NULL && seek != distance) {
    seek++;
    current = parent;
    parent = parent->parent();
  }
  return current;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/edgeUtils.hpp
#ifndef SHARE_VM_LEAKPROFILER_CHAINS_EDGEUTILS_HPP
#define SHARE_VM_LEAKPROFILER_CHAINS_EDGEUTILS_HPP
#include "memory/allocation.hpp"
class Edge;
class Symbol;
class EdgeUtils : public AllStatic {
 public:
  static const size_t leak_context = 100;
  static const size_t root_context = 100;
  static const size_t max_ref_chain_depth = leak_context + root_context;
  static bool is_leak_edge(const Edge& edge);
  static const Edge* root(const Edge& edge);
  static const Edge* ancestor(const Edge& edge, size_t distance);
  static bool is_array_element(const Edge& edge);
  static int array_index(const Edge& edge);
  static int array_size(const Edge& edge);
  static const Symbol* field_name_symbol(const Edge& edge);
  static jshort field_modifiers(const Edge& edge);
};
#endif // SHARE_VM_LEAKPROFILER_CHAINS_EDGEUTILS_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/objectSampleMarker.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_OBJECTSAMPLEMARKER_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_OBJECTSAMPLEMARKER_HPP
#include "memory/allocation.hpp"
#include "oops/markOop.hpp"
#include "utilities/growableArray.hpp"
class ObjectSampleMarker : public StackObj {
 private:
  class ObjectSampleMarkOop : public ResourceObj {
    friend class ObjectSampleMarker;
   private:
    oop _obj;
    markOop _mark_oop;
    ObjectSampleMarkOop(const oop obj,
                        const markOop mark_oop) : _obj(obj),
                                                  _mark_oop(mark_oop) {}
   public:
    ObjectSampleMarkOop() : _obj(NULL), _mark_oop(NULL) {}
  };
  GrowableArray<ObjectSampleMarkOop>* _store;
 public:
  ObjectSampleMarker() :
       _store(new GrowableArray<ObjectSampleMarkOop>(16)) {}
  ~ObjectSampleMarker() {
    assert(_store != NULL, "invariant");
    while (_store->is_nonempty()) {
      ObjectSampleMarkOop sample_oop = _store->pop();
      sample_oop._obj->set_mark(sample_oop._mark_oop);
      assert(sample_oop._obj->mark() == sample_oop._mark_oop, "invariant");
    }
  }
  void mark(oop obj) {
    assert(obj != NULL, "invariant");
    _store->push(ObjectSampleMarkOop(obj, obj->mark()));
    assert(NULL == markOopDesc::INFLATING(), "invariant");
    obj->set_mark(markOopDesc::INFLATING());
    assert(NULL == obj->mark(), "invariant");
  }
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_OBJECTSAMPLEMARKER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/pathToGcRootsOperation.cpp
#include "precompiled.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/leakprofiler/chains/bfsClosure.hpp"
#include "jfr/leakprofiler/chains/bitset.hpp"
#include "jfr/leakprofiler/chains/dfsClosure.hpp"
#include "jfr/leakprofiler/chains/edge.hpp"
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
#include "jfr/leakprofiler/chains/pathToGcRootsOperation.hpp"
#include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/leakprofiler/sampling/objectSample.hpp"
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
#include "jfr/leakprofiler/utilities/granularTimer.hpp"
#include "memory/universe.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/globalDefinitions.hpp"
PathToGcRootsOperation::PathToGcRootsOperation(ObjectSampler* sampler, EdgeStore* edge_store, int64_t cutoff, bool emit_all) :
  _sampler(sampler),_edge_store(edge_store), _cutoff_ticks(cutoff), _emit_all(emit_all) {}
static size_t edge_queue_memory_reservation(const MemRegion& heap_region) {
  const size_t memory_reservation_bytes = MAX2(heap_region.byte_size() / 20, 32*M);
  assert(memory_reservation_bytes >= (size_t)32*M, "invariant");
  return memory_reservation_bytes;
}
static size_t edge_queue_memory_commit_size(size_t memory_reservation_bytes) {
  const size_t memory_commit_block_size_bytes = memory_reservation_bytes / 10;
  assert(memory_commit_block_size_bytes >= (size_t)3*M, "invariant");
  return memory_commit_block_size_bytes;
}
static void log_edge_queue_summary(const EdgeQueue& edge_queue) {
  if (LogJFR && Verbose) tty->print_cr("EdgeQueue reserved size total: " SIZE_FORMAT " [KB]", edge_queue.reserved_size() / K);
  if (LogJFR && Verbose) tty->print_cr("EdgeQueue edges total: " SIZE_FORMAT, edge_queue.top());
  if (LogJFR && Verbose) tty->print_cr("EdgeQueue liveset total: " SIZE_FORMAT " [KB]", edge_queue.live_set() / K);
  if (edge_queue.reserved_size() > 0) {
    if (LogJFR && Verbose) tty->print_cr("EdgeQueue commit reserve ratio: %f\n",
      ((double)edge_queue.live_set() / (double)edge_queue.reserved_size()));
  }
}
void PathToGcRootsOperation::doit() {
  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
  assert(_cutoff_ticks > 0, "invariant");
  const MemRegion heap_region = Universe::heap()->reserved_region();
  BitSet mark_bits(heap_region);
  const size_t edge_queue_reservation_size = edge_queue_memory_reservation(heap_region);
  EdgeQueue edge_queue(edge_queue_reservation_size, edge_queue_memory_commit_size(edge_queue_reservation_size));
  if (!(mark_bits.initialize() && edge_queue.initialize())) {
    if (LogJFR) tty->print_cr("Unable to allocate memory for root chain processing");
    return;
  }
  ObjectSampleMarker marker;
  if (ObjectSampleCheckpoint::mark(_sampler, marker, _emit_all) == 0) {
    return;
  }
  Universe::heap()->ensure_parsability(false);
  BFSClosure bfs(&edge_queue, _edge_store, &mark_bits);
  RootSetClosure<BFSClosure> roots(&bfs);
  GranularTimer::start(_cutoff_ticks, 1000000);
  roots.process();
  if (edge_queue.is_full()) {
    DFSClosure::find_leaks_from_root_set(_edge_store, &mark_bits);
  } else {
    bfs.process();
  }
  GranularTimer::stop();
  log_edge_queue_summary(edge_queue);
  EventEmitter emitter(GranularTimer::start_time(), GranularTimer::end_time());
  emitter.write_events(_sampler, _edge_store, _emit_all);
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/pathToGcRootsOperation.hpp
#ifndef SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
#define SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
#include "jfr/leakprofiler/utilities/vmOperation.hpp"
class EdgeStore;
class ObjectSampler;
class PathToGcRootsOperation : public OldObjectVMOperation {
 private:
  ObjectSampler* _sampler;
  EdgeStore* const _edge_store;
  const int64_t _cutoff_ticks;
  const bool _emit_all;
 public:
  PathToGcRootsOperation(ObjectSampler* sampler, EdgeStore* edge_store, int64_t cutoff, bool emit_all);
  virtual void doit();
};
#endif // SHARE_JFR_LEAKPROFILER_CHAINS_PATHTOGCROOTSOPERATION_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/rootSetClosure.cpp
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/systemDictionary.hpp"
#include "jfr/leakprofiler/chains/bfsClosure.hpp"
#include "jfr/leakprofiler/chains/dfsClosure.hpp"
#include "jfr/leakprofiler/chains/edgeQueue.hpp"
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
#include "jfr/leakprofiler/utilities/saveRestore.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.hpp"
#include "services/management.hpp"
#include "utilities/align.hpp"
template <typename Delegate>
RootSetClosure<Delegate>::RootSetClosure(Delegate* delegate) : _delegate(delegate) {}
template <typename Delegate>
void RootSetClosure<Delegate>::do_oop(oop* ref) {
  assert(ref != NULL, "invariant");
  if (!is_aligned(ref, HeapWordSize)) {
    return;
  }
  assert(is_aligned(ref, HeapWordSize), "invariant");
  if (*ref != NULL) {
    _delegate->do_root(ref);
  }
}
template <typename Delegate>
void RootSetClosure<Delegate>::do_oop(narrowOop* ref) {
  assert(ref != NULL, "invariant");
  assert(is_aligned(ref, sizeof(narrowOop)), "invariant");
  const oop pointee = oopDesc::load_decode_heap_oop(ref);
  if (pointee != NULL) {
    _delegate->do_root(UnifiedOop::encode(ref));
  }
}
class RootSetClosureMarkScope : public MarkingCodeBlobClosure::MarkScope {};
template <typename Delegate>
void RootSetClosure<Delegate>::process() {
  RootSetClosureMarkScope mark_scope;
  CLDToOopClosure cldt_closure(this);
  ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
  CodeBlobToOopClosure blobs(this, false);
  Threads::oops_do(this, NULL, &blobs); // XXX set CLDClosure to NULL
  ObjectSynchronizer::oops_do(this);
  Universe::oops_do(this);
  JNIHandles::oops_do(this);
  JvmtiExport::oops_do(this);
  SystemDictionary::oops_do(this);
  Management::oops_do(this);
  StringTable::oops_do(this);
}
template class RootSetClosure<BFSClosure>;
template class RootSetClosure<DFSClosure>;
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/chains/rootSetClosure.hpp
#ifndef SHARE_VM_JFR_LEAKPROFILER_CHAINS_ROOTSETCLOSURE_HPP
#define SHARE_VM_JFR_LEAKPROFILER_CHAINS_ROOTSETCLOSURE_HPP
#include "memory/iterator.hpp"
template <typename Delegate>
class RootSetClosure: public ExtendedOopClosure { // BasicOopIterateClosure
 private:
  Delegate* const _delegate;
 public:
  RootSetClosure(Delegate* delegate);
  void process();
  virtual void do_oop(oop* reference);
  virtual void do_oop(narrowOop* reference);
};
#endif // SHARE_VM_JFR_LEAKPROFILER_CHAINS_ROOTSETCLOSURE_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/checkpoint/eventEmitter.cpp
#include "precompiled.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/pathToGcRootsOperation.hpp"
#include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/leakprofiler/sampling/objectSample.hpp"
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
#include "memory/resourceArea.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vmThread.hpp"
EventEmitter::EventEmitter(const JfrTicks& start_time, const JfrTicks& end_time) :
  _start_time(start_time),
  _end_time(end_time),
  _thread(Thread::current()),
  _jfr_thread_local(_thread->jfr_thread_local()),
  _thread_id(_thread->jfr_thread_local()->thread_id()) {}
EventEmitter::~EventEmitter() {
  _jfr_thread_local->set_thread_id(_thread_id);
  _jfr_thread_local->clear_cached_stack_trace();
}
void EventEmitter::emit(ObjectSampler* sampler, int64_t cutoff_ticks, bool emit_all) {
  assert(sampler != NULL, "invariant");
  ResourceMark rm;
  EdgeStore edge_store;
  if (cutoff_ticks <= 0) {
    JfrTicks time_stamp = JfrTicks::now();
    EventEmitter emitter(time_stamp, time_stamp);
    emitter.write_events(sampler, &edge_store, emit_all);
    return;
  }
  PathToGcRootsOperation op(sampler, &edge_store, cutoff_ticks, emit_all);
  VMThread::execute(&op);
}
size_t EventEmitter::write_events(ObjectSampler* object_sampler, EdgeStore* edge_store, bool emit_all) {
  assert(_thread == Thread::current(), "invariant");
  assert(_thread->jfr_thread_local() == _jfr_thread_local, "invariant");
  assert(object_sampler != NULL, "invariant");
  assert(edge_store != NULL, "invariant");
  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
  size_t count = 0;
  const ObjectSample* current = object_sampler->first();
  while (current != NULL) {
    ObjectSample* prev = current->prev();
    if (current->is_alive_and_older_than(last_sweep)) {
      write_event(current, edge_store);
      ++count;
    }
    current = prev;
  }
  if (count > 0) {
    ObjectSampleCheckpoint::write(object_sampler, edge_store, emit_all, _thread);
  }
  return count;
}
static int array_size(const oop object) {
  assert(object != NULL, "invariant");
  if (object->is_array()) {
    return arrayOop(object)->length();
  }
  return min_jint;
}
void EventEmitter::write_event(const ObjectSample* sample, EdgeStore* edge_store) {
  assert(sample != NULL, "invariant");
  assert(!sample->is_dead(), "invariant");
  assert(edge_store != NULL, "invariant");
  assert(_jfr_thread_local != NULL, "invariant");
  const oop* object_addr = sample->object_addr();
  traceid gc_root_id = 0;
  const Edge* edge = NULL;
  if (SafepointSynchronize::is_at_safepoint()) {
    edge = (const Edge*)(*object_addr)->mark();
  }
  if (edge == NULL) {
    edge = edge_store->put(object_addr);
  } else {
    gc_root_id = edge_store->gc_root_id(edge);
  }
  assert(edge != NULL, "invariant");
  const traceid object_id = edge_store->get_id(edge);
  assert(object_id != 0, "invariant");
  EventOldObjectSample e(UNTIMED);
  e.set_starttime(_start_time);
  e.set_endtime(_end_time);
  e.set_allocationTime(sample->allocation_time());
  e.set_lastKnownHeapUsage(sample->heap_used_at_last_gc());
  e.set_object(object_id);
  e.set_arrayElements(array_size(edge->pointee()));
  e.set_root(gc_root_id);
  _jfr_thread_local->set_cached_stack_trace_id(sample->stack_trace_id());
  assert(sample->has_thread(), "invariant");
  _jfr_thread_local->set_thread_id(sample->thread_id());
  e.commit();
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/checkpoint/eventEmitter.hpp
#ifndef SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
#define SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
#include "memory/allocation.hpp"
#include "jfr/utilities/jfrTime.hpp"
typedef u8 traceid;
class EdgeStore;
class JfrThreadLocal;
class ObjectSample;
class ObjectSampler;
class Thread;
class EventEmitter : public CHeapObj<mtTracing> {
  friend class LeakProfiler;
  friend class PathToGcRootsOperation;
 private:
  const JfrTicks& _start_time;
  const JfrTicks& _end_time;
  Thread* _thread;
  JfrThreadLocal* _jfr_thread_local;
  traceid _thread_id;
  EventEmitter(const JfrTicks& start_time, const JfrTicks& end_time);
  ~EventEmitter();
  void write_event(const ObjectSample* sample, EdgeStore* edge_store);
  size_t write_events(ObjectSampler* sampler, EdgeStore* store, bool emit_all);
  static void emit(ObjectSampler* sampler, int64_t cutoff_ticks, bool emit_all);
};
#endif // SHARE_JFR_LEAKPROFILER_CHECKPOINT_EVENTEMITTER_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
#include "precompiled.hpp"
#include "jfr/jfrEvents.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
#include "jfr/leakprofiler/chains/edgeStore.hpp"
#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleWriter.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/leakprofiler/sampling/objectSample.hpp"
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
#include "jfr/leakprofiler/utilities/rootType.hpp"
#include "jfr/metadata/jfrSerializer.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
template <typename SampleProcessor>
static void do_samples(ObjectSample* sample, const ObjectSample* const end, SampleProcessor& processor) {
  assert(sample != NULL, "invariant");
  while (sample != end) {
    processor.sample_do(sample);
    sample = sample->next();
  }
}
class RootSystemType : public JfrSerializer {
 public:
  void serialize(JfrCheckpointWriter& writer) {
    const u4 nof_root_systems = OldObjectRoot::_number_of_systems;
    writer.write_count(nof_root_systems);
    for (u4 i = 0; i < nof_root_systems; ++i) {
      writer.write_key(i);
      writer.write(OldObjectRoot::system_description((OldObjectRoot::System)i));
    }
  }
};
class RootType : public JfrSerializer {
 public:
  void serialize(JfrCheckpointWriter& writer) {
    const u4 nof_root_types = OldObjectRoot::_number_of_types;
    writer.write_count(nof_root_types);
    for (u4 i = 0; i < nof_root_types; ++i) {
      writer.write_key(i);
      writer.write(OldObjectRoot::type_description((OldObjectRoot::Type)i));
    }
  }
};
class CheckpointInstall {
 private:
  const JfrCheckpointBlobHandle& _cp;
 public:
  CheckpointInstall(const JfrCheckpointBlobHandle& cp) : _cp(cp) {}
  void sample_do(ObjectSample* sample) {
    assert(sample != NULL, "invariant");
    if (!sample->is_dead()) {
      sample->set_klass_checkpoint(_cp);
    }
  }
};
class CheckpointWrite {
 private:
  JfrCheckpointWriter& _writer;
  const jlong _last_sweep;
 public:
  CheckpointWrite(JfrCheckpointWriter& writer, jlong last_sweep) : _writer(writer), _last_sweep(last_sweep) {}
  void sample_do(ObjectSample* sample) {
    assert(sample != NULL, "invariant");
    if (sample->is_alive_and_older_than(_last_sweep)) {
      if (sample->has_thread_checkpoint()) {
        const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();
        thread_cp->exclusive_write(_writer);
      }
      if (sample->has_klass_checkpoint()) {
        const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();
        klass_cp->exclusive_write(_writer);
      }
    }
  }
};
class CheckpointStateReset {
 private:
  const jlong _last_sweep;
 public:
  CheckpointStateReset(jlong last_sweep) : _last_sweep(last_sweep) {}
  void sample_do(ObjectSample* sample) {
    assert(sample != NULL, "invariant");
    if (sample->is_alive_and_older_than(_last_sweep)) {
      if (sample->has_thread_checkpoint()) {
        const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();
        thread_cp->reset_write_state();
      }
      if (sample->has_klass_checkpoint()) {
        const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();
        klass_cp->reset_write_state();
      }
    }
  }
};
class StackTraceWrite {
 private:
  JfrStackTraceRepository& _stack_trace_repo;
  JfrCheckpointWriter& _writer;
  int _count;
 public:
  StackTraceWrite(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer) :
    _stack_trace_repo(stack_trace_repo), _writer(writer), _count(0) {
    JfrStacktrace_lock->lock();
  }
  ~StackTraceWrite() {
    assert(JfrStacktrace_lock->owned_by_self(), "invariant");
    JfrStacktrace_lock->unlock();
  }
  void sample_do(ObjectSample* sample) {
    assert(sample != NULL, "invariant");
    if (!sample->is_dead()) {
      if (sample->has_stack_trace()) {
        JfrTraceId::use(sample->klass(), true);
        _stack_trace_repo.write(_writer, sample->stack_trace_id(), sample->stack_trace_hash());
        ++_count;
      }
    }
  }
  int count() const {
    return _count;
  }
};
class SampleMark {
 private:
  ObjectSampleMarker& _marker;
  jlong _last_sweep;
  int _count;
 public:
  SampleMark(ObjectSampleMarker& marker, jlong last_sweep) : _marker(marker),
                                                             _last_sweep(last_sweep),
                                                             _count(0) {}
  void sample_do(ObjectSample* sample) {
    assert(sample != NULL, "invariant");
    if (sample->is_alive_and_older_than(_last_sweep)) {
      _marker.mark(sample->object());
      ++_count;
    }
  }
  int count() const {
    return _count;
  }
};
void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool type_set) {
  if (!writer.has_data()) {
    return;
  }
  assert(writer.has_data(), "invariant");
  const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob();
  CheckpointInstall install(h_cp);
  ObjectSampler* const object_sampler = ObjectSampler::sampler();
  assert(object_sampler != NULL, "invariant");
  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
  const ObjectSample* const last_resolved = object_sampler->last_resolved();
  if (last != last_resolved) {
    do_samples(last, last_resolved, install);
    if (class_unload) {
      return;
    }
    if (type_set) {
      object_sampler->set_last_resolved(last);
    }
  }
}
void ObjectSampleCheckpoint::write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) {
  assert(sampler != NULL, "invariant");
  assert(edge_store != NULL, "invariant");
  assert(thread != NULL, "invariant");
  static bool types_registered = false;
  if (!types_registered) {
    JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType());
    JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType());
    types_registered = true;
  }
  const jlong last_sweep = emit_all ? max_jlong : sampler->last_sweep().value();
  ObjectSample* const last = const_cast<ObjectSample*>(sampler->last());
  {
    JfrCheckpointWriter writer(false, false, thread);
    CheckpointWrite checkpoint_write(writer, last_sweep);
    do_samples(last, NULL, checkpoint_write);
  }
  CheckpointStateReset state_reset(last_sweep);
  do_samples(last, NULL, state_reset);
  if (!edge_store->is_empty()) {
    JfrCheckpointWriter writer(false, true, thread);
    ObjectSampleWriter osw(writer, edge_store);
    edge_store->iterate(osw);
  }
}
int ObjectSampleCheckpoint::mark(ObjectSampler* object_sampler, ObjectSampleMarker& marker, bool emit_all) {
  assert(object_sampler != NULL, "invariant");
  ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
  if (last == NULL) {
    return 0;
  }
  const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
  SampleMark mark(marker, last_sweep);
  do_samples(last, NULL, mark);
  return mark.count();
}
WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo) :
  _sampler(sampler), _stack_trace_repo(repo) {}
bool WriteObjectSampleStacktrace::process() {
  assert(LeakProfiler::is_running(), "invariant");
  assert(_sampler != NULL, "invariant");
  ObjectSample* const last = const_cast<ObjectSample*>(_sampler->last());
  const ObjectSample* const last_resolved = _sampler->last_resolved();
  if (last == last_resolved) {
    return true;
  }
  JfrCheckpointWriter writer(false, true, Thread::current());
  const JfrCheckpointContext ctx = writer.context();
  writer.write_type(TYPE_STACKTRACE);
  const jlong count_offset = writer.reserve(sizeof(u4));
  int count = 0;
  {
    StackTraceWrite stack_trace_write(_stack_trace_repo, writer); // JfrStacktrace_lock
    do_samples(last, last_resolved, stack_trace_write);
    count = stack_trace_write.count();
  }
  if (count == 0) {
    writer.set_context(ctx);
    return true;
  }
  assert(count > 0, "invariant");
  writer.write_count((u4)count, count_offset);
  JfrStackTraceRepository::write_metadata(writer);
  ObjectSampleCheckpoint::install(writer, false, false);
  return true;
}
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp
#ifndef SHARE_VM_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP
#define SHARE_VM_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP
#include "memory/allocation.hpp"
class EdgeStore;
class JfrCheckpointWriter;
class JfrStackTraceRepository;
class ObjectSampleMarker;
class ObjectSampler;
class ObjectSampleCheckpoint : AllStatic {
 public:
  static void install(JfrCheckpointWriter& writer, bool class_unload, bool type_set);
  static void write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread);
  static int mark(ObjectSampler* sampler, ObjectSampleMarker& marker, bool emit_all);
};
class WriteObjectSampleStacktrace : public StackObj {
 private:
  ObjectSampler* const _sampler;
  JfrStackTraceRepository& _stack_trace_repo;
 public:
  WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo);
  bool process();
};
#endif // SHARE_VM_LEAKPROFILER_CHECKPOINT_OBJECTSAMPLECHECKPOINT_HPP
C:\hotspot-69087d08d473\src\share\vm/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleDescription.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/thread.hpp"
#include "utilities/ostream.hpp"
static Symbol* symbol_size = NULL;
ObjectDescriptionBuilder::ObjectDescriptionBuilder() {
  reset();
}
void ObjectDescriptionBuilder::write_int(jint value) {
  char buf[20];
  jio_snprintf(buf, sizeof(buf), "%d", value);
  write_text(buf);
}
void ObjectDescriptionBuilder::write_text(const char* text) {
  if (_index == sizeof(_buffer) - 2) {
    return;
  }
  while (*text != '\0' && _index < sizeof(_buffer) - 2) {
    _buffer[_index] = *text;
    _index++;
    text++;
  }
  assert(_index < sizeof(_buffer) - 1, "index should not exceed buffer size");
  if (_index == sizeof(_buffer) - 2) {
    _buffer[_index-3] = '.';
    _buffer[_index-2] = '.';
    _buffer[_index-1] = '.';
  }
  _buffer[_index] = '\0';
}
void ObjectDescriptionBuilder::reset() {
  _index = 0;
  _buffer[0] = '\0';
}
void ObjectDescriptionBuilder::print_description(outputStream* out) {
  out->print("%s", (const char*)_buffer);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值