aoqi@0: /* aoqi@0: * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_SERVICES_ATTACHLISTENER_HPP aoqi@0: #define SHARE_VM_SERVICES_ATTACHLISTENER_HPP aoqi@0: aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "utilities/debug.hpp" aoqi@0: #include "utilities/ostream.hpp" aoqi@0: #include "utilities/macros.hpp" aoqi@0: aoqi@0: // The AttachListener thread services a queue of operations that are enqueued aoqi@0: // by client tools. Each operation is identified by a name and has up to 3 aoqi@0: // arguments. The operation name is mapped to a function which performs the aoqi@0: // operation. The function is called with an outputStream which is can use to aoqi@0: // write any result data (for examples the properties command serializes aoqi@0: // properties names and values to the output stream). When the function aoqi@0: // complets the result value and any result data is returned to the client aoqi@0: // tool. aoqi@0: aoqi@0: class AttachOperation; aoqi@0: aoqi@0: typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out); aoqi@0: aoqi@0: struct AttachOperationFunctionInfo { aoqi@0: const char* name; aoqi@0: AttachOperationFunction func; aoqi@0: }; aoqi@0: aoqi@0: class AttachListener: AllStatic { aoqi@0: public: aoqi@0: static void vm_start() NOT_SERVICES_RETURN; aoqi@0: static void init() NOT_SERVICES_RETURN; aoqi@0: static void abort() NOT_SERVICES_RETURN; aoqi@0: aoqi@0: // invoke to perform clean-up tasks when all clients detach aoqi@0: static void detachall() NOT_SERVICES_RETURN; aoqi@0: aoqi@0: // indicates if the Attach Listener needs to be created at startup aoqi@0: static bool init_at_startup() NOT_SERVICES_RETURN_(false); aoqi@0: aoqi@0: // indicates if we have a trigger to start the Attach Listener aoqi@0: static bool is_init_trigger() NOT_SERVICES_RETURN_(false); aoqi@0: aoqi@0: #if !INCLUDE_SERVICES aoqi@0: static bool is_attach_supported() { return false; } aoqi@0: #else aoqi@0: private: aoqi@0: static volatile bool _initialized; aoqi@0: aoqi@0: public: aoqi@0: static bool is_initialized() { return _initialized; } aoqi@0: static void set_initialized() { _initialized = true; } aoqi@0: aoqi@0: // indicates if this VM supports attach-on-demand aoqi@0: static bool is_attach_supported() { return !DisableAttachMechanism; } aoqi@0: aoqi@0: // platform specific initialization aoqi@0: static int pd_init(); aoqi@0: aoqi@0: // platform specific operation aoqi@0: static AttachOperationFunctionInfo* pd_find_operation(const char* name); aoqi@0: aoqi@0: // platform specific flag change aoqi@0: static jint pd_set_flag(AttachOperation* op, outputStream* out); aoqi@0: aoqi@0: // platform specific detachall aoqi@0: static void pd_detachall(); aoqi@0: aoqi@0: // platform specific data dump aoqi@0: static void pd_data_dump(); aoqi@0: aoqi@0: // dequeue the next operation aoqi@0: static AttachOperation* dequeue(); aoqi@0: #endif // !INCLUDE_SERVICES aoqi@0: }; aoqi@0: aoqi@0: #if INCLUDE_SERVICES aoqi@0: class AttachOperation: public CHeapObj { aoqi@0: public: aoqi@0: enum { aoqi@0: name_length_max = 16, // maximum length of name aoqi@0: arg_length_max = 1024, // maximum length of argument aoqi@0: arg_count_max = 3 // maximum number of arguments aoqi@0: }; aoqi@0: aoqi@0: // name of special operation that can be enqueued when all aoqi@0: // clients detach aoqi@0: static char* detachall_operation_name() { return (char*)"detachall"; } aoqi@0: aoqi@0: private: aoqi@0: char _name[name_length_max+1]; aoqi@0: char _arg[arg_count_max][arg_length_max+1]; aoqi@0: aoqi@0: public: aoqi@0: const char* name() const { return _name; } aoqi@0: aoqi@0: // set the operation name aoqi@0: void set_name(char* name) { aoqi@0: assert(strlen(name) <= name_length_max, "exceeds maximum name length"); aoqi@0: strcpy(_name, name); aoqi@0: } aoqi@0: aoqi@0: // get an argument value aoqi@0: const char* arg(int i) const { aoqi@0: assert(i>=0 && i=0 && i