jdk

Форк
0
/
jvmtiAgent.cpp 
643 строки · 22.7 Кб
1
/*
2
 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
15
 * You should have received a copy of the GNU General Public License version
16
 * 2 along with this work; if not, write to the Free Software Foundation,
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
 * or visit www.oracle.com if you need additional information or have any
21
 * questions.
22
 */
23

24
#include "precompiled.hpp"
25
#include "prims/jvmtiAgent.hpp"
26

27
#include "cds/cds_globals.hpp"
28
#include "cds/cdsConfig.hpp"
29
#include "jni.h"
30
#include "jvm_io.h"
31
#include "jvmtifiles/jvmtiEnv.hpp"
32
#include "prims/jvmtiEnvBase.hpp"
33
#include "prims/jvmtiExport.hpp"
34
#include "prims/jvmtiAgentList.hpp"
35
#include "runtime/arguments.hpp"
36
#include "runtime/handles.inline.hpp"
37
#include "runtime/interfaceSupport.inline.hpp"
38
#include "runtime/java.hpp"
39
#include "runtime/jniHandles.hpp"
40
#include "runtime/globals_extension.hpp"
41
#include "runtime/os.inline.hpp"
42
#include "runtime/thread.inline.hpp"
43
#include "utilities/defaultStream.hpp"
44

45
static inline const char* copy_string(const char* str) {
46
  return str != nullptr ? os::strdup(str, mtServiceability) : nullptr;
47
}
48

49
// Returns the lhs before '=', parsed_options output param gets the rhs.
50
static const char* split_options_and_allocate_copy(const char* options, const char** parsed_options) {
51
  assert(options != nullptr, "invariant");
52
  assert(parsed_options != nullptr, "invariant");
53
  const char* const equal_sign = strchr(options, '=');
54
  const size_t length = strlen(options);
55
  size_t name_length = length;
56
  if (equal_sign != nullptr) {
57
    name_length = equal_sign - options;
58
    const size_t options_length = length - name_length - 1;
59
    *parsed_options = copy_string(equal_sign + 1);
60
  } else {
61
    *parsed_options = nullptr;
62
    name_length = length;
63
  }
64
  char* const name = AllocateHeap(name_length + 1, mtServiceability);
65
  jio_snprintf(name, name_length + 1, "%s", options);
66
  assert(strncmp(name, options, name_length) == 0, "invariant");
67
  return name;
68
}
69

70
JvmtiAgent::JvmtiAgent(const char* name, const char* options, bool is_absolute_path, bool dynamic /* false */) :
71
  _initialization_time(),
72
  _initialization_duration(),
73
  _next(nullptr),
74
  _name(copy_string(name)),
75
  _options(copy_string(options)),
76
  _os_lib(nullptr),
77
  _os_lib_path(nullptr),
78
  _jplis(nullptr),
79
  _loaded(false),
80
  _absolute_path(is_absolute_path),
81
  _static_lib(false),
82
  _instrument_lib(strcmp(name, "instrument") == 0),
83
  _dynamic(dynamic),
84
  _xrun(false) {}
85

86
JvmtiAgent* JvmtiAgent::next() const {
87
  return _next;
88
}
89

90
void JvmtiAgent::set_next(JvmtiAgent* agent) {
91
  _next = agent;
92
}
93

94
const char* JvmtiAgent::name() const {
95
  return _name;
96
}
97

98
const char* JvmtiAgent::options() const {
99
  return _options;
100
}
101

102
void* JvmtiAgent::os_lib() const {
103
  return _os_lib;
104
}
105

106
void JvmtiAgent::set_os_lib(void* os_lib) {
107
  _os_lib = os_lib;
108
}
109

110
void JvmtiAgent::set_os_lib_path(const char* path) {
111
  assert(path != nullptr, "invariant");
112
  if (_os_lib_path == nullptr) {
113
    _os_lib_path = copy_string(path);
114
  }
115
  assert(strcmp(_os_lib_path, path) == 0, "invariant");
116
}
117

118
const char* JvmtiAgent::os_lib_path() const {
119
  return _os_lib_path;
120
}
121

122
bool JvmtiAgent::is_loaded() const {
123
  return _loaded;
124
}
125

126
void JvmtiAgent::set_loaded() {
127
  _loaded = true;
128
}
129

130
bool JvmtiAgent::is_absolute_path() const {
131
  return _absolute_path;
132
}
133

134
bool JvmtiAgent::is_static_lib() const {
135
  return _static_lib;
136
}
137

138
void JvmtiAgent::set_static_lib() {
139
  _static_lib = true;
140
}
141

142
bool JvmtiAgent::is_dynamic() const {
143
  return _dynamic;
144
}
145

146
bool JvmtiAgent:: is_instrument_lib() const {
147
  return _instrument_lib;
148
}
149

150
bool JvmtiAgent::is_xrun() const {
151
  return _xrun;
152
}
153

154
void JvmtiAgent::set_xrun() {
155
  _xrun = true;
156
}
157

158
bool JvmtiAgent::is_jplis() const {
159
  return _jplis != nullptr;
160
}
161

162
const Ticks& JvmtiAgent::initialization_time() const {
163
  return _initialization_time;
164
}
165

166
const Tickspan& JvmtiAgent::initialization_duration() const {
167
  return _initialization_duration;
168
}
169

170
bool JvmtiAgent::is_initialized() const {
171
  return _initialization_time.value() != 0;
172
}
173

174
void JvmtiAgent::initialization_begin() {
175
  assert(!is_initialized(), "invariant");
176
  _initialization_time = Ticks::now();
177
}
178

179
void JvmtiAgent::initialization_end() {
180
  assert(is_initialized(), "invariant");
181
  assert(_initialization_duration.value() == 0, "invariant");
182
  _initialization_duration = Ticks::now() - initialization_time();
183
}
184

185
/*
186
 * The implementation builds a mapping bewteen JvmtiEnvs and JPLIS agents,
187
 * using internal JDK implementation knowledge about the way JPLIS agents
188
 * store data in their JvmtiEnv local storage.
189
 *
190
 * Please see JPLISAgent.h and JPLISAgent.c in module java.instrument.
191
 *
192
 * jvmtierror = (*jvmtienv)->SetEnvironmentLocalStorage( jvmtienv, &(agent->mNormalEnvironment));
193
 *
194
 * It is the pointer to the field agent->mNormalEnvironment that is stored in the jvmtiEnv local storage.
195
 * It has the following type:
196
 *
197
 * struct _JPLISEnvironment {
198
 *   jvmtiEnv*   mJVMTIEnv;         // the JVMTI environment
199
 *   JPLISAgent* mAgent;            // corresponding agent
200
 *   jboolean    mIsRetransformer;  // indicates if special environment
201
 * };
202
 *
203
 * We mirror this struct to get the mAgent field as an identifier.
204
 */
205

206
struct JPLISEnvironmentMirror {
207
  jvmtiEnv* mJVMTIEnv; // the JVMTI environment
208
  const void* mAgent;  // corresponding agent
209
  jboolean mIsRetransformer; // indicates if special environment
210
};
211

212
static inline const JPLISEnvironmentMirror* get_env_local_storage(JvmtiEnv* env) {
213
  assert(env != nullptr, "invariant");
214
  return reinterpret_cast<const JPLISEnvironmentMirror*>(env->get_env_local_storage());
215
}
216

217
bool JvmtiAgent::is_jplis(JvmtiEnv* env) const {
218
  assert(env != nullptr, "invariant");
219
  assert(is_instrument_lib(), "invariant");
220
  const JPLISEnvironmentMirror* const jplis_env = get_env_local_storage(env);
221
  return jplis_env != nullptr && _jplis == jplis_env->mAgent;
222
}
223

224
void JvmtiAgent::set_jplis(const void* jplis) {
225
  assert(jplis != nullptr, "invaiant");
226
  assert(is_instrument_lib(), "invariant");
227
  assert(_jplis == nullptr, "invariant");
228
  if (_options != nullptr) {
229
    // For JPLIS agents, update with the java name and options.
230
    os::free(const_cast<char*>(_name));
231
    const char* options = _options;
232
    _name = split_options_and_allocate_copy(options, &_options);
233
    os::free(const_cast<char*>(options));
234
  }
235
  _jplis = jplis;
236
}
237

238
static const char* not_found_error_msg = "Could not find agent library ";
239
static const char* missing_module_error_msg = "\nModule java.instrument may be missing from runtime image.";
240
static char ebuf[1024];
241
static char buffer[JVM_MAXPATHLEN];
242

243
static void vm_exit(const JvmtiAgent* agent, const char* sub_msg1, const char* sub_msg2) {
244
  assert(agent != nullptr, "invariant");
245
  assert(sub_msg1 != nullptr, "invariant");
246
  assert(!agent->is_instrument_lib() || sub_msg2 != nullptr, "invariant");
247
  const size_t len = strlen(not_found_error_msg) + strlen(agent->name()) + strlen(sub_msg1) + strlen(&ebuf[0]) + 1 + (agent->is_instrument_lib() ? strlen(sub_msg2) : 0);
248
  char* buf = NEW_C_HEAP_ARRAY(char, len, mtServiceability);
249
  if (agent->is_instrument_lib()) {
250
    jio_snprintf(buf, len, "%s%s%s%s%s", not_found_error_msg, agent->name(), sub_msg1, &ebuf[0], sub_msg2);
251
  } else {
252
    jio_snprintf(buf, len, "%s%s%s%s", not_found_error_msg, agent->name(), sub_msg1, &ebuf[0]);
253
  }
254
  vm_exit_during_initialization(buf, nullptr);
255
  FREE_C_HEAP_ARRAY(char, buf);
256
}
257

258
#ifdef ASSERT
259
static void assert_preload(const JvmtiAgent* agent) {
260
  assert(agent != nullptr, "invariant");
261
  assert(!agent->is_loaded(), "invariant");
262
}
263
#endif
264

265
// Check for a statically linked-in agent, i.e. in the executable.
266
// This should be the first function called when loading an agent. It is a bit special:
267
// For statically linked agents we can't rely on os_lib == nullptr because
268
// statically linked agents could have a handle of RTLD_DEFAULT which == 0 on some platforms.
269
// If this function returns true, then agent->is_static_lib() && agent->is_loaded().
270
static bool load_agent_from_executable(JvmtiAgent* agent, const char* on_load_symbols[], size_t num_symbol_entries) {
271
  DEBUG_ONLY(assert_preload(agent);)
272
  assert(on_load_symbols != nullptr, "invariant");
273
  return os::find_builtin_agent(agent, &on_load_symbols[0], num_symbol_entries);
274
}
275

276
// Load the library from the absolute path of the agent, if available.
277
static void* load_agent_from_absolute_path(JvmtiAgent* agent, bool vm_exit_on_error) {
278
  DEBUG_ONLY(assert_preload(agent);)
279
  assert(agent->is_absolute_path(), "invariant");
280
  assert(!agent->is_instrument_lib(), "invariant");
281
  void* const library = os::dll_load(agent->name(), &ebuf[0], sizeof ebuf);
282
  if (library == nullptr && vm_exit_on_error) {
283
    vm_exit(agent, " in absolute path, with error: ", nullptr);
284
  }
285
  return library;
286
}
287

288
// Agents with relative paths are loaded from the standard dll directory.
289
static void* load_agent_from_relative_path(JvmtiAgent* agent, bool vm_exit_on_error) {
290
  DEBUG_ONLY(assert_preload(agent);)
291
  assert(!agent->is_absolute_path(), "invariant");
292
  const char* const name = agent->name();
293
  void* library = nullptr;
294
  // Try to load the agent from the standard dll directory
295
  if (os::dll_locate_lib(&buffer[0], sizeof buffer, Arguments::get_dll_dir(), name)) {
296
    library = os::dll_load(&buffer[0], &ebuf[0], sizeof ebuf);
297
  }
298
  if (library == nullptr && os::dll_build_name(&buffer[0], sizeof buffer, name)) {
299
    // Try the library path directory.
300
    library = os::dll_load(&buffer[0], &ebuf[0], sizeof ebuf);
301
    if (library != nullptr) {
302
      return library;
303
    }
304
    if (vm_exit_on_error) {
305
      vm_exit(agent, " on the library path, with error: ", missing_module_error_msg);
306
    }
307
  }
308
  return library;
309
}
310

311
// For absolute and relative paths.
312
static void* load_library(JvmtiAgent* agent, const char* on_symbols[], size_t num_symbol_entries, bool vm_exit_on_error) {
313
  return agent->is_absolute_path() ? load_agent_from_absolute_path(agent, vm_exit_on_error) :
314
                                     load_agent_from_relative_path(agent, vm_exit_on_error);
315
}
316

317
// Type for the Agent_OnLoad and JVM_OnLoad entry points.
318
extern "C" {
319
  typedef jint(JNICALL* OnLoadEntry_t)(JavaVM*, char*, void*);
320
}
321

322
// Find the OnLoad entry point for -agentlib:  -agentpath:   -Xrun agents.
323
// num_symbol_entries must be passed-in since only the caller knows the number of symbols in the array.
324
static OnLoadEntry_t lookup_On_Load_entry_point(JvmtiAgent* agent, const char* on_load_symbols[], size_t num_symbol_entries) {
325
  assert(agent != nullptr, "invariant");
326
  if (!agent->is_loaded()) {
327
    if (!load_agent_from_executable(agent, on_load_symbols, num_symbol_entries)) {
328
      void* const library = load_library(agent, on_load_symbols, num_symbol_entries, /* vm exit on error */ true);
329
      assert(library != nullptr, "invariant");
330
      agent->set_os_lib(library);
331
      agent->set_loaded();
332
    }
333
  }
334
  assert(agent->is_loaded(), "invariant");
335
  // Find the OnLoad function.
336
  return CAST_TO_FN_PTR(OnLoadEntry_t, os::find_agent_function(agent, false, on_load_symbols, num_symbol_entries));
337
}
338

339
static OnLoadEntry_t lookup_JVM_OnLoad_entry_point(JvmtiAgent* lib) {
340
  const char* on_load_symbols[] = JVM_ONLOAD_SYMBOLS;
341
  return lookup_On_Load_entry_point(lib, on_load_symbols, sizeof(on_load_symbols) / sizeof(char*));
342
}
343

344
static OnLoadEntry_t lookup_Agent_OnLoad_entry_point(JvmtiAgent* agent) {
345
  const char* on_load_symbols[] = AGENT_ONLOAD_SYMBOLS;
346
  return lookup_On_Load_entry_point(agent, on_load_symbols, sizeof(on_load_symbols) / sizeof(char*));
347
}
348

349
void JvmtiAgent::convert_xrun_agent() {
350
  assert(is_xrun(), "invariant");
351
  assert(!is_loaded(), "invariant");
352
  assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_PRIMORDIAL, "invalid init sequence");
353
  OnLoadEntry_t on_load_entry = lookup_JVM_OnLoad_entry_point(this);
354
  // If there is an JVM_OnLoad function it will get called later,
355
  // otherwise see if there is an Agent_OnLoad.
356
  if (on_load_entry == nullptr) {
357
    on_load_entry = lookup_Agent_OnLoad_entry_point(this);
358
    if (on_load_entry == nullptr) {
359
      vm_exit_during_initialization("Could not find JVM_OnLoad or Agent_OnLoad function in the library", name());
360
    }
361
    _xrun = false; // converted
362
  }
363
}
364

365
// Called after the VM is initialized for -Xrun agents which have not been converted to JVMTI agents.
366
static bool invoke_JVM_OnLoad(JvmtiAgent* agent) {
367
  assert(agent != nullptr, "invariant");
368
  assert(agent->is_xrun(), "invariant");
369
  assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_PRIMORDIAL, "invalid init sequence");
370
  OnLoadEntry_t on_load_entry = lookup_JVM_OnLoad_entry_point(agent);
371
  if (on_load_entry == nullptr) {
372
    vm_exit_during_initialization("Could not find JVM_OnLoad function in -Xrun library", agent->name());
373
  }
374
  // Invoke the JVM_OnLoad function
375
  JavaThread* thread = JavaThread::current();
376
  ThreadToNativeFromVM ttn(thread);
377
  HandleMark hm(thread);
378
  extern struct JavaVM_ main_vm;
379
  const jint err = (*on_load_entry)(&main_vm, const_cast<char*>(agent->options()), nullptr);
380
  if (err != JNI_OK) {
381
    vm_exit_during_initialization("-Xrun library failed to init", agent->name());
382
  }
383
  return true;
384
}
385

386
// The newest jvmtiEnv is appended to the list,
387
// hence the JvmtiEnvIterator order is from oldest to newest.
388
static JvmtiEnv* get_last_jplis_jvmtienv() {
389
  JvmtiEnvIterator it;
390
  JvmtiEnv* env = it.first();
391
  assert(env != nullptr, "invariant");
392
  JvmtiEnv* next = it.next(env);
393
  while (next != nullptr) {
394
    assert(env != nullptr, "invariant");
395
    // get_env_local_storage() lets us find which JVMTI env map to which JPLIS agent.
396
    if (next->get_env_local_storage() == nullptr) {
397
      JvmtiEnv* temp = it.next(next);
398
      if (temp != nullptr) {
399
        next = temp;
400
        continue;
401
      }
402
      break;
403
    }
404
    env = next;
405
    next = it.next(env);
406
  }
407
  assert(env != nullptr, "invariant");
408
  assert(env->get_env_local_storage() != nullptr, "invariant");
409
  return env;
410
}
411

412
// Associate the last, i.e. most recent, JvmtiEnv that is a JPLIS agent with the current agent.
413
static void convert_to_jplis(JvmtiAgent* agent) {
414
  assert(agent != nullptr, "invariant");
415
  assert(agent->is_instrument_lib(), "invariant");
416
  JvmtiEnv* const env = get_last_jplis_jvmtienv();
417
  assert(env != nullptr, "invariant");
418
  const JPLISEnvironmentMirror* const jplis_env = get_env_local_storage(env);
419
  assert(jplis_env != nullptr, "invaiant");
420
  assert(reinterpret_cast<JvmtiEnv*>(jplis_env->mJVMTIEnv) == env, "invariant");
421
  agent->set_jplis(jplis_env->mAgent);
422
}
423

424
// Use this for JavaThreads and state is _thread_in_vm.
425
class AgentJavaThreadEventTransition : StackObj {
426
 private:
427
  ResourceMark _rm;
428
  ThreadToNativeFromVM _transition;
429
  HandleMark _hm;
430
 public:
431
  AgentJavaThreadEventTransition(JavaThread* thread) : _rm(), _transition(thread), _hm(thread) {};
432
};
433

434
class AgentEventMark : StackObj {
435
 private:
436
  JavaThread* _thread;
437
  JNIEnv* _jni_env;
438
  JvmtiThreadState::ExceptionState _saved_exception_state;
439

440
 public:
441
  AgentEventMark(JavaThread* thread) : _thread(thread),
442
                                       _jni_env(thread->jni_environment()),
443
                                       _saved_exception_state(JvmtiThreadState::ES_CLEARED) {
444
    JvmtiThreadState* state = thread->jvmti_thread_state();
445
    // we are before an event.
446
    // Save current jvmti thread exception state.
447
    if (state != nullptr) {
448
      _saved_exception_state = state->get_exception_state();
449
    }
450
    thread->push_jni_handle_block();
451
    assert(thread == JavaThread::current(), "thread must be current!");
452
    thread->frame_anchor()->make_walkable();
453
  }
454

455
  ~AgentEventMark() {
456
    _thread->pop_jni_handle_block();
457
    JvmtiThreadState* state = _thread->jvmti_thread_state();
458
    // we are continuing after an event.
459
    if (state != nullptr) {
460
      // Restore the jvmti thread exception state.
461
      state->restore_exception_state(_saved_exception_state);
462
    }
463
  }
464
};
465

466
class AgentThreadEventMark : public AgentEventMark {
467
 private:
468
  jobject _jthread;
469
 public:
470
  AgentThreadEventMark(JavaThread* thread) : AgentEventMark(thread),
471
                                             _jthread(JNIHandles::make_local(thread, thread->threadObj())) {}
472
  jthread jni_thread() { return (jthread)_jthread; }
473
};
474

475
static void unload_library(JvmtiAgent* agent, void* library) {
476
  assert(agent != nullptr, "invariant");
477
  assert(agent->is_loaded(), "invariant");
478
  if (!agent->is_static_lib()) {
479
    assert(library != nullptr, "invariant");
480
    os::dll_unload(library);
481
  }
482
}
483

484
// type for the Agent_OnAttach entry point
485
extern "C" {
486
  typedef jint(JNICALL* OnAttachEntry_t)(JavaVM*, char*, void*);
487
}
488

489
// Loading the agent by invoking Agent_OnAttach.
490
// This function is called before the agent is added to JvmtiAgentList.
491
static bool invoke_Agent_OnAttach(JvmtiAgent* agent, outputStream* st) {
492
  if (!EnableDynamicAgentLoading) {
493
    st->print_cr("Dynamic agent loading is not enabled. "
494
                 "Use -XX:+EnableDynamicAgentLoading to launch target VM.");
495
    return false;
496
  }
497
  DEBUG_ONLY(assert_preload(agent);)
498
  assert(agent->is_dynamic(), "invariant");
499
  assert(st != nullptr, "invariant");
500
  assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE, "not in live phase!");
501
  const char* on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS;
502
  const size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols);
503
  void* library = nullptr;
504
  bool previously_loaded;
505
  if (load_agent_from_executable(agent, &on_attach_symbols[0], num_symbol_entries)) {
506
    previously_loaded = JvmtiAgentList::is_static_lib_loaded(agent->name());
507
  } else {
508
    library = load_library(agent, &on_attach_symbols[0], num_symbol_entries, /* vm_exit_on_error */ false);
509
    if (library == nullptr) {
510
      st->print_cr("%s was not loaded.", agent->name());
511
      if (*ebuf != '\0') {
512
        st->print_cr("%s", &ebuf[0]);
513
      }
514
      return false;
515
    }
516
    agent->set_os_lib_path(&buffer[0]);
517
    agent->set_os_lib(library);
518
    agent->set_loaded();
519
    previously_loaded = JvmtiAgentList::is_dynamic_lib_loaded(library);
520
  }
521

522
  // Print warning if agent was not previously loaded and EnableDynamicAgentLoading not enabled on the command line.
523
  if (!previously_loaded && !FLAG_IS_CMDLINE(EnableDynamicAgentLoading) && !agent->is_instrument_lib()) {
524
    jio_fprintf(defaultStream::error_stream(),
525
      "WARNING: A JVM TI agent has been loaded dynamically (%s)\n"
526
      "WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning\n"
527
      "WARNING: Dynamic loading of agents will be disallowed by default in a future release\n", agent->name());
528
  }
529

530
  assert(agent->is_loaded(), "invariant");
531
  // The library was loaded so we attempt to lookup and invoke the Agent_OnAttach function.
532
  OnAttachEntry_t on_attach_entry = CAST_TO_FN_PTR(OnAttachEntry_t,
533
                                                   os::find_agent_function(agent, false, &on_attach_symbols[0], num_symbol_entries));
534

535
  if (on_attach_entry == nullptr) {
536
    st->print_cr("%s is not available in %s", on_attach_symbols[0], agent->name());
537
    unload_library(agent, library);
538
    return false;
539
  }
540

541
  // Invoke the Agent_OnAttach function
542
  JavaThread* thread = JavaThread::current();
543
  jint result = JNI_ERR;
544
  {
545
    extern struct JavaVM_ main_vm;
546
    AgentThreadEventMark jem(thread);
547
    AgentJavaThreadEventTransition jet(thread);
548

549
    agent->initialization_begin();
550

551
    result = (*on_attach_entry)(&main_vm, (char*)agent->options(), nullptr);
552

553
    agent->initialization_end();
554

555
    // Agent_OnAttach may have used JNI
556
    if (thread->is_pending_jni_exception_check()) {
557
      thread->clear_pending_jni_exception_check();
558
    }
559
  }
560

561
  // Agent_OnAttach may have used JNI
562
  if (thread->has_pending_exception()) {
563
    thread->clear_pending_exception();
564
  }
565

566
  st->print_cr("return code: %d", result);
567

568
  if (result != JNI_OK) {
569
    unload_library(agent, library);
570
    return false;
571
  }
572

573
  if (agent->is_instrument_lib()) {
574
    // Convert the instrument lib to the actual JPLIS / javaagent it represents.
575
    convert_to_jplis(agent);
576
  }
577
  return true;
578
}
579

580
// CDS dumping does not support native JVMTI agent.
581
// CDS dumping supports Java agent if the AllowArchivingWithJavaAgent diagnostic option is specified.
582
static void check_cds_dump(JvmtiAgent* agent) {
583
  assert(agent != nullptr, "invariant");
584
  assert(CDSConfig::is_dumping_archive(), "invariant");
585
  if (!agent->is_instrument_lib()) {
586
    vm_exit_during_cds_dumping("CDS dumping does not support native JVMTI agent, name", agent->name());
587
  }
588
  if (!AllowArchivingWithJavaAgent) {
589
    vm_exit_during_cds_dumping(
590
      "Must enable AllowArchivingWithJavaAgent in order to run Java agent during CDS dumping");
591
  }
592
}
593

594
// Loading the agent by invoking Agent_OnLoad.
595
static bool invoke_Agent_OnLoad(JvmtiAgent* agent) {
596
  assert(agent != nullptr, "invariant");
597
  assert(!agent->is_xrun(), "invariant");
598
  assert(!agent->is_dynamic(), "invariant");
599
  assert(JvmtiEnvBase::get_phase() == JVMTI_PHASE_ONLOAD, "invariant");
600
  if (CDSConfig::is_dumping_archive()) {
601
    check_cds_dump(agent);
602
  }
603
  OnLoadEntry_t on_load_entry = lookup_Agent_OnLoad_entry_point(agent);
604
  if (on_load_entry == nullptr) {
605
    vm_exit_during_initialization("Could not find Agent_OnLoad function in the agent library", agent->name());
606
  }
607
  // Invoke the Agent_OnLoad function
608
  extern struct JavaVM_ main_vm;
609
  if ((*on_load_entry)(&main_vm, const_cast<char*>(agent->options()), nullptr) != JNI_OK) {
610
    vm_exit_during_initialization("agent library failed Agent_OnLoad", agent->name());
611
  }
612
  // Convert the instrument lib to the actual JPLIS / javaagent it represents.
613
  if (agent->is_instrument_lib()) {
614
    convert_to_jplis(agent);
615
  }
616
  return true;
617
}
618

619
bool JvmtiAgent::load(outputStream* st /* nullptr */) {
620
  if (is_xrun()) {
621
    return invoke_JVM_OnLoad(this);
622
  }
623
  return is_dynamic() ? invoke_Agent_OnAttach(this, st) : invoke_Agent_OnLoad(this);
624
}
625

626
extern "C" {
627
  typedef void (JNICALL* Agent_OnUnload_t)(JavaVM*);
628
}
629

630
void JvmtiAgent::unload() {
631
  const char* on_unload_symbols[] = AGENT_ONUNLOAD_SYMBOLS;
632
  // Find the Agent_OnUnload function.
633
  Agent_OnUnload_t unload_entry = CAST_TO_FN_PTR(Agent_OnUnload_t,
634
                                                 os::find_agent_function(this, false, &on_unload_symbols[0], ARRAY_SIZE(on_unload_symbols)));
635
  if (unload_entry != nullptr) {
636
    // Invoke the Agent_OnUnload function
637
    JavaThread* thread = JavaThread::current();
638
    ThreadToNativeFromVM ttn(thread);
639
    HandleMark hm(thread);
640
    extern struct JavaVM_ main_vm;
641
    (*unload_entry)(&main_vm);
642
  }
643
}
644

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.