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