Tue, 23 Nov 2010 13:22:55 -0800
6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg
1 /*
2 * Copyright (c) 2005, 2010, 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 */
25 #include "precompiled.hpp"
26 #include "classfile/javaClasses.hpp"
27 #include "classfile/systemDictionary.hpp"
28 #include "gc_implementation/shared/vmGCOperations.hpp"
29 #include "memory/resourceArea.hpp"
30 #include "prims/jvmtiExport.hpp"
31 #include "runtime/arguments.hpp"
32 #include "runtime/globals.hpp"
33 #include "runtime/java.hpp"
34 #include "runtime/javaCalls.hpp"
35 #include "runtime/os.hpp"
36 #include "services/attachListener.hpp"
37 #include "services/heapDumper.hpp"
39 volatile bool AttachListener::_initialized;
41 // Implementation of "properties" command.
42 //
43 // Invokes sun.misc.VMSupport.serializePropertiesToByteArray to serialize
44 // the system properties into a byte array.
46 static klassOop load_and_initialize_klass(symbolHandle sh, TRAPS) {
47 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
48 instanceKlassHandle ik (THREAD, k);
49 if (ik->should_be_initialized()) {
50 ik->initialize(CHECK_NULL);
51 }
52 return ik();
53 }
55 static jint get_properties(AttachOperation* op, outputStream* out, symbolHandle serializePropertiesMethod) {
56 Thread* THREAD = Thread::current();
57 HandleMark hm;
59 // load sun.misc.VMSupport
60 symbolHandle klass = vmSymbolHandles::sun_misc_VMSupport();
61 klassOop k = load_and_initialize_klass(klass, THREAD);
62 if (HAS_PENDING_EXCEPTION) {
63 java_lang_Throwable::print(PENDING_EXCEPTION, out);
64 CLEAR_PENDING_EXCEPTION;
65 return JNI_ERR;
66 }
67 instanceKlassHandle ik(THREAD, k);
69 // invoke the serializePropertiesToByteArray method
70 JavaValue result(T_OBJECT);
71 JavaCallArguments args;
74 symbolHandle signature = vmSymbolHandles::serializePropertiesToByteArray_signature();
75 JavaCalls::call_static(&result,
76 ik,
77 serializePropertiesMethod,
78 signature,
79 &args,
80 THREAD);
81 if (HAS_PENDING_EXCEPTION) {
82 java_lang_Throwable::print(PENDING_EXCEPTION, out);
83 CLEAR_PENDING_EXCEPTION;
84 return JNI_ERR;
85 }
87 // The result should be a [B
88 oop res = (oop)result.get_jobject();
89 assert(res->is_typeArray(), "just checking");
90 assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
92 // copy the bytes to the output stream
93 typeArrayOop ba = typeArrayOop(res);
94 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
95 out->print_raw((const char*)addr, ba->length());
97 return JNI_OK;
98 }
100 // Implementation of "properties" command.
101 static jint get_system_properties(AttachOperation* op, outputStream* out) {
102 return get_properties(op, out, vmSymbolHandles::serializePropertiesToByteArray_name());
103 }
105 // Implementation of "agent_properties" command.
106 static jint get_agent_properties(AttachOperation* op, outputStream* out) {
107 return get_properties(op, out, vmSymbolHandles::serializeAgentPropertiesToByteArray_name());
108 }
110 // Implementation of "datadump" command.
111 //
112 // Raises a SIGBREAK signal so that VM dump threads, does deadlock detection,
113 // etc. In theory this command should only post a DataDumpRequest to any
114 // JVMTI environment that has enabled this event. However it's useful to
115 // trigger the SIGBREAK handler.
117 static jint data_dump(AttachOperation* op, outputStream* out) {
118 if (!ReduceSignalUsage) {
119 AttachListener::pd_data_dump();
120 } else {
121 if (JvmtiExport::should_post_data_dump()) {
122 JvmtiExport::post_data_dump();
123 }
124 }
125 return JNI_OK;
126 }
128 // Implementation of "threaddump" command - essentially a remote ctrl-break
129 //
130 static jint thread_dump(AttachOperation* op, outputStream* out) {
131 bool print_concurrent_locks = false;
132 if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) {
133 print_concurrent_locks = true;
134 }
136 // thread stacks
137 VM_PrintThreads op1(out, print_concurrent_locks);
138 VMThread::execute(&op1);
140 // JNI global handles
141 VM_PrintJNI op2(out);
142 VMThread::execute(&op2);
144 // Deadlock detection
145 VM_FindDeadlocks op3(out);
146 VMThread::execute(&op3);
148 return JNI_OK;
149 }
151 #ifndef SERVICES_KERNEL // Heap dumping not supported
152 // Implementation of "dumpheap" command.
153 //
154 // Input arguments :-
155 // arg0: Name of the dump file
156 // arg1: "-live" or "-all"
157 jint dump_heap(AttachOperation* op, outputStream* out) {
158 const char* path = op->arg(0);
159 if (path == NULL || path[0] == '\0') {
160 out->print_cr("No dump file specified");
161 } else {
162 bool live_objects_only = true; // default is true to retain the behavior before this change is made
163 const char* arg1 = op->arg(1);
164 if (arg1 != NULL && (strlen(arg1) > 0)) {
165 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
166 out->print_cr("Invalid argument to dumpheap operation: %s", arg1);
167 return JNI_ERR;
168 }
169 live_objects_only = strcmp(arg1, "-live") == 0;
170 }
172 // Request a full GC before heap dump if live_objects_only = true
173 // This helps reduces the amount of unreachable objects in the dump
174 // and makes it easier to browse.
175 HeapDumper dumper(live_objects_only /* request GC */);
176 int res = dumper.dump(op->arg(0));
177 if (res == 0) {
178 out->print_cr("Heap dump file created");
179 } else {
180 // heap dump failed
181 ResourceMark rm;
182 char* error = dumper.error_as_C_string();
183 if (error == NULL) {
184 out->print_cr("Dump failed - reason unknown");
185 } else {
186 out->print_cr("%s", error);
187 }
188 }
189 }
190 return JNI_OK;
191 }
192 #endif // SERVICES_KERNEL
194 // Implementation of "inspectheap" command
195 //
196 // Input arguments :-
197 // arg0: "-live" or "-all"
198 static jint heap_inspection(AttachOperation* op, outputStream* out) {
199 bool live_objects_only = true; // default is true to retain the behavior before this change is made
200 const char* arg0 = op->arg(0);
201 if (arg0 != NULL && (strlen(arg0) > 0)) {
202 if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) {
203 out->print_cr("Invalid argument to inspectheap operation: %s", arg0);
204 return JNI_ERR;
205 }
206 live_objects_only = strcmp(arg0, "-live") == 0;
207 }
208 VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */);
209 VMThread::execute(&heapop);
210 return JNI_OK;
211 }
213 // set a boolean global flag using value from AttachOperation
214 static jint set_bool_flag(const char* name, AttachOperation* op, outputStream* out) {
215 bool value = true;
216 const char* arg1;
217 if ((arg1 = op->arg(1)) != NULL) {
218 int tmp;
219 int n = sscanf(arg1, "%d", &tmp);
220 if (n != 1) {
221 out->print_cr("flag value must be a boolean (1 or 0)");
222 return JNI_ERR;
223 }
224 value = (tmp != 0);
225 }
226 bool res = CommandLineFlags::boolAtPut((char*)name, &value, ATTACH_ON_DEMAND);
227 if (! res) {
228 out->print_cr("setting flag %s failed", name);
229 }
230 return res? JNI_OK : JNI_ERR;
231 }
233 // set a intx global flag using value from AttachOperation
234 static jint set_intx_flag(const char* name, AttachOperation* op, outputStream* out) {
235 intx value;
236 const char* arg1;
237 if ((arg1 = op->arg(1)) != NULL) {
238 int n = sscanf(arg1, INTX_FORMAT, &value);
239 if (n != 1) {
240 out->print_cr("flag value must be an integer");
241 return JNI_ERR;
242 }
243 }
244 bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
245 if (! res) {
246 out->print_cr("setting flag %s failed", name);
247 }
249 return res? JNI_OK : JNI_ERR;
250 }
252 // set a uintx global flag using value from AttachOperation
253 static jint set_uintx_flag(const char* name, AttachOperation* op, outputStream* out) {
254 uintx value;
255 const char* arg1;
256 if ((arg1 = op->arg(1)) != NULL) {
257 int n = sscanf(arg1, UINTX_FORMAT, &value);
258 if (n != 1) {
259 out->print_cr("flag value must be an unsigned integer");
260 return JNI_ERR;
261 }
262 }
263 bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
264 if (! res) {
265 out->print_cr("setting flag %s failed", name);
266 }
268 return res? JNI_OK : JNI_ERR;
269 }
271 // set a uint64_t global flag using value from AttachOperation
272 static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStream* out) {
273 uint64_t value;
274 const char* arg1;
275 if ((arg1 = op->arg(1)) != NULL) {
276 int n = sscanf(arg1, UINT64_FORMAT, &value);
277 if (n != 1) {
278 out->print_cr("flag value must be an unsigned 64-bit integer");
279 return JNI_ERR;
280 }
281 }
282 bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND);
283 if (! res) {
284 out->print_cr("setting flag %s failed", name);
285 }
287 return res? JNI_OK : JNI_ERR;
288 }
290 // set a string global flag using value from AttachOperation
291 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
292 const char* value;
293 if ((value = op->arg(1)) == NULL) {
294 out->print_cr("flag value must be a string");
295 return JNI_ERR;
296 }
297 bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND);
298 if (res) {
299 FREE_C_HEAP_ARRAY(char, value);
300 } else {
301 out->print_cr("setting flag %s failed", name);
302 }
304 return res? JNI_OK : JNI_ERR;
305 }
307 // Implementation of "setflag" command
308 static jint set_flag(AttachOperation* op, outputStream* out) {
310 const char* name = NULL;
311 if ((name = op->arg(0)) == NULL) {
312 out->print_cr("flag name is missing");
313 return JNI_ERR;
314 }
316 Flag* f = Flag::find_flag((char*)name, strlen(name));
317 if (f && f->is_external() && f->is_writeable()) {
318 if (f->is_bool()) {
319 return set_bool_flag(name, op, out);
320 } else if (f->is_intx()) {
321 return set_intx_flag(name, op, out);
322 } else if (f->is_uintx()) {
323 return set_uintx_flag(name, op, out);
324 } else if (f->is_uint64_t()) {
325 return set_uint64_t_flag(name, op, out);
326 } else if (f->is_ccstr()) {
327 return set_ccstr_flag(name, op, out);
328 } else {
329 ShouldNotReachHere();
330 return JNI_ERR;
331 }
332 } else {
333 return AttachListener::pd_set_flag(op, out);
334 }
335 }
337 // Implementation of "printflag" command
338 static jint print_flag(AttachOperation* op, outputStream* out) {
339 const char* name = NULL;
340 if ((name = op->arg(0)) == NULL) {
341 out->print_cr("flag name is missing");
342 return JNI_ERR;
343 }
344 Flag* f = Flag::find_flag((char*)name, strlen(name));
345 if (f) {
346 f->print_as_flag(out);
347 out->print_cr("");
348 } else {
349 out->print_cr("no such flag '%s'", name);
350 }
351 return JNI_OK;
352 }
354 // Table to map operation names to functions.
356 // names must be of length <= AttachOperation::name_length_max
357 static AttachOperationFunctionInfo funcs[] = {
358 { "agentProperties", get_agent_properties },
359 { "datadump", data_dump },
360 #ifndef SERVICES_KERNEL
361 { "dumpheap", dump_heap },
362 #endif // SERVICES_KERNEL
363 { "load", JvmtiExport::load_agent_library },
364 { "properties", get_system_properties },
365 { "threaddump", thread_dump },
366 { "inspectheap", heap_inspection },
367 { "setflag", set_flag },
368 { "printflag", print_flag },
369 { NULL, NULL }
370 };
374 // The Attach Listener threads services a queue. It dequeues an operation
375 // from the queue, examines the operation name (command), and dispatches
376 // to the corresponding function to perform the operation.
378 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {
379 os::set_priority(thread, NearMaxPriority);
381 if (AttachListener::pd_init() != 0) {
382 return;
383 }
384 AttachListener::set_initialized();
386 for (;;) {
387 AttachOperation* op = AttachListener::dequeue();
388 if (op == NULL) {
389 return; // dequeue failed or shutdown
390 }
392 ResourceMark rm;
393 bufferedStream st;
394 jint res = JNI_OK;
396 // handle special detachall operation
397 if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) {
398 AttachListener::detachall();
399 } else {
400 // find the function to dispatch too
401 AttachOperationFunctionInfo* info = NULL;
402 for (int i=0; funcs[i].name != NULL; i++) {
403 const char* name = funcs[i].name;
404 assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max");
405 if (strcmp(op->name(), name) == 0) {
406 info = &(funcs[i]);
407 break;
408 }
409 }
411 // check for platform dependent attach operation
412 if (info == NULL) {
413 info = AttachListener::pd_find_operation(op->name());
414 }
416 if (info != NULL) {
417 // dispatch to the function that implements this operation
418 res = (info->func)(op, &st);
419 } else {
420 st.print("Operation %s not recognized!", op->name());
421 res = JNI_ERR;
422 }
423 }
425 // operation complete - send result and output to client
426 op->complete(res, &st);
427 }
428 }
430 // Starts the Attach Listener thread
431 void AttachListener::init() {
432 EXCEPTION_MARK;
433 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK);
434 instanceKlassHandle klass (THREAD, k);
435 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
437 const char thread_name[] = "Attach Listener";
438 Handle string = java_lang_String::create_from_str(thread_name, CHECK);
440 // Initialize thread_oop to put it into the system threadGroup
441 Handle thread_group (THREAD, Universe::system_thread_group());
442 JavaValue result(T_VOID);
443 JavaCalls::call_special(&result, thread_oop,
444 klass,
445 vmSymbolHandles::object_initializer_name(),
446 vmSymbolHandles::threadgroup_string_void_signature(),
447 thread_group,
448 string,
449 CHECK);
451 KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass());
452 JavaCalls::call_special(&result,
453 thread_group,
454 group,
455 vmSymbolHandles::add_method_name(),
456 vmSymbolHandles::thread_void_signature(),
457 thread_oop, // ARG 1
458 CHECK);
460 { MutexLocker mu(Threads_lock);
461 JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry);
463 // Check that thread and osthread were created
464 if (listener_thread == NULL || listener_thread->osthread() == NULL) {
465 vm_exit_during_initialization("java.lang.OutOfMemoryError",
466 "unable to create new native thread");
467 }
469 java_lang_Thread::set_thread(thread_oop(), listener_thread);
470 java_lang_Thread::set_daemon(thread_oop());
472 listener_thread->set_threadObj(thread_oop());
473 Threads::add(listener_thread);
474 Thread::start(listener_thread);
475 }
476 }
478 // Performs clean-up tasks on platforms where we can detect that the last
479 // client has detached
480 void AttachListener::detachall() {
481 // call the platform dependent clean-up
482 pd_detachall();
483 }