1/*
2 * Copyright (c) 2005, 2017, 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
25#include "precompiled.hpp"
26#include "classfile/javaClasses.hpp"
27#include "classfile/systemDictionary.hpp"
28#include "gc/shared/vmGCOperations.hpp"
29#include "memory/resourceArea.hpp"
30#include "oops/oop.inline.hpp"
31#include "prims/jvmtiExport.hpp"
32#include "runtime/arguments.hpp"
33#include "runtime/globals.hpp"
34#include "runtime/java.hpp"
35#include "runtime/javaCalls.hpp"
36#include "runtime/os.hpp"
37#include "services/attachListener.hpp"
38#include "services/diagnosticCommand.hpp"
39#include "services/heapDumper.hpp"
40#include "services/writeableFlags.hpp"
41#include "utilities/debug.hpp"
42#include "utilities/formatBuffer.hpp"
43
44volatile bool AttachListener::_initialized;
45
46// Implementation of "properties" command.
47//
48// Invokes VMSupport.serializePropertiesToByteArray to serialize
49// the system properties into a byte array.
50
51static InstanceKlass* load_and_initialize_klass(Symbol* sh, TRAPS) {
52  Klass* k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
53  InstanceKlass* ik = InstanceKlass::cast(k);
54  if (ik->should_be_initialized()) {
55    ik->initialize(CHECK_NULL);
56  }
57  return ik;
58}
59
60static jint get_properties(AttachOperation* op, outputStream* out, Symbol* serializePropertiesMethod) {
61  Thread* THREAD = Thread::current();
62  HandleMark hm;
63
64  // load VMSupport
65  Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();
66  InstanceKlass* k = load_and_initialize_klass(klass, THREAD);
67  if (HAS_PENDING_EXCEPTION) {
68    java_lang_Throwable::print(PENDING_EXCEPTION, out);
69    CLEAR_PENDING_EXCEPTION;
70    return JNI_ERR;
71  }
72
73  // invoke the serializePropertiesToByteArray method
74  JavaValue result(T_OBJECT);
75  JavaCallArguments args;
76
77
78  Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
79  JavaCalls::call_static(&result,
80                         k,
81                         serializePropertiesMethod,
82                         signature,
83                         &args,
84                         THREAD);
85  if (HAS_PENDING_EXCEPTION) {
86    java_lang_Throwable::print(PENDING_EXCEPTION, out);
87    CLEAR_PENDING_EXCEPTION;
88    return JNI_ERR;
89  }
90
91  // The result should be a [B
92  oop res = (oop)result.get_jobject();
93  assert(res->is_typeArray(), "just checking");
94  assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
95
96  // copy the bytes to the output stream
97  typeArrayOop ba = typeArrayOop(res);
98  jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
99  out->print_raw((const char*)addr, ba->length());
100
101  return JNI_OK;
102}
103
104// Implementation of "load" command.
105static jint load_agent(AttachOperation* op, outputStream* out) {
106  // get agent name and options
107  const char* agent = op->arg(0);
108  const char* absParam = op->arg(1);
109  const char* options = op->arg(2);
110
111  // If loading a java agent then need to ensure that the java.instrument module is loaded
112  if (strcmp(agent, "instrument") == 0) {
113    Thread* THREAD = Thread::current();
114    ResourceMark rm(THREAD);
115    HandleMark hm(THREAD);
116    JavaValue result(T_OBJECT);
117    Handle h_module_name = java_lang_String::create_from_str("java.instrument", THREAD);
118    JavaCalls::call_static(&result,
119                           SystemDictionary::module_Modules_klass(),
120                           vmSymbols::loadModule_name(),
121                           vmSymbols::loadModule_signature(),
122                           h_module_name,
123                           THREAD);
124    if (HAS_PENDING_EXCEPTION) {
125      java_lang_Throwable::print(PENDING_EXCEPTION, out);
126      CLEAR_PENDING_EXCEPTION;
127      return JNI_ERR;
128    }
129  }
130
131  return JvmtiExport::load_agent_library(agent, absParam, options, out);
132}
133
134// Implementation of "properties" command.
135// See also: PrintSystemPropertiesDCmd class
136static jint get_system_properties(AttachOperation* op, outputStream* out) {
137  return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name());
138}
139
140// Implementation of "agent_properties" command.
141static jint get_agent_properties(AttachOperation* op, outputStream* out) {
142  return get_properties(op, out, vmSymbols::serializeAgentPropertiesToByteArray_name());
143}
144
145// Implementation of "datadump" command.
146//
147// Raises a SIGBREAK signal so that VM dump threads, does deadlock detection,
148// etc. In theory this command should only post a DataDumpRequest to any
149// JVMTI environment that has enabled this event. However it's useful to
150// trigger the SIGBREAK handler.
151
152static jint data_dump(AttachOperation* op, outputStream* out) {
153  if (!ReduceSignalUsage) {
154    AttachListener::pd_data_dump();
155  } else {
156    if (JvmtiExport::should_post_data_dump()) {
157      JvmtiExport::post_data_dump();
158    }
159  }
160  return JNI_OK;
161}
162
163// Implementation of "threaddump" command - essentially a remote ctrl-break
164// See also: ThreadDumpDCmd class
165//
166static jint thread_dump(AttachOperation* op, outputStream* out) {
167  bool print_concurrent_locks = false;
168  if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) {
169    print_concurrent_locks = true;
170  }
171
172  // thread stacks
173  VM_PrintThreads op1(out, print_concurrent_locks);
174  VMThread::execute(&op1);
175
176  // JNI global handles
177  VM_PrintJNI op2(out);
178  VMThread::execute(&op2);
179
180  // Deadlock detection
181  VM_FindDeadlocks op3(out);
182  VMThread::execute(&op3);
183
184  return JNI_OK;
185}
186
187// A jcmd attach operation request was received, which will now
188// dispatch to the diagnostic commands used for serviceability functions.
189static jint jcmd(AttachOperation* op, outputStream* out) {
190  Thread* THREAD = Thread::current();
191  // All the supplied jcmd arguments are stored as a single
192  // string (op->arg(0)). This is parsed by the Dcmd framework.
193  DCmd::parse_and_execute(DCmd_Source_AttachAPI, out, op->arg(0), ' ', THREAD);
194  if (HAS_PENDING_EXCEPTION) {
195    java_lang_Throwable::print(PENDING_EXCEPTION, out);
196    out->cr();
197    CLEAR_PENDING_EXCEPTION;
198    return JNI_ERR;
199  }
200  return JNI_OK;
201}
202
203// Implementation of "dumpheap" command.
204// See also: HeapDumpDCmd class
205//
206// Input arguments :-
207//   arg0: Name of the dump file
208//   arg1: "-live" or "-all"
209jint dump_heap(AttachOperation* op, outputStream* out) {
210  const char* path = op->arg(0);
211  if (path == NULL || path[0] == '\0') {
212    out->print_cr("No dump file specified");
213  } else {
214    bool live_objects_only = true;   // default is true to retain the behavior before this change is made
215    const char* arg1 = op->arg(1);
216    if (arg1 != NULL && (strlen(arg1) > 0)) {
217      if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
218        out->print_cr("Invalid argument to dumpheap operation: %s", arg1);
219        return JNI_ERR;
220      }
221      live_objects_only = strcmp(arg1, "-live") == 0;
222    }
223
224    // Request a full GC before heap dump if live_objects_only = true
225    // This helps reduces the amount of unreachable objects in the dump
226    // and makes it easier to browse.
227    HeapDumper dumper(live_objects_only /* request GC */);
228    int res = dumper.dump(op->arg(0));
229    if (res == 0) {
230      out->print_cr("Heap dump file created");
231    } else {
232      // heap dump failed
233      ResourceMark rm;
234      char* error = dumper.error_as_C_string();
235      if (error == NULL) {
236        out->print_cr("Dump failed - reason unknown");
237      } else {
238        out->print_cr("%s", error);
239      }
240    }
241  }
242  return JNI_OK;
243}
244
245// Implementation of "inspectheap" command
246// See also: ClassHistogramDCmd class
247//
248// Input arguments :-
249//   arg0: "-live" or "-all"
250static jint heap_inspection(AttachOperation* op, outputStream* out) {
251  bool live_objects_only = true;   // default is true to retain the behavior before this change is made
252  const char* arg0 = op->arg(0);
253  if (arg0 != NULL && (strlen(arg0) > 0)) {
254    if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) {
255      out->print_cr("Invalid argument to inspectheap operation: %s", arg0);
256      return JNI_ERR;
257    }
258    live_objects_only = strcmp(arg0, "-live") == 0;
259  }
260  VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */);
261  VMThread::execute(&heapop);
262  return JNI_OK;
263}
264
265// Implementation of "setflag" command
266static jint set_flag(AttachOperation* op, outputStream* out) {
267
268  const char* name = NULL;
269  if ((name = op->arg(0)) == NULL) {
270    out->print_cr("flag name is missing");
271    return JNI_ERR;
272  }
273
274  FormatBuffer<80> err_msg("%s", "");
275
276  int ret = WriteableFlags::set_flag(op->arg(0), op->arg(1), Flag::ATTACH_ON_DEMAND, err_msg);
277  if (ret != Flag::SUCCESS) {
278    if (ret == Flag::NON_WRITABLE) {
279      // if the flag is not manageable try to change it through
280      // the platform dependent implementation
281      return AttachListener::pd_set_flag(op, out);
282    } else {
283      out->print_cr("%s", err_msg.buffer());
284    }
285
286    return JNI_ERR;
287  }
288  return JNI_OK;
289}
290
291// Implementation of "printflag" command
292// See also: PrintVMFlagsDCmd class
293static jint print_flag(AttachOperation* op, outputStream* out) {
294  const char* name = NULL;
295  if ((name = op->arg(0)) == NULL) {
296    out->print_cr("flag name is missing");
297    return JNI_ERR;
298  }
299  Flag* f = Flag::find_flag((char*)name, strlen(name));
300  if (f) {
301    f->print_as_flag(out);
302    out->cr();
303  } else {
304    out->print_cr("no such flag '%s'", name);
305  }
306  return JNI_OK;
307}
308
309// Table to map operation names to functions.
310
311// names must be of length <= AttachOperation::name_length_max
312static AttachOperationFunctionInfo funcs[] = {
313  { "agentProperties",  get_agent_properties },
314  { "datadump",         data_dump },
315  { "dumpheap",         dump_heap },
316  { "load",             load_agent },
317  { "properties",       get_system_properties },
318  { "threaddump",       thread_dump },
319  { "inspectheap",      heap_inspection },
320  { "setflag",          set_flag },
321  { "printflag",        print_flag },
322  { "jcmd",             jcmd },
323  { NULL,               NULL }
324};
325
326
327
328// The Attach Listener threads services a queue. It dequeues an operation
329// from the queue, examines the operation name (command), and dispatches
330// to the corresponding function to perform the operation.
331
332static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {
333  os::set_priority(thread, NearMaxPriority);
334
335  thread->record_stack_base_and_size();
336
337  if (AttachListener::pd_init() != 0) {
338    return;
339  }
340  AttachListener::set_initialized();
341
342  for (;;) {
343    AttachOperation* op = AttachListener::dequeue();
344    if (op == NULL) {
345      return;   // dequeue failed or shutdown
346    }
347
348    ResourceMark rm;
349    bufferedStream st;
350    jint res = JNI_OK;
351
352    // handle special detachall operation
353    if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) {
354      AttachListener::detachall();
355    } else if (!EnableDynamicAgentLoading && strcmp(op->name(), "load") == 0) {
356      st.print("Dynamic agent loading is not enabled. "
357               "Use -XX:+EnableDynamicAgentLoading to launch target VM.");
358      res = JNI_ERR;
359    } else {
360      // find the function to dispatch too
361      AttachOperationFunctionInfo* info = NULL;
362      for (int i=0; funcs[i].name != NULL; i++) {
363        const char* name = funcs[i].name;
364        assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max");
365        if (strcmp(op->name(), name) == 0) {
366          info = &(funcs[i]);
367          break;
368        }
369      }
370
371      // check for platform dependent attach operation
372      if (info == NULL) {
373        info = AttachListener::pd_find_operation(op->name());
374      }
375
376      if (info != NULL) {
377        // dispatch to the function that implements this operation
378        res = (info->func)(op, &st);
379      } else {
380        st.print("Operation %s not recognized!", op->name());
381        res = JNI_ERR;
382      }
383    }
384
385    // operation complete - send result and output to client
386    op->complete(res, &st);
387  }
388}
389
390bool AttachListener::has_init_error(TRAPS) {
391  if (HAS_PENDING_EXCEPTION) {
392    tty->print_cr("Exception in VM (AttachListener::init) : ");
393    java_lang_Throwable::print(PENDING_EXCEPTION, tty);
394    tty->cr();
395
396    CLEAR_PENDING_EXCEPTION;
397
398    return true;
399  } else {
400    return false;
401  }
402}
403
404// Starts the Attach Listener thread
405void AttachListener::init() {
406  EXCEPTION_MARK;
407  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, THREAD);
408  if (has_init_error(THREAD)) {
409    return;
410  }
411
412  InstanceKlass* klass = InstanceKlass::cast(k);
413  instanceHandle thread_oop = klass->allocate_instance_handle(THREAD);
414  if (has_init_error(THREAD)) {
415    return;
416  }
417
418  const char thread_name[] = "Attach Listener";
419  Handle string = java_lang_String::create_from_str(thread_name, THREAD);
420  if (has_init_error(THREAD)) {
421    return;
422  }
423
424  // Initialize thread_oop to put it into the system threadGroup
425  Handle thread_group (THREAD, Universe::system_thread_group());
426  JavaValue result(T_VOID);
427  JavaCalls::call_special(&result, thread_oop,
428                       klass,
429                       vmSymbols::object_initializer_name(),
430                       vmSymbols::threadgroup_string_void_signature(),
431                       thread_group,
432                       string,
433                       THREAD);
434
435  if (has_init_error(THREAD)) {
436    return;
437  }
438
439  Klass* group = SystemDictionary::ThreadGroup_klass();
440  JavaCalls::call_special(&result,
441                        thread_group,
442                        group,
443                        vmSymbols::add_method_name(),
444                        vmSymbols::thread_void_signature(),
445                        thread_oop,             // ARG 1
446                        THREAD);
447  if (has_init_error(THREAD)) {
448    return;
449  }
450
451  { MutexLocker mu(Threads_lock);
452    JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry);
453
454    // Check that thread and osthread were created
455    if (listener_thread == NULL || listener_thread->osthread() == NULL) {
456      vm_exit_during_initialization("java.lang.OutOfMemoryError",
457                                    os::native_thread_creation_failed_msg());
458    }
459
460    java_lang_Thread::set_thread(thread_oop(), listener_thread);
461    java_lang_Thread::set_daemon(thread_oop());
462
463    listener_thread->set_threadObj(thread_oop());
464    Threads::add(listener_thread);
465    Thread::start(listener_thread);
466  }
467}
468
469// Performs clean-up tasks on platforms where we can detect that the last
470// client has detached
471void AttachListener::detachall() {
472  // call the platform dependent clean-up
473  pd_detachall();
474}
475