products/Sources/formale Sprachen/Java/openjdk-20-36_src/src/hotspot/share/prims image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: jvmtiEnvBase.hpp   Sprache: C

/*
 * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#ifndef SHARE_PRIMS_JVMTIENVBASE_HPP
#define SHARE_PRIMS_JVMTIENVBASE_HPP

#include "prims/jvmtiEnvThreadState.hpp"
#include "prims/jvmtiEventController.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "oops/oopHandle.hpp"
#include "runtime/atomic.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/frame.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/threads.hpp"
#include "runtime/vmOperation.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"

//
// Forward Declarations
//

class JvmtiEnv;
class JvmtiThreadState;
class JvmtiRawMonitor; // for jvmtiEnv.hpp
class JvmtiEventControllerPrivate;
class JvmtiTagMap;



// One JvmtiEnv object is created per jvmti attachment;
// done via JNI GetEnv() call. Multiple attachments are
// allowed in jvmti.

class JvmtiEnvBase : public CHeapObj<mtInternal> {

 private:

#if INCLUDE_JVMTI
  static JvmtiEnvBase*     _head_environment;  // head of environment list
#endif // INCLUDE_JVMTI

  static bool              _globally_initialized;
  static jvmtiPhase        _phase;
  static volatile int      _dying_thread_env_iteration_count;

 public:

  enum {
    JDK15_JVMTI_VERSION = JVMTI_VERSION_1_0 +  33,  /* version: 1.0.33  */
    JDK16_JVMTI_VERSION = JVMTI_VERSION_1_1 + 102,  /* version: 1.1.102 */
    JDK17_JVMTI_VERSION = JVMTI_VERSION_1_2 +   2   /* version: 1.2.2   */
  };

  static jvmtiPhase  get_phase()                    { return _phase; }
  static jvmtiPhase  get_phase(jvmtiEnv* env)       { return ((JvmtiEnvBase*)JvmtiEnv_from_jvmti_env(env))->phase(); }
  static void  set_phase(jvmtiPhase phase)          { _phase = phase; }
  static bool is_vm_live()                          { return _phase == JVMTI_PHASE_LIVE; }

  static void entering_dying_thread_env_iteration() { ++_dying_thread_env_iteration_count; }
  static void leaving_dying_thread_env_iteration()  { --_dying_thread_env_iteration_count; }
  static bool is_inside_dying_thread_env_iteration(){ return _dying_thread_env_iteration_count > 0; }

  static jvmtiError suspend_thread(oop thread_oop, JavaThread* java_thread, bool single_suspend,
                                   int* need_safepoint_p);
  static jvmtiError resume_thread(oop thread_oop, JavaThread* java_thread, bool single_resume);
  static jvmtiError check_thread_list(jint count, const jthread* list);
  static bool is_in_thread_list(jint count, const jthread* list, oop jt_oop);

  // check if thread_oop represents a passive carrier thread
  static bool is_passive_carrier_thread(JavaThread* java_thread, oop thread_oop) {
    return java_thread != NULL && java_thread->jvmti_vthread() != NULL
                               && java_thread->jvmti_vthread() != thread_oop
                               && java_thread->threadObj() == thread_oop;
  }

 private:

  enum {
      JVMTI_MAGIC    = 0x71EE,
      DISPOSED_MAGIC = 0xDEFC,
      BAD_MAGIC      = 0xDEAD
  };

  jvmtiEnv _jvmti_external;
  jint _magic;
  jint _version;  // version value passed to JNI GetEnv()
  JvmtiEnvBase* _next;
  bool _is_retransformable;
  const void *_env_local_storage;     // per env agent allocated data.
  jvmtiEventCallbacks _event_callbacks;
  jvmtiExtEventCallbacks _ext_event_callbacks;
  JvmtiTagMap* volatile _tag_map;
  JvmtiEnvEventEnable _env_event_enable;
  jvmtiCapabilities _current_capabilities;
  jvmtiCapabilities _prohibited_capabilities;
  volatile bool _class_file_load_hook_ever_enabled;
  static volatile bool _needs_clean_up;
  char** _native_method_prefixes;
  int    _native_method_prefix_count;

 protected:
  JvmtiEnvBase(jint version);
  ~JvmtiEnvBase();
  void dispose();
  void env_dispose();

  void set_env_local_storage(const void* data)     { _env_local_storage = data; }
  const void* get_env_local_storage()              { return _env_local_storage; }

  void record_class_file_load_hook_enabled();
  void record_first_time_class_file_load_hook_enabled();

  char** get_native_method_prefixes()              { return _native_method_prefixes; }
  int    get_native_method_prefix_count()          { return _native_method_prefix_count; }
  jvmtiError set_native_method_prefixes(jint prefix_count, char** prefixes);

 private:
  friend class JvmtiEventControllerPrivate;
  void initialize();
  void set_event_callbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks);
  static void globally_initialize();
  static void periodic_clean_up();

  friend class JvmtiEnvIterator;
  JvmtiEnv* next_environment()                     { return (JvmtiEnv*)_next; }
  void set_next_environment(JvmtiEnvBase* env)     { _next = env; }
  static JvmtiEnv* head_environment()              {
    JVMTI_ONLY(return (JvmtiEnv*)_head_environment);
    NOT_JVMTI(return NULL);
  }

 public:

  jvmtiPhase  phase();
  bool is_valid();

  bool use_version_1_0_semantics();  // agent asked for version 1.0
  bool use_version_1_1_semantics();  // agent asked for version 1.1
  bool use_version_1_2_semantics();  // agent asked for version 1.2

  bool is_retransformable()                        { return _is_retransformable; }

  static ByteSize jvmti_external_offset() {
    return byte_offset_of(JvmtiEnvBase, _jvmti_external);
  };

  // If (thread == NULL) then return current thread object.
  // Otherwise return JNIHandles::resolve_external_guard(thread).
  static oop current_thread_obj_or_resolve_external_guard(jthread thread);

  // Return true if the thread identified with a pair <jt,thr_obj> is current.
  // A passive carrier thread is not treated as current.
  static bool is_JavaThread_current(JavaThread* jt, oop thr_obj) {
    JavaThread* current = JavaThread::current();
    // jt can be NULL in case of a virtual thread
    if (jt == NULL || jt != current) {
      return false;
    }
    oop cur_obj = current->jvmti_vthread();

    // cur_obj == NULL is true for normal platform threads only
    // otherwise it can be virtual or carrier thread.
    return cur_obj == NULL || cur_obj == thr_obj;
  }

  static jvmtiError get_JavaThread(ThreadsList* tlist, jthread thread, JavaThread** jt_pp) {
    jvmtiError err = JVMTI_ERROR_NONE;
    if (thread == NULL) {
      *jt_pp = JavaThread::current();
    } else {
      err = JvmtiExport::cv_external_thread_to_JavaThread(tlist, thread, jt_pp, NULL);
    }
    return err;
  }

  // If there is a virtual thread mounted on the JavaThread* then
  // return virtual thread oop. Otherwise, return thread oop.
  static oop get_vthread_or_thread_oop(JavaThread* jt) {
    oop result = jt->threadObj();
    if (jt->jvmti_vthread() != NULL) {
      result = jt->jvmti_vthread();
    }
    return result;
  }

  static jvmtiError get_threadOop_and_JavaThread(ThreadsList* t_list, jthread thread,
                                                 JavaThread** jt_pp, oop* thread_oop_p);

  // Return true if java thread is a carrier thread with a mounted virtual thread.
  static bool is_cthread_with_mounted_vthread(JavaThread* jt);
  static bool is_cthread_with_continuation(JavaThread* jt);

  static JvmtiEnv* JvmtiEnv_from_jvmti_env(jvmtiEnv *env) {
    return (JvmtiEnv*)((intptr_t)env - in_bytes(jvmti_external_offset()));
  };

  jvmtiCapabilities *get_capabilities()             { return &_current_capabilities; }

  jvmtiCapabilities *get_prohibited_capabilities()  { return &_prohibited_capabilities; }

  bool early_class_hook_env() {
    return get_capabilities()->can_generate_early_class_hook_events != 0
        && get_capabilities()->can_generate_all_class_hook_events != 0;
  }

  bool early_vmstart_env() {
    return get_capabilities()->can_generate_early_vmstart != 0;
  }

  static char** get_all_native_method_prefixes(int* count_ptr);

  // This test will answer true when all environments have been disposed and some have
  // not yet been deallocated.  As a result, this test should only be used as an
  // optimization for the no environment case.
  static bool environments_might_exist() {
    return head_environment() != NULL;
  }

  static void check_for_periodic_clean_up();

  JvmtiEnvEventEnable *env_event_enable() {
    return &_env_event_enable;
  }

  jvmtiError allocate(jlong size, unsigned char** mem_ptr) {
    if (size < 0) {
      return JVMTI_ERROR_ILLEGAL_ARGUMENT;
    }
    if (size == 0) {
      *mem_ptr = NULL;
    } else {
      *mem_ptr = (unsigned char *)os::malloc((size_t)size, mtInternal);
      if (*mem_ptr == NULL) {
        return JVMTI_ERROR_OUT_OF_MEMORY;
      }
    }
    return JVMTI_ERROR_NONE;
  }

  jvmtiError deallocate(unsigned char* mem) {
    if (mem != NULL) {
      os::free(mem);
    }
    return JVMTI_ERROR_NONE;
  }


  // Memory functions
  unsigned char* jvmtiMalloc(jlong size);  // don't use this - call allocate

  // method to create a local handle
  jobject jni_reference(Handle hndl);

  // method to create a local handle.
  // This function allows caller to specify which
  // threads local handle table to use.
  jobject jni_reference(JavaThread *thread, Handle hndl);

  // method to destroy a local handle
  void destroy_jni_reference(jobject jobj);

  // method to destroy a local handle.
  // This function allows caller to specify which
  // threads local handle table to use.
  void destroy_jni_reference(JavaThread *thread, jobject jobj);

  jvmtiEnv* jvmti_external() { return &_jvmti_external; };

// Event Dispatch

  bool has_callback(jvmtiEvent event_type) {
    assert(event_type >= JVMTI_MIN_EVENT_TYPE_VAL &&
           event_type <= JVMTI_MAX_EVENT_TYPE_VAL, "checking");
    return ((void**)&_event_callbacks)[event_type-JVMTI_MIN_EVENT_TYPE_VAL] != NULL;
  }

  jvmtiEventCallbacks* callbacks() {
    return &_event_callbacks;
  }

  jvmtiExtEventCallbacks* ext_callbacks() {
    return &_ext_event_callbacks;
  }

  void set_tag_map(JvmtiTagMap* tag_map) {
    _tag_map = tag_map;
  }

  JvmtiTagMap* tag_map() {
    return _tag_map;
  }

  JvmtiTagMap* tag_map_acquire() {
    return Atomic::load_acquire(&_tag_map);
  }

  void release_set_tag_map(JvmtiTagMap* tag_map) {
    Atomic::release_store(&_tag_map, tag_map);
  }

  // return true if event is enabled globally or for any thread
  // True only if there is a callback for it.
  bool is_enabled(jvmtiEvent event_type) {
    return _env_event_enable.is_enabled(event_type);
  }

// Random Utilities

 protected:
  // helper methods for creating arrays of global JNI Handles from local Handles
  // allocated into environment specific storage
  jthread * new_jthreadArray(int length, Handle *handles);
  jthreadGroup * new_jthreadGroupArray(int length, objArrayHandle groups);

  // convert to a jni jclass from a non-null Klass*
  jclass get_jni_class_non_null(Klass* k);

  jint count_locked_objects(JavaThread *java_thread, Handle hobj);
  jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread,
                                   JavaThread* java_thread,
                                   javaVFrame *jvf,
                                   GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list,
                                   jint depth);
 public:
  static javaVFrame* jvf_for_thread_and_depth(JavaThread* java_thread, jint depth);

  // get a field descriptor for the specified class and field
  static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd);

  // check and skip frames hidden in mount/unmount transitions
  static javaVFrame* check_and_skip_hidden_frames(bool is_in_VTMS_transition, javaVFrame* jvf);
  static javaVFrame* check_and_skip_hidden_frames(JavaThread* jt, javaVFrame* jvf);
  static javaVFrame* check_and_skip_hidden_frames(oop vthread, javaVFrame* jvf);

  // check if virtual thread is not terminated (alive)
  static bool is_vthread_alive(oop vt);

  // return JavaThread if virtual thread is mounted, NULL otherwise
  static JavaThread* get_JavaThread_or_null(oop vthread);

  // get virtual thread last java vframe
  static javaVFrame* get_vthread_jvf(oop vthread);

  // get carrier thread last java vframe
  static javaVFrame* get_cthread_last_java_vframe(JavaThread* jt, RegisterMap* reg_map);

  // get ordinary thread thread state
  static jint get_thread_state(oop thread_oop, JavaThread* jt);

  // get virtual thread thread state
  static jint get_vthread_state(oop thread_oop, JavaThread* jt);

  // enumerates the live threads in the given thread group
  static jvmtiError get_live_threads(JavaThread* current_thread, Handle group_hdl, jint *count_ptr, Handle **thread_objs_p);

  // enumerates the subgroups in the given thread group
  static jvmtiError get_subgroups(JavaThread* current_thread, Handle group_hdl, jint *count_ptr, objArrayHandle *group_objs_p);

  // JVMTI API helper functions which are called when target thread is suspended
  // or at safepoint / thread local handshake.
  static jint get_frame_count(javaVFrame* jvf);
  jvmtiError get_frame_count(JavaThread* java_thread, jint *count_ptr);
  jvmtiError get_frame_count(oop frame_oop, jint *count_ptr);
  jvmtiError get_frame_location(javaVFrame* jvf, jint depth,
                                jmethodID* method_ptr, jlocation* location_ptr);
  jvmtiError get_frame_location(JavaThread* java_thread, jint depth,
                                jmethodID* method_ptr, jlocation* location_ptr);
  jvmtiError get_frame_location(oop vthread_oop, jint depth,
                                jmethodID* method_ptr, jlocation* location_ptr);
  jvmtiError set_frame_pop(JvmtiThreadState* state, javaVFrame* jvf, jint depth);
  jvmtiError get_object_monitor_usage(JavaThread* calling_thread,
                                      jobject object, jvmtiMonitorUsage* info_ptr);
  jvmtiError get_stack_trace(javaVFrame* jvf,
                             jint stack_depth, jint max_count,
                             jvmtiFrameInfo* frame_buffer, jint* count_ptr);
  jvmtiError get_stack_trace(JavaThread* java_thread,
                             jint stack_depth, jint max_count,
                             jvmtiFrameInfo* frame_buffer, jint* count_ptr);
  jvmtiError get_current_contended_monitor(JavaThread* calling_thread, JavaThread* java_thread,
                                           jobject* monitor_ptr, bool is_virtual);
  jvmtiError get_owned_monitors(JavaThread* calling_thread, JavaThread* java_thread,
                                GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list);
  jvmtiError get_owned_monitors(JavaThread* calling_thread, JavaThread* java_thread, javaVFrame* jvf,
                                GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list);
  static jvmtiError check_top_frame(Thread* current_thread, JavaThread* java_thread,
                                    jvalue value, TosState tos, Handle* ret_ob_h);
  jvmtiError force_early_return(jthread thread, jvalue value, TosState tos);
};

// This class is the only safe means of iterating through environments.
// Note that this iteratation includes invalid environments pending
// deallocation -- in fact, some uses depend on this behavior.

class JvmtiEnvIterator : public StackObj {
 private:
  bool _entry_was_marked;
 public:
  JvmtiEnvIterator() {
    if (Threads::number_of_threads() == 0) {
      _entry_was_marked = false// we are single-threaded, no need
    } else {
      Thread::current()->entering_jvmti_env_iteration();
      _entry_was_marked = true;
    }
  }
  ~JvmtiEnvIterator() {
    if (_entry_was_marked) {
      Thread::current()->leaving_jvmti_env_iteration();
    }
  }
  JvmtiEnv* first()                 { return JvmtiEnvBase::head_environment(); }
  JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); }
};

class JvmtiHandshakeClosure : public HandshakeClosure {
 protected:
  jvmtiError _result;
 public:
  JvmtiHandshakeClosure(const char* name)
    : HandshakeClosure(name),
      _result(JVMTI_ERROR_THREAD_NOT_ALIVE) {}
  jvmtiError result() { return _result; }
};

class SetForceEarlyReturn : public JvmtiHandshakeClosure {
private:
  JvmtiThreadState* _state;
  jvalue _value;
  TosState _tos;
public:
  SetForceEarlyReturn(JvmtiThreadState* state, jvalue value, TosState tos)
    : JvmtiHandshakeClosure("SetForceEarlyReturn"),
     _state(state),
     _value(value),
     _tos(tos) {}
  void do_thread(Thread *target) {
    doit(target, false /* self */);
  }
  void doit(Thread *target, bool self);
};

// HandshakeClosure to update for pop top frame.
class UpdateForPopTopFrameClosure : public JvmtiHandshakeClosure {
private:
  JvmtiThreadState* _state;

public:
  UpdateForPopTopFrameClosure(JvmtiThreadState* state)
    : JvmtiHandshakeClosure("UpdateForPopTopFrame"),
     _state(state) {}
  void do_thread(Thread *target) {
    doit(target, false /* self */);
  }
  void doit(Thread *target, bool self);
};

// HandshakeClosure to set frame pop.
class SetFramePopClosure : public JvmtiHandshakeClosure {
private:
  JvmtiEnv *_env;
  JvmtiThreadState* _state;
  jint _depth;

public:
  SetFramePopClosure(JvmtiEnv *env, JvmtiThreadState* state, jint depth)
    : JvmtiHandshakeClosure("SetFramePopClosure"),
      _env(env),
      _state(state),
      _depth(depth) {}
  void do_thread(Thread *target) {
    doit(target, false /* self */);
  }
  void doit(Thread *target, bool self);
};

// HandshakeClosure to get monitor information with stack depth.
class GetOwnedMonitorInfoClosure : public JvmtiHandshakeClosure {
private:
  JavaThread* _calling_thread;
  JvmtiEnv *_env;
  GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;

public:
  GetOwnedMonitorInfoClosure(JavaThread* calling_thread, JvmtiEnv* env,
                             GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list)
    : JvmtiHandshakeClosure("GetOwnedMonitorInfo"),
      _calling_thread(calling_thread),
      _env(env),
      _owned_monitors_list(owned_monitor_list) {}
  void do_thread(Thread *target);
};

// VM operation to get object monitor usage.
class VM_GetObjectMonitorUsage : public VM_Operation {
private:
  JvmtiEnv *_env;
  jobject _object;
  JavaThread* _calling_thread;
  jvmtiMonitorUsage* _info_ptr;
  jvmtiError _result;

public:
  VM_GetObjectMonitorUsage(JvmtiEnv *env, JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) {
    _env = env;
    _object = object;
    _calling_thread = calling_thread;
    _info_ptr = info_ptr;
  }
  VMOp_Type type() const { return VMOp_GetObjectMonitorUsage; }
  jvmtiError result() { return _result; }
  void doit() {
    _result = ((JvmtiEnvBase*) _env)->get_object_monitor_usage(_calling_thread, _object, _info_ptr);
  }

};

// HandshakeClosure to get current contended monitor. It is used for both platform and virtual threads.
class GetCurrentContendedMonitorClosure : public JvmtiHandshakeClosure {
private:
  JavaThread *_calling_thread;
  JvmtiEnv *_env;
  jobject *_owned_monitor_ptr;
  bool _is_virtual;

public:
  GetCurrentContendedMonitorClosure(JavaThread* calling_thread, JvmtiEnv *env, jobject *mon_ptr, bool is_virtual)
    : JvmtiHandshakeClosure("GetCurrentContendedMonitor"),
      _calling_thread(calling_thread),
      _env(env),
      _owned_monitor_ptr(mon_ptr),
      _is_virtual(is_virtual) {}
  void do_thread(Thread *target);
};

// HandshakeClosure to get stack trace.
class GetStackTraceClosure : public JvmtiHandshakeClosure {
private:
  JvmtiEnv *_env;
  jint _start_depth;
  jint _max_count;
  jvmtiFrameInfo *_frame_buffer;
  jint *_count_ptr;

public:
  GetStackTraceClosure(JvmtiEnv *env, jint start_depth, jint max_count,
                       jvmtiFrameInfo* frame_buffer, jint* count_ptr)
    : JvmtiHandshakeClosure("GetStackTrace"),
      _env(env),
      _start_depth(start_depth),
      _max_count(max_count),
      _frame_buffer(frame_buffer),
      _count_ptr(count_ptr) {}
  void do_thread(Thread *target);
};

#ifdef ASSERT
// HandshakeClosure to print stack trace in JvmtiVTMSTransitionDisabler error handling.
class PrintStackTraceClosure : public HandshakeClosure {
 public:
  static void do_thread_impl(Thread *target);

  PrintStackTraceClosure()
      : HandshakeClosure("PrintStackTraceClosure") {}
  void do_thread(Thread *target);
};
#endif

// Forward declaration.
struct StackInfoNode;

// Get stack trace at safepoint or at direct handshake.
class MultipleStackTracesCollector {
private:
  friend class VM_GetThreadListStackTraces;
  JvmtiEnv *_env;
  jint _max_frame_count;
  jvmtiStackInfo *_stack_info;
  jvmtiError _result;
  int _frame_count_total;
  struct StackInfoNode *_head;

  JvmtiEnvBase *env()                 { return (JvmtiEnvBase *)_env; }
  jint max_frame_count()              { return _max_frame_count; }
  struct StackInfoNode *head()        { return _head; }
  void set_head(StackInfoNode *head)  { _head = head; }

public:
  MultipleStackTracesCollector(JvmtiEnv *env, jint max_frame_count)
    : _env(env),
      _max_frame_count(max_frame_count),
      _stack_info(NULL),
      _result(JVMTI_ERROR_NONE),
      _frame_count_total(0),
      _head(NULL) {
  }
  void set_result(jvmtiError result)  { _result = result; }
  void fill_frames(jthread jt, JavaThread *thr, oop thread_oop);
  void allocate_and_fill_stacks(jint thread_count);
  jvmtiStackInfo *stack_info()       { return _stack_info; }
  jvmtiError result()                { return _result; }
};


// VM operation to get stack trace at safepoint.
class VM_GetAllStackTraces : public VM_Operation {
private:
  JavaThread *_calling_thread;
  jint _final_thread_count;
  MultipleStackTracesCollector _collector;

public:
  VM_GetAllStackTraces(JvmtiEnv *env, JavaThread *calling_thread,
                       jint max_frame_count)
      : _calling_thread(calling_thread),
        _final_thread_count(0),
        _collector(env, max_frame_count) {
  }
  VMOp_Type type() const          { return VMOp_GetAllStackTraces; }
  void doit();
  jint final_thread_count()       { return _final_thread_count; }
  jvmtiStackInfo *stack_info()    { return _collector.stack_info(); }
  jvmtiError result()             { return _collector.result(); }
};

// VM operation to get stack trace at safepoint.
class VM_GetThreadListStackTraces : public VM_Operation {
private:
  jint _thread_count;
  const jthread* _thread_list;
  MultipleStackTracesCollector _collector;

  JvmtiEnvBase *env() { return _collector.env(); }

public:
  VM_GetThreadListStackTraces(JvmtiEnv *env, jint thread_count, const jthread* thread_list, jint max_frame_count)
      : _thread_count(thread_count),
        _thread_list(thread_list),
        _collector(env, max_frame_count) {
  }
  VMOp_Type type() const { return VMOp_GetThreadListStackTraces; }
  void doit();
  jvmtiStackInfo *stack_info()    { return _collector.stack_info(); }
  jvmtiError result()             { return _collector.result(); }
};

class VM_VirtualThreadGetStackTrace : public VM_Operation {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  jint _start_depth;
  jint _max_count;
  jvmtiFrameInfo* _frame_buffer;
  jint* _count_ptr;
  jvmtiError _result;

public:
  VM_VirtualThreadGetStackTrace(JvmtiEnv *env, Handle vthread_h,
                                jint start_depth, jint max_count,
                                jvmtiFrameInfo* frame_buffer, jint* count_ptr)
    : _env(env),
      _vthread_h(vthread_h),
      _start_depth(start_depth),
      _max_count(max_count),
      _frame_buffer(frame_buffer),
      _count_ptr(count_ptr),
      _result(JVMTI_ERROR_NONE)
  {}

  VMOp_Type type() const { return VMOp_VirtualThreadGetStackTrace; }
  void doit();
  jvmtiError result() { return _result; }
};

class VM_VirtualThreadGetFrameCount : public VM_Operation {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  jint* _count_ptr;
  jvmtiError _result;

public:
  VM_VirtualThreadGetFrameCount(JvmtiEnv *env, Handle vthread_h, jint* count_ptr)
    : _env(env),
      _vthread_h(vthread_h),
      _count_ptr(count_ptr),
      _result(JVMTI_ERROR_NONE)
  {}

  VMOp_Type type() const { return VMOp_VirtualThreadGetFrameCount; }
  void doit();
  jvmtiError result() { return _result; }
};

// HandshakeClosure to get single stack trace.
class GetSingleStackTraceClosure : public HandshakeClosure {
private:
  JavaThread *_calling_thread;
  jthread _jthread;
  MultipleStackTracesCollector _collector;

public:
  GetSingleStackTraceClosure(JvmtiEnv *env, JavaThread *calling_thread,
                             jthread thread, jint max_frame_count)
    : HandshakeClosure("GetSingleStackTrace"),
      _calling_thread(calling_thread),
      _jthread(thread),
      _collector(env, max_frame_count) {
  }
  void do_thread(Thread *target);
  jvmtiStackInfo *stack_info()    { return _collector.stack_info(); }
  jvmtiError result()             { return _collector.result(); }
};

// HandshakeClosure to count stack frames.
class GetFrameCountClosure : public JvmtiHandshakeClosure {
private:
  JvmtiEnv *_env;
  jint *_count_ptr;

public:
  GetFrameCountClosure(JvmtiEnv *env, jint *count_ptr)
    : JvmtiHandshakeClosure("GetFrameCount"),
      _env(env),
      _count_ptr(count_ptr) {}
  void do_thread(Thread *target);
};

// HandshakeClosure to get frame location.
class GetFrameLocationClosure : public JvmtiHandshakeClosure {
private:
  JvmtiEnv *_env;
  jint _depth;
  jmethodID* _method_ptr;
  jlocation* _location_ptr;

public:
  GetFrameLocationClosure(JvmtiEnv *env, jint depth,
                          jmethodID* method_ptr, jlocation* location_ptr)
    : JvmtiHandshakeClosure("GetFrameLocation"),
      _env(env),
      _depth(depth),
      _method_ptr(method_ptr),
      _location_ptr(location_ptr) {}
  void do_thread(Thread *target);
};

// HandshakeClosure to get virtual thread monitor information with stack depth.
class VirtualThreadGetOwnedMonitorInfoClosure : public HandshakeClosure {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;
  jvmtiError _result;

public:
  VirtualThreadGetOwnedMonitorInfoClosure(JvmtiEnv* env,
                                          Handle vthread_h,
                                          GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list)
    : HandshakeClosure("VirtualThreadGetOwnedMonitorInfo"),
      _env(env),
      _vthread_h(vthread_h),
      _owned_monitors_list(owned_monitors_list),
      _result(JVMTI_ERROR_THREAD_NOT_ALIVE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure to get virtual thread thread at safepoint.
class VirtualThreadGetThreadClosure : public HandshakeClosure {
private:
  Handle _vthread_h;
  jthread* _carrier_thread_ptr;
  jvmtiError _result;

public:
  VirtualThreadGetThreadClosure(Handle vthread_h, jthread* carrier_thread_ptr)
    : HandshakeClosure("VirtualThreadGetThread"),
      _vthread_h(vthread_h),
      _carrier_thread_ptr(carrier_thread_ptr),
      _result(JVMTI_ERROR_NONE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure to get virtual thread stack trace at safepoint.
class VirtualThreadGetStackTraceClosure : public HandshakeClosure {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  jint _start_depth;
  jint _max_count;
  jvmtiFrameInfo *_frame_buffer;
  jint *_count_ptr;
  jvmtiError _result;

public:
  VirtualThreadGetStackTraceClosure(JvmtiEnv *env, Handle vthread_h,
                                    jint start_depth, jint max_count,
                                    jvmtiFrameInfo* frame_buffer, jint* count_ptr)
    : HandshakeClosure("VirtualThreadGetStackTrace"),
      _env(env),
      _vthread_h(vthread_h),
       _start_depth(start_depth),
      _max_count(max_count),
      _frame_buffer(frame_buffer),
      _count_ptr(count_ptr),
      _result(JVMTI_ERROR_NONE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure to count virtual thread stack frames at safepoint.
class VirtualThreadGetFrameCountClosure : public HandshakeClosure {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  jint *_count_ptr;
  jvmtiError _result;

public:
  VirtualThreadGetFrameCountClosure(JvmtiEnv *env, Handle vthread_h, jint *count_ptr)
    : HandshakeClosure("VirtualThreadGetFrameCount"),
      _env(env), _vthread_h(vthread_h), _count_ptr(count_ptr),
      _result(JVMTI_ERROR_NONE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure get to virtual thread frame location at safepoint.
class VirtualThreadGetFrameLocationClosure : public HandshakeClosure {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  jint _depth;
  jmethodID* _method_ptr;
  jlocation* _location_ptr;
  jvmtiError _result;

public:
  VirtualThreadGetFrameLocationClosure(JvmtiEnv *env, Handle vthread_h, jint depth,
                                       jmethodID* method_ptr, jlocation* location_ptr)
    : HandshakeClosure("VirtualThreadGetFrameLocation"),
      _env(env),
      _vthread_h(vthread_h),
      _depth(depth),
      _method_ptr(method_ptr),
      _location_ptr(location_ptr),
      _result(JVMTI_ERROR_NONE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure to get virtual thread state at safepoint.
class VirtualThreadGetThreadStateClosure : public HandshakeClosure {
private:
  Handle _vthread_h;
  jint *_state_ptr;
  jvmtiError _result;

public:
  VirtualThreadGetThreadStateClosure(Handle vthread_h, jint *state_ptr)
    : HandshakeClosure("VirtualThreadGetThreadState"),
      _vthread_h(vthread_h),
      _state_ptr(state_ptr),
      _result(JVMTI_ERROR_NONE) {}

  void do_thread(Thread *target);
  jvmtiError result() { return _result; }
};

// HandshakeClosure to set frame pop for a virtual thread.
class VirtualThreadSetFramePopClosure : public JvmtiHandshakeClosure {
private:
  JvmtiEnv *_env;
  Handle _vthread_h;
  JvmtiThreadState* _state;
  jint _depth;

public:
  VirtualThreadSetFramePopClosure(JvmtiEnv *env, Handle vthread_h, JvmtiThreadState* state, jint depth)
    : JvmtiHandshakeClosure("VirtualThreadSetFramePopClosure"),
      _env(env),
      _vthread_h(vthread_h),
      _state(state),
      _depth(depth) {}

  void do_thread(Thread *target) {
    doit(target, false /* self */);
  }
  void doit(Thread *target, bool self);
};


// ResourceTracker
//
// ResourceTracker works a little like a ResourceMark. All allocates
// using the resource tracker are recorded. If an allocate using the
// resource tracker fails the destructor will free any resources
// that were allocated using the tracker.
// The motive for this class is to avoid messy error recovery code
// in situations where multiple allocations are done in sequence. If
// the second or subsequent allocation fails it avoids any code to
// release memory allocated in the previous calls.
//
// Usage :-
//   ResourceTracker rt(env);
//   :
//   err = rt.allocate(1024, &ptr);

class ResourceTracker : public StackObj {
 private:
  JvmtiEnv* _env;
  GrowableArray<unsigned char*> *_allocations;
  bool _failed;
 public:
  ResourceTracker(JvmtiEnv* env);
  ~ResourceTracker();
  jvmtiError allocate(jlong size, unsigned char** mem_ptr);
  unsigned char* allocate(jlong size);
  char* strdup(const char* str);
};


// Jvmti monitor closure to collect off stack monitors.
class JvmtiMonitorClosure: public MonitorClosure {
 private:
  JavaThread *_calling_thread;
  GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;
  jvmtiError _error;
  JvmtiEnvBase *_env;

 public:
  JvmtiMonitorClosure(JavaThread *calling_thread,
                      GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors,
                      JvmtiEnvBase *env) {
    _calling_thread = calling_thread;
    _owned_monitors_list = owned_monitors;
    _error = JVMTI_ERROR_NONE;
    _env = env;
  }
  void do_monitor(ObjectMonitor* mon);
  jvmtiError error() { return _error;}
};


// Jvmti module closure to collect all modules loaded to the system.
class JvmtiModuleClosure : public StackObj {
private:
  static GrowableArray<OopHandle> *_tbl; // Protected with Module_lock

  static void do_module(ModuleEntry* entry);
public:
  jvmtiError get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr);
};

#endif // SHARE_PRIMS_JVMTIENVBASE_HPP

¤ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff