Mercurial > hg > truffle
annotate src/share/vm/services/attachListener.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
2 * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_attachListener.cpp.incl" | |
27 | |
28 volatile bool AttachListener::_initialized; | |
29 | |
30 // Implementation of "properties" command. | |
31 // | |
32 // Invokes sun.misc.VMSupport.serializePropertiesToByteArray to serialize | |
33 // the system properties into a byte array. | |
34 | |
35 static klassOop load_and_initialize_klass(symbolHandle sh, TRAPS) { | |
36 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL); | |
37 instanceKlassHandle ik (THREAD, k); | |
38 if (ik->should_be_initialized()) { | |
39 ik->initialize(CHECK_NULL); | |
40 } | |
41 return ik(); | |
42 } | |
43 | |
44 static jint get_properties(AttachOperation* op, outputStream* out, symbolHandle serializePropertiesMethod) { | |
45 Thread* THREAD = Thread::current(); | |
46 HandleMark hm; | |
47 | |
48 // load sun.misc.VMSupport | |
49 symbolHandle klass = vmSymbolHandles::sun_misc_VMSupport(); | |
50 klassOop k = load_and_initialize_klass(klass, THREAD); | |
51 if (HAS_PENDING_EXCEPTION) { | |
52 java_lang_Throwable::print(PENDING_EXCEPTION, out); | |
53 CLEAR_PENDING_EXCEPTION; | |
54 return JNI_ERR; | |
55 } | |
56 instanceKlassHandle ik(THREAD, k); | |
57 | |
58 // invoke the serializePropertiesToByteArray method | |
59 JavaValue result(T_OBJECT); | |
60 JavaCallArguments args; | |
61 | |
62 | |
63 symbolHandle signature = vmSymbolHandles::serializePropertiesToByteArray_signature(); | |
64 JavaCalls::call_static(&result, | |
65 ik, | |
66 serializePropertiesMethod, | |
67 signature, | |
68 &args, | |
69 THREAD); | |
70 if (HAS_PENDING_EXCEPTION) { | |
71 java_lang_Throwable::print(PENDING_EXCEPTION, out); | |
72 CLEAR_PENDING_EXCEPTION; | |
73 return JNI_ERR; | |
74 } | |
75 | |
76 // The result should be a [B | |
77 oop res = (oop)result.get_jobject(); | |
78 assert(res->is_typeArray(), "just checking"); | |
79 assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking"); | |
80 | |
81 // copy the bytes to the output stream | |
82 typeArrayOop ba = typeArrayOop(res); | |
83 jbyte* addr = typeArrayOop(res)->byte_at_addr(0); | |
84 out->print_raw((const char*)addr, ba->length()); | |
85 | |
86 return JNI_OK; | |
87 } | |
88 | |
89 // Implementation of "properties" command. | |
90 static jint get_system_properties(AttachOperation* op, outputStream* out) { | |
91 return get_properties(op, out, vmSymbolHandles::serializePropertiesToByteArray_name()); | |
92 } | |
93 | |
94 // Implementation of "agent_properties" command. | |
95 static jint get_agent_properties(AttachOperation* op, outputStream* out) { | |
96 return get_properties(op, out, vmSymbolHandles::serializeAgentPropertiesToByteArray_name()); | |
97 } | |
98 | |
99 // Implementation of "datadump" command. | |
100 // | |
101 // Raises a SIGBREAK signal so that VM dump threads, does deadlock detection, | |
102 // etc. In theory this command should only post a DataDumpRequest to any | |
103 // JVMTI environment that has enabled this event. However it's useful to | |
104 // trigger the SIGBREAK handler. | |
105 | |
106 static jint data_dump(AttachOperation* op, outputStream* out) { | |
107 if (!ReduceSignalUsage) { | |
108 AttachListener::pd_data_dump(); | |
109 } else { | |
110 if (JvmtiExport::should_post_data_dump()) { | |
111 JvmtiExport::post_data_dump(); | |
112 } | |
113 } | |
114 return JNI_OK; | |
115 } | |
116 | |
117 // Implementation of "threaddump" command - essentially a remote ctrl-break | |
118 // | |
119 static jint thread_dump(AttachOperation* op, outputStream* out) { | |
120 bool print_concurrent_locks = false; | |
121 if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) { | |
122 print_concurrent_locks = true; | |
123 } | |
124 | |
125 // thread stacks | |
126 VM_PrintThreads op1(out, print_concurrent_locks); | |
127 VMThread::execute(&op1); | |
128 | |
129 // JNI global handles | |
130 VM_PrintJNI op2(out); | |
131 VMThread::execute(&op2); | |
132 | |
133 // Deadlock detection | |
134 VM_FindDeadlocks op3(out); | |
135 VMThread::execute(&op3); | |
136 | |
137 return JNI_OK; | |
138 } | |
139 | |
140 #ifndef SERVICES_KERNEL // Heap dumping not supported | |
141 // Implementation of "dumpheap" command. | |
142 // | |
143 // Input arguments :- | |
144 // arg0: Name of the dump file | |
145 // arg1: "-live" or "-all" | |
146 jint dump_heap(AttachOperation* op, outputStream* out) { | |
147 const char* path = op->arg(0); | |
148 if (path == NULL || path[0] == '\0') { | |
149 out->print_cr("No dump file specified"); | |
150 } else { | |
151 bool live_objects_only = true; // default is true to retain the behavior before this change is made | |
152 const char* arg1 = op->arg(1); | |
153 if (arg1 != NULL && (strlen(arg1) > 0)) { | |
154 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) { | |
155 out->print_cr("Invalid argument to dumpheap operation: %s", arg1); | |
156 return JNI_ERR; | |
157 } | |
158 live_objects_only = strcmp(arg1, "-live") == 0; | |
159 } | |
160 | |
161 // Request a full GC before heap dump if live_objects_only = true | |
162 // This helps reduces the amount of unreachable objects in the dump | |
163 // and makes it easier to browse. | |
164 HeapDumper dumper(live_objects_only /* request GC */); | |
165 int res = dumper.dump(op->arg(0)); | |
166 if (res == 0) { | |
167 out->print_cr("Heap dump file created"); | |
168 } else { | |
169 // heap dump failed | |
170 ResourceMark rm; | |
171 char* error = dumper.error_as_C_string(); | |
172 if (error == NULL) { | |
173 out->print_cr("Dump failed - reason unknown"); | |
174 } else { | |
175 out->print_cr("%s", error); | |
176 } | |
177 } | |
178 } | |
179 return JNI_OK; | |
180 } | |
181 #endif // SERVICES_KERNEL | |
182 | |
183 // Implementation of "inspectheap" command | |
184 // | |
185 // Input arguments :- | |
186 // arg0: "-live" or "-all" | |
187 static jint heap_inspection(AttachOperation* op, outputStream* out) { | |
188 bool live_objects_only = true; // default is true to retain the behavior before this change is made | |
189 const char* arg0 = op->arg(0); | |
190 if (arg0 != NULL && (strlen(arg0) > 0)) { | |
191 if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) { | |
192 out->print_cr("Invalid argument to inspectheap operation: %s", arg0); | |
193 return JNI_ERR; | |
194 } | |
195 live_objects_only = strcmp(arg0, "-live") == 0; | |
196 } | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
0
diff
changeset
|
197 VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */); |
0 | 198 VMThread::execute(&heapop); |
199 return JNI_OK; | |
200 } | |
201 | |
202 // set a boolean global flag using value from AttachOperation | |
203 static jint set_bool_flag(const char* name, AttachOperation* op, outputStream* out) { | |
204 bool value = true; | |
205 const char* arg1; | |
206 if ((arg1 = op->arg(1)) != NULL) { | |
207 int tmp; | |
208 int n = sscanf(arg1, "%d", &tmp); | |
209 if (n != 1) { | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
210 out->print_cr("flag value must be a boolean (1 or 0)"); |
0 | 211 return JNI_ERR; |
212 } | |
213 value = (tmp != 0); | |
214 } | |
215 bool res = CommandLineFlags::boolAtPut((char*)name, &value, ATTACH_ON_DEMAND); | |
216 if (! res) { | |
217 out->print_cr("setting flag %s failed", name); | |
218 } | |
219 return res? JNI_OK : JNI_ERR; | |
220 } | |
221 | |
222 // set a intx global flag using value from AttachOperation | |
223 static jint set_intx_flag(const char* name, AttachOperation* op, outputStream* out) { | |
224 intx value; | |
225 const char* arg1; | |
226 if ((arg1 = op->arg(1)) != NULL) { | |
227 int n = sscanf(arg1, INTX_FORMAT, &value); | |
228 if (n != 1) { | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
229 out->print_cr("flag value must be an integer"); |
0 | 230 return JNI_ERR; |
231 } | |
232 } | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
233 bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND); |
0 | 234 if (! res) { |
235 out->print_cr("setting flag %s failed", name); | |
236 } | |
237 | |
238 return res? JNI_OK : JNI_ERR; | |
239 } | |
240 | |
241 // set a uintx global flag using value from AttachOperation | |
242 static jint set_uintx_flag(const char* name, AttachOperation* op, outputStream* out) { | |
243 uintx value; | |
244 const char* arg1; | |
245 if ((arg1 = op->arg(1)) != NULL) { | |
246 int n = sscanf(arg1, UINTX_FORMAT, &value); | |
247 if (n != 1) { | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
248 out->print_cr("flag value must be an unsigned integer"); |
0 | 249 return JNI_ERR; |
250 } | |
251 } | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
252 bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND); |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
253 if (! res) { |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
254 out->print_cr("setting flag %s failed", name); |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
255 } |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
256 |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
257 return res? JNI_OK : JNI_ERR; |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
258 } |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
259 |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
260 // set a uint64_t global flag using value from AttachOperation |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
261 static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStream* out) { |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
262 uint64_t value; |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
263 const char* arg1; |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
264 if ((arg1 = op->arg(1)) != NULL) { |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
265 int n = sscanf(arg1, UINT64_FORMAT, &value); |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
266 if (n != 1) { |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
267 out->print_cr("flag value must be an unsigned 64-bit integer"); |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
268 return JNI_ERR; |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
269 } |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
270 } |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
271 bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND); |
0 | 272 if (! res) { |
273 out->print_cr("setting flag %s failed", name); | |
274 } | |
275 | |
276 return res? JNI_OK : JNI_ERR; | |
277 } | |
278 | |
279 // set a string global flag using value from AttachOperation | |
280 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) { | |
281 const char* value; | |
282 if ((value = op->arg(1)) == NULL) { | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
283 out->print_cr("flag value must be a string"); |
0 | 284 return JNI_ERR; |
285 } | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
286 bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND); |
0 | 287 if (res) { |
288 FREE_C_HEAP_ARRAY(char, value); | |
289 } else { | |
290 out->print_cr("setting flag %s failed", name); | |
291 } | |
292 | |
293 return res? JNI_OK : JNI_ERR; | |
294 } | |
295 | |
296 // Implementation of "setflag" command | |
297 static jint set_flag(AttachOperation* op, outputStream* out) { | |
298 | |
299 const char* name = NULL; | |
300 if ((name = op->arg(0)) == NULL) { | |
301 out->print_cr("flag name is missing"); | |
302 return JNI_ERR; | |
303 } | |
304 | |
305 Flag* f = Flag::find_flag((char*)name, strlen(name)); | |
306 if (f && f->is_external() && f->is_writeable()) { | |
307 if (f->is_bool()) { | |
308 return set_bool_flag(name, op, out); | |
309 } else if (f->is_intx()) { | |
310 return set_intx_flag(name, op, out); | |
311 } else if (f->is_uintx()) { | |
312 return set_uintx_flag(name, op, out); | |
1067
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
313 } else if (f->is_uint64_t()) { |
ba7ea42fc66e
6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents:
615
diff
changeset
|
314 return set_uint64_t_flag(name, op, out); |
0 | 315 } else if (f->is_ccstr()) { |
316 return set_ccstr_flag(name, op, out); | |
317 } else { | |
318 ShouldNotReachHere(); | |
319 return JNI_ERR; | |
320 } | |
321 } else { | |
322 return AttachListener::pd_set_flag(op, out); | |
323 } | |
324 } | |
325 | |
326 // Implementation of "printflag" command | |
327 static jint print_flag(AttachOperation* op, outputStream* out) { | |
328 const char* name = NULL; | |
329 if ((name = op->arg(0)) == NULL) { | |
330 out->print_cr("flag name is missing"); | |
331 return JNI_ERR; | |
332 } | |
333 Flag* f = Flag::find_flag((char*)name, strlen(name)); | |
334 if (f) { | |
335 f->print_as_flag(out); | |
336 out->print_cr(""); | |
337 } else { | |
338 out->print_cr("no such flag '%s'", name); | |
339 } | |
340 return JNI_OK; | |
341 } | |
342 | |
343 // Table to map operation names to functions. | |
344 | |
345 // names must be of length <= AttachOperation::name_length_max | |
346 static AttachOperationFunctionInfo funcs[] = { | |
347 { "agentProperties", get_agent_properties }, | |
348 { "datadump", data_dump }, | |
349 #ifndef SERVICES_KERNEL | |
350 { "dumpheap", dump_heap }, | |
351 #endif // SERVICES_KERNEL | |
352 { "load", JvmtiExport::load_agent_library }, | |
353 { "properties", get_system_properties }, | |
354 { "threaddump", thread_dump }, | |
355 { "inspectheap", heap_inspection }, | |
356 { "setflag", set_flag }, | |
357 { "printflag", print_flag }, | |
358 { NULL, NULL } | |
359 }; | |
360 | |
361 | |
362 | |
363 // The Attach Listener threads services a queue. It dequeues an operation | |
364 // from the queue, examines the operation name (command), and dispatches | |
365 // to the corresponding function to perform the operation. | |
366 | |
367 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) { | |
368 os::set_priority(thread, NearMaxPriority); | |
369 | |
370 if (AttachListener::pd_init() != 0) { | |
371 return; | |
372 } | |
373 AttachListener::set_initialized(); | |
374 | |
375 for (;;) { | |
376 AttachOperation* op = AttachListener::dequeue(); | |
377 if (op == NULL) { | |
378 return; // dequeue failed or shutdown | |
379 } | |
380 | |
381 ResourceMark rm; | |
382 bufferedStream st; | |
383 jint res = JNI_OK; | |
384 | |
385 // handle special detachall operation | |
386 if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) { | |
387 AttachListener::detachall(); | |
388 } else { | |
389 // find the function to dispatch too | |
390 AttachOperationFunctionInfo* info = NULL; | |
391 for (int i=0; funcs[i].name != NULL; i++) { | |
392 const char* name = funcs[i].name; | |
393 assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max"); | |
394 if (strcmp(op->name(), name) == 0) { | |
395 info = &(funcs[i]); | |
396 break; | |
397 } | |
398 } | |
399 | |
400 // check for platform dependent attach operation | |
401 if (info == NULL) { | |
402 info = AttachListener::pd_find_operation(op->name()); | |
403 } | |
404 | |
405 if (info != NULL) { | |
406 // dispatch to the function that implements this operation | |
407 res = (info->func)(op, &st); | |
408 } else { | |
409 st.print("Operation %s not recognized!", op->name()); | |
410 res = JNI_ERR; | |
411 } | |
412 } | |
413 | |
414 // operation complete - send result and output to client | |
415 op->complete(res, &st); | |
416 } | |
417 } | |
418 | |
419 // Starts the Attach Listener thread | |
420 void AttachListener::init() { | |
421 EXCEPTION_MARK; | |
422 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK); | |
423 instanceKlassHandle klass (THREAD, k); | |
424 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); | |
425 | |
426 const char thread_name[] = "Attach Listener"; | |
427 Handle string = java_lang_String::create_from_str(thread_name, CHECK); | |
428 | |
429 // Initialize thread_oop to put it into the system threadGroup | |
430 Handle thread_group (THREAD, Universe::system_thread_group()); | |
431 JavaValue result(T_VOID); | |
432 JavaCalls::call_special(&result, thread_oop, | |
433 klass, | |
434 vmSymbolHandles::object_initializer_name(), | |
435 vmSymbolHandles::threadgroup_string_void_signature(), | |
436 thread_group, | |
437 string, | |
438 CHECK); | |
439 | |
1142 | 440 KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); |
0 | 441 JavaCalls::call_special(&result, |
442 thread_group, | |
443 group, | |
444 vmSymbolHandles::add_method_name(), | |
445 vmSymbolHandles::thread_void_signature(), | |
446 thread_oop, // ARG 1 | |
447 CHECK); | |
448 | |
449 { MutexLocker mu(Threads_lock); | |
450 JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry); | |
451 | |
452 // Check that thread and osthread were created | |
453 if (listener_thread == NULL || listener_thread->osthread() == NULL) { | |
454 vm_exit_during_initialization("java.lang.OutOfMemoryError", | |
455 "unable to create new native thread"); | |
456 } | |
457 | |
458 java_lang_Thread::set_thread(thread_oop(), listener_thread); | |
459 java_lang_Thread::set_daemon(thread_oop()); | |
460 | |
461 listener_thread->set_threadObj(thread_oop()); | |
462 Threads::add(listener_thread); | |
463 Thread::start(listener_thread); | |
464 } | |
465 } | |
466 | |
467 // Performs clean-up tasks on platforms where we can detect that the last | |
468 // client has detached | |
469 void AttachListener::detachall() { | |
470 // call the platform dependent clean-up | |
471 pd_detachall(); | |
472 } |