Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
4e06de41
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
4e06de41
编写于
12月 14, 2011
作者:
F
fparain
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7104647: Adding a diagnostic command framework
Reviewed-by: phh, dcubed
上级
8bb317a2
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
1412 addition
and
2 deletion
+1412
-2
src/share/vm/services/attachListener.cpp
src/share/vm/services/attachListener.cpp
+20
-0
src/share/vm/services/diagnosticArgument.cpp
src/share/vm/services/diagnosticArgument.cpp
+112
-0
src/share/vm/services/diagnosticArgument.hpp
src/share/vm/services/diagnosticArgument.hpp
+102
-0
src/share/vm/services/diagnosticCommand.cpp
src/share/vm/services/diagnosticCommand.cpp
+131
-0
src/share/vm/services/diagnosticCommand.hpp
src/share/vm/services/diagnosticCommand.hpp
+76
-0
src/share/vm/services/diagnosticFramework.cpp
src/share/vm/services/diagnosticFramework.cpp
+450
-0
src/share/vm/services/diagnosticFramework.hpp
src/share/vm/services/diagnosticFramework.hpp
+362
-0
src/share/vm/services/jmm.h
src/share/vm/services/jmm.h
+32
-1
src/share/vm/services/management.cpp
src/share/vm/services/management.cpp
+127
-1
未找到文件。
src/share/vm/services/attachListener.cpp
浏览文件 @
4e06de41
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
#include "runtime/javaCalls.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
#include "runtime/os.hpp"
#include "services/attachListener.hpp"
#include "services/attachListener.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/heapDumper.hpp"
#include "services/heapDumper.hpp"
volatile
bool
AttachListener
::
_initialized
;
volatile
bool
AttachListener
::
_initialized
;
...
@@ -148,6 +149,24 @@ static jint thread_dump(AttachOperation* op, outputStream* out) {
...
@@ -148,6 +149,24 @@ static jint thread_dump(AttachOperation* op, outputStream* out) {
return
JNI_OK
;
return
JNI_OK
;
}
}
// A jcmd attach operation request was received, which will now
// dispatch to the diagnostic commands used for serviceability functions.
static
jint
jcmd
(
AttachOperation
*
op
,
outputStream
*
out
)
{
Thread
*
THREAD
=
Thread
::
current
();
// All the supplied jcmd arguments are stored as a single
// string (op->arg(0)). This is parsed by the Dcmd framework.
DCmd
::
parse_and_execute
(
out
,
op
->
arg
(
0
),
' '
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
java_lang_Throwable
::
print
(
PENDING_EXCEPTION
,
out
);
CLEAR_PENDING_EXCEPTION
;
// The exception has been printed on the output stream
// If the JVM returns JNI_ERR, the attachAPI throws a generic I/O
// exception and the content of the output stream is not processed.
// By returning JNI_OK, the exception will be displayed on the client side
}
return
JNI_OK
;
}
#ifndef SERVICES_KERNEL // Heap dumping not supported
#ifndef SERVICES_KERNEL // Heap dumping not supported
// Implementation of "dumpheap" command.
// Implementation of "dumpheap" command.
//
//
...
@@ -366,6 +385,7 @@ static AttachOperationFunctionInfo funcs[] = {
...
@@ -366,6 +385,7 @@ static AttachOperationFunctionInfo funcs[] = {
{
"inspectheap"
,
heap_inspection
},
{
"inspectheap"
,
heap_inspection
},
{
"setflag"
,
set_flag
},
{
"setflag"
,
set_flag
},
{
"printflag"
,
print_flag
},
{
"printflag"
,
print_flag
},
{
"jcmd"
,
jcmd
},
{
NULL
,
NULL
}
{
NULL
,
NULL
}
};
};
...
...
src/share/vm/services/diagnosticArgument.cpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/thread.hpp"
#include "services/diagnosticArgument.hpp"
void
GenDCmdArgument
::
read_value
(
const
char
*
str
,
size_t
len
,
TRAPS
)
{
if
(
is_set
())
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Duplicates in diagnostic command arguments"
);
}
parse_value
(
str
,
len
,
CHECK
);
set_is_set
(
true
);
}
template
<
>
void
DCmdArgument
<
jlong
>::
parse_value
(
const
char
*
str
,
size_t
len
,
TRAPS
)
{
if
(
sscanf
(
str
,
INT64_FORMAT
,
&
_value
)
!=
1
)
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Integer parsing error in diagnostic command arguments"
);
}
}
template
<
>
void
DCmdArgument
<
jlong
>::
init_value
(
TRAPS
)
{
if
(
has_default
())
{
this
->
parse_value
(
_default_string
,
strlen
(
_default_string
),
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
fatal
(
"Default string must be parsable"
);
}
}
else
{
set_value
(
0
);
}
}
template
<
>
void
DCmdArgument
<
jlong
>::
destroy_value
()
{
}
template
<
>
void
DCmdArgument
<
bool
>::
parse_value
(
const
char
*
str
,
size_t
len
,
TRAPS
)
{
if
(
len
==
0
)
{
set_value
(
true
);
}
else
{
if
(
strcasecmp
(
str
,
"true"
)
==
0
)
{
set_value
(
true
);
}
else
if
(
strcasecmp
(
str
,
"false"
)
==
0
)
{
set_value
(
false
);
}
else
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Boolean parsing error in diagnostic command arguments"
);
}
}
}
template
<
>
void
DCmdArgument
<
bool
>::
init_value
(
TRAPS
)
{
if
(
has_default
())
{
this
->
parse_value
(
_default_string
,
strlen
(
_default_string
),
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
fatal
(
"Default string must be parsable"
);
}
}
else
{
set_value
(
false
);
}
}
template
<
>
void
DCmdArgument
<
bool
>::
destroy_value
()
{
}
template
<
>
void
DCmdArgument
<
char
*>::
parse_value
(
const
char
*
str
,
size_t
len
,
TRAPS
)
{
_value
=
NEW_C_HEAP_ARRAY
(
char
,
len
+
1
);
strncpy
(
_value
,
str
,
len
);
_value
[
len
]
=
0
;
}
template
<
>
void
DCmdArgument
<
char
*>::
init_value
(
TRAPS
)
{
if
(
has_default
())
{
this
->
parse_value
(
_default_string
,
strlen
(
_default_string
),
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
fatal
(
"Default string must be parsable"
);
}
}
else
{
set_value
(
NULL
);
}
}
template
<
>
void
DCmdArgument
<
char
*>::
destroy_value
()
{
if
(
_value
!=
NULL
)
{
FREE_C_HEAP_ARRAY
(
char
,
_value
);
set_value
(
NULL
);
}
}
src/share/vm/services/diagnosticArgument.hpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP
#define SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "utilities/exceptions.hpp"
class
GenDCmdArgument
:
public
ResourceObj
{
protected:
GenDCmdArgument
*
_next
;
const
char
*
_name
;
const
char
*
_description
;
const
char
*
_type
;
const
char
*
_default_string
;
bool
_is_set
;
bool
_is_mandatory
;
GenDCmdArgument
(
const
char
*
name
,
const
char
*
description
,
const
char
*
type
,
const
char
*
default_string
,
bool
mandatory
)
{
_name
=
name
;
_description
=
description
;
_type
=
type
;
_default_string
=
default_string
;
_is_mandatory
=
mandatory
;
_is_set
=
false
;
};
public:
const
char
*
name
()
{
return
_name
;
}
const
char
*
description
()
{
return
_description
;
}
const
char
*
type
()
{
return
_type
;
}
const
char
*
default_string
()
{
return
_default_string
;
}
bool
is_set
()
{
return
_is_set
;
}
void
set_is_set
(
bool
b
)
{
_is_set
=
b
;
}
bool
is_mandatory
()
{
return
_is_mandatory
;
}
bool
has_value
()
{
return
_is_set
||
_default_string
!=
NULL
;
}
bool
has_default
()
{
return
_default_string
!=
NULL
;
}
void
read_value
(
const
char
*
str
,
size_t
len
,
TRAPS
);
virtual
void
parse_value
(
const
char
*
str
,
size_t
len
,
TRAPS
)
=
0
;
virtual
void
init_value
(
TRAPS
)
=
0
;
virtual
void
reset
(
TRAPS
)
=
0
;
virtual
void
cleanup
()
=
0
;
void
set_next
(
GenDCmdArgument
*
arg
)
{
_next
=
arg
;
}
GenDCmdArgument
*
next
()
{
return
_next
;
}
};
template
<
class
ArgType
>
class
DCmdArgument
:
public
GenDCmdArgument
{
private:
ArgType
_value
;
public:
DCmdArgument
(
const
char
*
name
,
const
char
*
description
,
const
char
*
type
,
bool
mandatory
)
:
GenDCmdArgument
(
name
,
description
,
type
,
NULL
,
mandatory
)
{
}
DCmdArgument
(
const
char
*
name
,
const
char
*
description
,
const
char
*
type
,
bool
mandatory
,
const
char
*
defaultvalue
)
:
GenDCmdArgument
(
name
,
description
,
type
,
defaultvalue
,
mandatory
)
{
}
~
DCmdArgument
()
{
destroy_value
();
}
ArgType
value
()
{
return
_value
;}
void
set_value
(
ArgType
v
)
{
_value
=
v
;
}
void
reset
(
TRAPS
)
{
destroy_value
();
init_value
(
CHECK
);
_is_set
=
false
;
}
void
cleanup
()
{
destroy_value
();
}
void
parse_value
(
const
char
*
str
,
size_t
len
,
TRAPS
);
void
init_value
(
TRAPS
);
void
destroy_value
();
};
#endif
/* SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP */
src/share/vm/services/diagnosticCommand.cpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/diagnosticFramework.hpp"
HelpDCmd
::
HelpDCmd
(
outputStream
*
output
,
bool
heap
)
:
DCmd
(
output
,
heap
),
_all
(
"-all"
,
"Show help for all commands"
,
"BOOLEAN"
,
false
,
"false"
),
_cmd
(
"command name"
,
"The name of the command for which we want help"
,
"STRING"
,
false
)
{
_dcmdparser
.
add_dcmd_option
(
&
_all
);
_dcmdparser
.
add_dcmd_argument
(
&
_cmd
);
};
void
HelpDCmd
::
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
)
{
_dcmdparser
.
parse
(
line
,
delim
,
CHECK
);
}
void
HelpDCmd
::
print_help
(
outputStream
*
out
)
{
_dcmdparser
.
print_help
(
out
,
name
());
}
void
HelpDCmd
::
execute
(
TRAPS
)
{
if
(
_all
.
value
())
{
GrowableArray
<
const
char
*>*
cmd_list
=
DCmdFactory
::
DCmd_list
();
for
(
int
i
=
0
;
i
<
cmd_list
->
length
();
i
++
)
{
DCmdFactory
*
factory
=
DCmdFactory
::
factory
(
cmd_list
->
at
(
i
),
strlen
(
cmd_list
->
at
(
i
)));
if
(
!
factory
->
is_hidden
())
{
output
()
->
print_cr
(
"%s%s"
,
factory
->
name
(),
factory
->
is_enabled
()
?
""
:
" [disabled]"
);
output
()
->
print_cr
(
"
\t
%s"
,
factory
->
description
());
output
()
->
cr
();
}
factory
=
factory
->
next
();
}
}
else
if
(
_cmd
.
has_value
())
{
DCmd
*
cmd
=
NULL
;
DCmdFactory
*
factory
=
DCmdFactory
::
factory
(
_cmd
.
value
(),
strlen
(
_cmd
.
value
()));
if
(
factory
!=
NULL
)
{
output
()
->
print_cr
(
"%s%s"
,
factory
->
name
(),
factory
->
is_enabled
()
?
""
:
" [disabled]"
);
output
()
->
print_cr
(
factory
->
description
());
output
()
->
print_cr
(
"
\n
Impact: %s"
,
factory
->
impact
());
cmd
=
factory
->
create_resource_instance
(
output
());
if
(
cmd
!=
NULL
)
{
DCmdMark
mark
(
cmd
);
cmd
->
print_help
(
output
());
}
}
else
{
output
()
->
print_cr
(
"Help unavailable : '%s' : No such command"
,
_cmd
.
value
());
}
}
else
{
output
()
->
print_cr
(
"The following commands are available:"
);
GrowableArray
<
const
char
*>*
cmd_list
=
DCmdFactory
::
DCmd_list
();
for
(
int
i
=
0
;
i
<
cmd_list
->
length
();
i
++
)
{
DCmdFactory
*
factory
=
DCmdFactory
::
factory
(
cmd_list
->
at
(
i
),
strlen
(
cmd_list
->
at
(
i
)));
if
(
!
factory
->
is_hidden
())
{
output
()
->
print_cr
(
"%s%s"
,
factory
->
name
(),
factory
->
is_enabled
()
?
""
:
" [disabled]"
);
}
factory
=
factory
->
_next
;
}
output
()
->
print_cr
(
"
\n
For more information about a specific command use 'help <command>'."
);
}
}
void
HelpDCmd
::
reset
(
TRAPS
)
{
_dcmdparser
.
reset
(
CHECK
);
}
void
HelpDCmd
::
cleanup
()
{
_dcmdparser
.
cleanup
();
}
int
HelpDCmd
::
num_arguments
()
{
ResourceMark
rm
;
HelpDCmd
*
dcmd
=
new
HelpDCmd
(
NULL
,
false
);
if
(
dcmd
!=
NULL
)
{
DCmdMark
mark
(
dcmd
);
return
dcmd
->
_dcmdparser
.
num_arguments
();
}
else
{
return
0
;
}
}
GrowableArray
<
const
char
*>*
HelpDCmd
::
argument_name_array
()
{
return
_dcmdparser
.
argument_name_array
();
}
GrowableArray
<
DCmdArgumentInfo
*>*
HelpDCmd
::
argument_info_array
()
{
return
_dcmdparser
.
argument_info_array
();
}
void
VersionDCmd
::
execute
(
TRAPS
)
{
output
()
->
print_cr
(
"%s version %s"
,
Abstract_VM_Version
::
vm_name
(),
Abstract_VM_Version
::
vm_release
());
JDK_Version
jdk_version
=
JDK_Version
::
current
();
if
(
jdk_version
.
update_version
()
>
0
)
{
output
()
->
print_cr
(
"JDK %d.%d_%02d"
,
jdk_version
.
major_version
(),
jdk_version
.
minor_version
(),
jdk_version
.
update_version
());
}
else
{
output
()
->
print_cr
(
"JDK %d.%d"
,
jdk_version
.
major_version
(),
jdk_version
.
minor_version
());
}
}
src/share/vm/services/diagnosticCommand.hpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
#define SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
#include "runtime/arguments.hpp"
#include "classfile/vmSymbols.hpp"
#include "utilities/ostream.hpp"
#include "runtime/vm_version.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/os.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/diagnosticFramework.hpp"
class
HelpDCmd
:
public
DCmd
{
protected:
DCmdParser
_dcmdparser
;
DCmdArgument
<
bool
>
_all
;
DCmdArgument
<
char
*>
_cmd
;
public:
HelpDCmd
(
outputStream
*
output
,
bool
heap
);
static
const
char
*
name
()
{
return
"help"
;
}
static
const
char
*
description
()
{
return
"For more information about a specific command use 'help <command>'. "
"With no argument this will show a list of available commands. "
"'help all' will show help for all commands."
;
}
static
const
char
*
impact
()
{
return
"Low: "
;
}
static
int
num_arguments
();
virtual
void
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
);
virtual
void
execute
(
TRAPS
);
virtual
void
reset
(
TRAPS
);
virtual
void
cleanup
();
virtual
void
print_help
(
outputStream
*
out
);
virtual
GrowableArray
<
const
char
*>*
argument_name_array
();
virtual
GrowableArray
<
DCmdArgumentInfo
*>*
argument_info_array
();
};
class
VersionDCmd
:
public
DCmd
{
public:
VersionDCmd
(
outputStream
*
output
,
bool
heap
)
:
DCmd
(
output
,
heap
)
{
}
static
const
char
*
name
()
{
return
"VM.version"
;
}
static
const
char
*
description
()
{
return
"Print JVM version information."
;
}
static
const
char
*
impact
()
{
return
"Low: "
;
}
static
int
num_arguments
()
{
return
0
;
}
virtual
void
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
)
{
}
virtual
void
execute
(
TRAPS
);
virtual
void
print_help
(
outputStream
*
out
)
{
}
};
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
src/share/vm/services/diagnosticFramework.cpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/oopFactory.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticFramework.hpp"
#include "services/management.hpp"
CmdLine
::
CmdLine
(
const
char
*
line
,
size_t
len
,
bool
no_command_name
)
{
assert
(
line
!=
NULL
,
"Command line string should not be NULL"
);
const
char
*
line_end
;
const
char
*
cmd_end
;
_cmd
=
line
;
line_end
=
&
line
[
len
];
// Skip whitespace in the beginning of the line.
while
(
_cmd
<
line_end
&&
isspace
((
int
)
_cmd
[
0
]))
{
_cmd
++
;
}
cmd_end
=
_cmd
;
if
(
no_command_name
)
{
_cmd
=
NULL
;
_cmd_len
=
0
;
}
else
{
// Look for end of the command name
while
(
cmd_end
<
line_end
&&
!
isspace
((
int
)
cmd_end
[
0
]))
{
cmd_end
++
;
}
_cmd_len
=
cmd_end
-
_cmd
;
}
_args
=
cmd_end
;
_args_len
=
line_end
-
_args
;
}
bool
DCmdArgIter
::
next
(
TRAPS
)
{
if
(
_len
==
0
)
return
false
;
// skipping spaces
while
(
_cursor
<
_len
-
1
&&
isspace
(
_buffer
[
_cursor
]))
{
_cursor
++
;
}
// handling end of command line
if
(
_cursor
>=
_len
-
1
)
{
_cursor
=
_len
-
1
;
_key_addr
=
&
_buffer
[
_len
-
1
];
_key_len
=
0
;
_value_addr
=
&
_buffer
[
_len
-
1
];
_value_len
=
0
;
return
false
;
}
// extracting first item, argument or option name
_key_addr
=
&
_buffer
[
_cursor
];
while
(
_cursor
<=
_len
-
1
&&
_buffer
[
_cursor
]
!=
'='
&&
_buffer
[
_cursor
]
!=
_delim
)
{
// argument can be surrounded by single or double quotes
if
(
_buffer
[
_cursor
]
==
'\"'
||
_buffer
[
_cursor
]
==
'\''
)
{
_key_addr
++
;
char
quote
=
_buffer
[
_cursor
];
while
(
_cursor
<
_len
-
1
)
{
_cursor
++
;
if
(
_buffer
[
_cursor
]
==
quote
&&
_buffer
[
_cursor
-
1
]
!=
'\\'
)
{
break
;
}
}
if
(
_buffer
[
_cursor
]
!=
quote
)
{
THROW_MSG_
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Format error in diagnostic command arguments"
,
false
);
}
break
;
}
_cursor
++
;
}
_key_len
=
&
_buffer
[
_cursor
]
-
_key_addr
;
// check if the argument has the <key>=<value> format
if
(
_cursor
<=
_len
-
1
&&
_buffer
[
_cursor
]
==
'='
)
{
_cursor
++
;
_value_addr
=
&
_buffer
[
_cursor
];
// extract the value
while
(
_cursor
<=
_len
-
1
&&
_buffer
[
_cursor
]
!=
_delim
)
{
// value can be surrounded by simple or double quotes
if
(
_buffer
[
_cursor
]
==
'\"'
||
_buffer
[
_cursor
]
==
'\''
)
{
_value_addr
++
;
char
quote
=
_buffer
[
_cursor
];
while
(
_cursor
<
_len
-
1
)
{
_cursor
++
;
if
(
_buffer
[
_cursor
]
==
quote
&&
_buffer
[
_cursor
-
1
]
!=
'\\'
)
{
break
;
}
}
if
(
_buffer
[
_cursor
]
!=
quote
)
{
THROW_MSG_
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Format error in diagnostic command arguments"
,
false
);
}
break
;
}
_cursor
++
;
}
_value_len
=
&
_buffer
[
_cursor
]
-
_value_addr
;
}
else
{
_value_addr
=
NULL
;
_value_len
=
0
;
}
return
_key_len
!=
0
;
}
bool
DCmdInfo
::
by_name
(
void
*
cmd_name
,
DCmdInfo
*
info
)
{
if
(
info
==
NULL
)
return
false
;
return
strcmp
((
const
char
*
)
cmd_name
,
info
->
name
())
==
0
;
}
void
DCmdParser
::
add_dcmd_option
(
GenDCmdArgument
*
arg
)
{
assert
(
arg
!=
NULL
,
"Sanity"
);
if
(
_options
==
NULL
)
{
_options
=
arg
;
}
else
{
GenDCmdArgument
*
o
=
_options
;
while
(
o
->
next
()
!=
NULL
)
{
o
=
o
->
next
();
}
o
->
set_next
(
arg
);
}
arg
->
set_next
(
NULL
);
Thread
*
THREAD
=
Thread
::
current
();
arg
->
init_value
(
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
fatal
(
"Initialization must be successful"
);
}
}
void
DCmdParser
::
add_dcmd_argument
(
GenDCmdArgument
*
arg
)
{
assert
(
arg
!=
NULL
,
"Sanity"
);
if
(
_arguments_list
==
NULL
)
{
_arguments_list
=
arg
;
}
else
{
GenDCmdArgument
*
a
=
_arguments_list
;
while
(
a
->
next
()
!=
NULL
)
{
a
=
a
->
next
();
}
a
->
set_next
(
arg
);
}
arg
->
set_next
(
NULL
);
Thread
*
THREAD
=
Thread
::
current
();
arg
->
init_value
(
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
fatal
(
"Initialization must be successful"
);
}
}
void
DCmdParser
::
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
)
{
GenDCmdArgument
*
next_argument
=
_arguments_list
;
DCmdArgIter
iter
(
line
->
args_addr
(),
line
->
args_len
(),
delim
);
bool
cont
=
iter
.
next
(
CHECK
);
while
(
cont
)
{
GenDCmdArgument
*
arg
=
lookup_dcmd_option
(
iter
.
key_addr
(),
iter
.
key_length
());
if
(
arg
!=
NULL
)
{
arg
->
read_value
(
iter
.
value_addr
(),
iter
.
value_length
(),
CHECK
);
}
else
{
if
(
next_argument
!=
NULL
)
{
arg
=
next_argument
;
arg
->
read_value
(
iter
.
key_addr
(),
iter
.
key_length
(),
CHECK
);
next_argument
=
next_argument
->
next
();
}
else
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Unknown argument in diagnostic command"
);
}
}
cont
=
iter
.
next
(
CHECK
);
}
check
(
CHECK
);
}
GenDCmdArgument
*
DCmdParser
::
lookup_dcmd_option
(
const
char
*
name
,
size_t
len
)
{
GenDCmdArgument
*
arg
=
_options
;
while
(
arg
!=
NULL
)
{
if
(
strlen
(
arg
->
name
())
==
len
&&
strncmp
(
name
,
arg
->
name
(),
len
)
==
0
)
{
return
arg
;
}
arg
=
arg
->
next
();
}
return
NULL
;
}
void
DCmdParser
::
check
(
TRAPS
)
{
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
if
(
arg
->
is_mandatory
()
&&
!
arg
->
has_value
())
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Missing argument for diagnostic command"
);
}
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
if
(
arg
->
is_mandatory
()
&&
!
arg
->
has_value
())
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Missing option for diagnostic command"
);
}
arg
=
arg
->
next
();
}
}
void
DCmdParser
::
print_help
(
outputStream
*
out
,
const
char
*
cmd_name
)
{
out
->
print
(
"
\n
Syntax : %s %s"
,
cmd_name
,
_options
==
NULL
?
""
:
"[options]"
);
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
if
(
arg
->
is_mandatory
())
{
out
->
print
(
" <%s>"
,
arg
->
name
());
}
else
{
out
->
print
(
" [<%s>]"
,
arg
->
name
());
}
arg
=
arg
->
next
();
}
out
->
print_cr
(
""
);
if
(
_arguments_list
!=
NULL
)
{
out
->
print_cr
(
"
\n
Arguments:"
);
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
out
->
print
(
"
\t
%s : %s %s (%s, "
,
arg
->
name
(),
arg
->
is_mandatory
()
?
""
:
"[optional]"
,
arg
->
description
(),
arg
->
type
());
if
(
arg
->
has_default
())
{
out
->
print
(
arg
->
default_string
());
}
else
{
out
->
print
(
"no default value"
);
}
out
->
print_cr
(
")"
);
arg
=
arg
->
next
();
}
}
if
(
_options
!=
NULL
)
{
out
->
print_cr
(
"
\n
Options: (options must be specified using the <key> or <key>=<value> syntax)"
);
arg
=
_options
;
while
(
arg
!=
NULL
)
{
out
->
print
(
"
\t
%s : %s %s (%s, "
,
arg
->
name
(),
arg
->
is_mandatory
()
?
""
:
"[optional]"
,
arg
->
description
(),
arg
->
type
());
if
(
arg
->
has_default
())
{
out
->
print
(
arg
->
default_string
());
}
else
{
out
->
print
(
"no default value"
);
}
out
->
print_cr
(
")"
);
arg
=
arg
->
next
();
}
}
}
void
DCmdParser
::
reset
(
TRAPS
)
{
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
arg
->
reset
(
CHECK
);
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
arg
->
reset
(
CHECK
);
arg
=
arg
->
next
();
}
}
void
DCmdParser
::
cleanup
()
{
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
arg
->
cleanup
();
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
arg
->
cleanup
();
arg
=
arg
->
next
();
}
}
int
DCmdParser
::
num_arguments
()
{
GenDCmdArgument
*
arg
=
_arguments_list
;
int
count
=
0
;
while
(
arg
!=
NULL
)
{
count
++
;
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
count
++
;
arg
=
arg
->
next
();
}
return
count
;
}
GrowableArray
<
const
char
*>*
DCmdParser
::
argument_name_array
()
{
int
count
=
num_arguments
();
GrowableArray
<
const
char
*>*
array
=
new
GrowableArray
<
const
char
*>
(
count
);
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
array
->
append
(
arg
->
name
());
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
array
->
append
(
arg
->
name
());
arg
=
arg
->
next
();
}
return
array
;
}
GrowableArray
<
DCmdArgumentInfo
*>*
DCmdParser
::
argument_info_array
()
{
int
count
=
num_arguments
();
GrowableArray
<
DCmdArgumentInfo
*>*
array
=
new
GrowableArray
<
DCmdArgumentInfo
*>
(
count
);
int
idx
=
0
;
GenDCmdArgument
*
arg
=
_arguments_list
;
while
(
arg
!=
NULL
)
{
array
->
append
(
new
DCmdArgumentInfo
(
arg
->
name
(),
arg
->
description
(),
arg
->
type
(),
arg
->
default_string
(),
arg
->
is_mandatory
(),
false
,
idx
));
idx
++
;
arg
=
arg
->
next
();
}
arg
=
_options
;
while
(
arg
!=
NULL
)
{
array
->
append
(
new
DCmdArgumentInfo
(
arg
->
name
(),
arg
->
description
(),
arg
->
type
(),
arg
->
default_string
(),
arg
->
is_mandatory
(),
true
));
arg
=
arg
->
next
();
}
return
array
;
}
DCmdFactory
*
DCmdFactory
::
_DCmdFactoryList
=
NULL
;
void
DCmd
::
parse_and_execute
(
outputStream
*
out
,
const
char
*
cmdline
,
char
delim
,
TRAPS
)
{
if
(
cmdline
==
NULL
)
return
;
// Nothing to do!
DCmdIter
iter
(
cmdline
,
'\n'
);
while
(
iter
.
has_next
())
{
CmdLine
line
=
iter
.
next
();
if
(
line
.
is_stop
())
{
break
;
}
if
(
line
.
is_executable
())
{
DCmd
*
command
=
DCmdFactory
::
create_local_DCmd
(
line
,
out
,
CHECK
);
assert
(
command
!=
NULL
,
"command error must be handled before this line"
);
DCmdMark
mark
(
command
);
command
->
parse
(
&
line
,
delim
,
CHECK
);
command
->
execute
(
CHECK
);
}
}
}
Mutex
*
DCmdFactory
::
_dcmdFactory_lock
=
new
Mutex
(
Mutex
::
leaf
,
"DCmdFactory"
,
true
);
DCmdFactory
*
DCmdFactory
::
factory
(
const
char
*
name
,
size_t
len
)
{
MutexLockerEx
ml
(
_dcmdFactory_lock
,
Mutex
::
_no_safepoint_check_flag
);
DCmdFactory
*
factory
=
_DCmdFactoryList
;
while
(
factory
!=
NULL
)
{
if
(
strlen
(
factory
->
name
())
==
len
&&
strncmp
(
name
,
factory
->
name
(),
len
)
==
0
)
{
return
factory
;
}
factory
=
factory
->
_next
;
}
return
NULL
;
}
int
DCmdFactory
::
register_DCmdFactory
(
DCmdFactory
*
factory
)
{
MutexLockerEx
ml
(
_dcmdFactory_lock
,
Mutex
::
_no_safepoint_check_flag
);
factory
->
_next
=
_DCmdFactoryList
;
_DCmdFactoryList
=
factory
;
return
0
;
// Actually, there's no checks for duplicates
}
DCmd
*
DCmdFactory
::
create_global_DCmd
(
CmdLine
&
line
,
outputStream
*
out
,
TRAPS
)
{
DCmdFactory
*
f
=
factory
(
line
.
cmd_addr
(),
line
.
cmd_len
());
if
(
f
!=
NULL
)
{
if
(
f
->
is_enabled
())
{
THROW_MSG_NULL
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
f
->
disabled_message
());
}
return
f
->
create_Cheap_instance
(
out
);
}
THROW_MSG_NULL
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Unknown diagnostic command"
);
}
DCmd
*
DCmdFactory
::
create_local_DCmd
(
CmdLine
&
line
,
outputStream
*
out
,
TRAPS
)
{
DCmdFactory
*
f
=
factory
(
line
.
cmd_addr
(),
line
.
cmd_len
());
if
(
f
!=
NULL
)
{
if
(
!
f
->
is_enabled
())
{
THROW_MSG_NULL
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
f
->
disabled_message
());
}
return
f
->
create_resource_instance
(
out
);
}
THROW_MSG_NULL
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Unknown diagnostic command"
);
}
GrowableArray
<
const
char
*>*
DCmdFactory
::
DCmd_list
()
{
MutexLockerEx
ml
(
_dcmdFactory_lock
,
Mutex
::
_no_safepoint_check_flag
);
GrowableArray
<
const
char
*>*
array
=
new
GrowableArray
<
const
char
*>
();
DCmdFactory
*
factory
=
_DCmdFactoryList
;
while
(
factory
!=
NULL
)
{
if
(
!
factory
->
is_hidden
())
{
array
->
append
(
factory
->
name
());
}
factory
=
factory
->
next
();
}
return
array
;
}
GrowableArray
<
DCmdInfo
*>*
DCmdFactory
::
DCmdInfo_list
()
{
MutexLockerEx
ml
(
_dcmdFactory_lock
,
Mutex
::
_no_safepoint_check_flag
);
GrowableArray
<
DCmdInfo
*>*
array
=
new
GrowableArray
<
DCmdInfo
*>
();
DCmdFactory
*
factory
=
_DCmdFactoryList
;
while
(
factory
!=
NULL
)
{
if
(
!
factory
->
is_hidden
())
{
array
->
append
(
new
DCmdInfo
(
factory
->
name
(),
factory
->
description
(),
factory
->
impact
(),
factory
->
num_arguments
(),
factory
->
is_enabled
()));
}
factory
=
factory
->
next
();
}
return
array
;
}
src/share/vm/services/diagnosticFramework.hpp
0 → 100644
浏览文件 @
4e06de41
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP
#define SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/vm_version.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/ostream.hpp"
// CmdLine is the class used to handle a command line containing a single
// diagnostic command and its arguments. It provides methods to access the
// command name and the beginning of the arguments. The class is also
// able to identify commented command lines and the "stop" keyword
class
CmdLine
:
public
StackObj
{
private:
const
char
*
_cmd
;
size_t
_cmd_len
;
const
char
*
_args
;
size_t
_args_len
;
public:
CmdLine
(
const
char
*
line
,
size_t
len
,
bool
no_command_name
);
const
char
*
args_addr
()
const
{
return
_args
;
}
size_t
args_len
()
const
{
return
_args_len
;
}
const
char
*
cmd_addr
()
const
{
return
_cmd
;
}
size_t
cmd_len
()
const
{
return
_cmd_len
;
}
bool
is_empty
()
{
return
_cmd_len
==
0
;
}
bool
is_executable
()
{
return
is_empty
()
||
_cmd
[
0
]
!=
'#'
;
}
bool
is_stop
()
{
return
!
is_empty
()
&&
strncmp
(
"stop"
,
_cmd
,
_cmd_len
)
==
0
;
}
};
// Iterator class taking a character string in input and returning a CmdLine
// instance for each command line. The argument delimiter has to be specified.
class
DCmdIter
:
public
StackObj
{
friend
class
DCmd
;
private:
const
char
*
_str
;
char
_delim
;
size_t
_len
;
size_t
_cursor
;
public:
DCmdIter
(
const
char
*
str
,
char
delim
)
{
_str
=
str
;
_delim
=
delim
;
_len
=
strlen
(
str
);
_cursor
=
0
;
}
bool
has_next
()
{
return
_cursor
<
_len
;
}
CmdLine
next
()
{
assert
(
_cursor
<=
_len
,
"Cannot iterate more"
);
size_t
n
=
_cursor
;
while
(
n
<
_len
&&
_str
[
n
]
!=
_delim
)
n
++
;
CmdLine
line
(
&
(
_str
[
_cursor
]),
n
-
_cursor
,
false
);
_cursor
=
n
+
1
;
// The default copy constructor of CmdLine is used to return a CmdLine
// instance to the caller.
return
line
;
}
};
// Iterator class to iterate over diagnostic command arguments
class
DCmdArgIter
:
public
ResourceObj
{
const
char
*
_buffer
;
size_t
_len
;
size_t
_cursor
;
const
char
*
_key_addr
;
size_t
_key_len
;
const
char
*
_value_addr
;
size_t
_value_len
;
char
_delim
;
public:
DCmdArgIter
(
const
char
*
buf
,
size_t
len
,
char
delim
)
{
_buffer
=
buf
;
_len
=
len
;
_delim
=
delim
;
_cursor
=
0
;
}
bool
next
(
TRAPS
);
const
char
*
key_addr
()
{
return
_key_addr
;
}
size_t
key_length
()
{
return
_key_len
;
}
const
char
*
value_addr
()
{
return
_value_addr
;
}
size_t
value_length
()
{
return
_value_len
;
}
};
// A DCmdInfo instance provides a description of a diagnostic command. It is
// used to export the description to the JMX interface of the framework.
class
DCmdInfo
:
public
ResourceObj
{
protected:
const
char
*
_name
;
const
char
*
_description
;
const
char
*
_impact
;
int
_num_arguments
;
bool
_is_enabled
;
public:
DCmdInfo
(
const
char
*
name
,
const
char
*
description
,
const
char
*
impact
,
int
num_arguments
,
bool
enabled
)
{
this
->
_name
=
name
;
this
->
_description
=
description
;
this
->
_impact
=
impact
;
this
->
_num_arguments
=
num_arguments
;
this
->
_is_enabled
=
enabled
;
}
const
char
*
name
()
const
{
return
_name
;
}
const
char
*
description
()
const
{
return
_description
;
}
const
char
*
impact
()
const
{
return
_impact
;
}
int
num_arguments
()
const
{
return
_num_arguments
;
}
bool
is_enabled
()
const
{
return
_is_enabled
;
}
static
bool
by_name
(
void
*
name
,
DCmdInfo
*
info
);
};
// A DCmdArgumentInfo instance provides a description of a diagnostic command
// argument. It is used to export the description to the JMX interface of the
// framework.
class
DCmdArgumentInfo
:
public
ResourceObj
{
protected:
const
char
*
_name
;
const
char
*
_description
;
const
char
*
_type
;
const
char
*
_default_string
;
bool
_mandatory
;
bool
_option
;
int
_position
;
public:
DCmdArgumentInfo
(
const
char
*
name
,
const
char
*
description
,
const
char
*
type
,
const
char
*
default_string
,
bool
mandatory
,
bool
option
)
{
this
->
_name
=
name
;
this
->
_description
=
description
;
this
->
_type
=
type
;
this
->
_default_string
=
default_string
;
this
->
_option
=
option
;
this
->
_mandatory
=
mandatory
;
this
->
_option
=
option
;
this
->
_position
=
-
1
;
}
DCmdArgumentInfo
(
const
char
*
name
,
const
char
*
description
,
const
char
*
type
,
const
char
*
default_string
,
bool
mandatory
,
bool
option
,
int
position
)
{
this
->
_name
=
name
;
this
->
_description
=
description
;
this
->
_type
=
type
;
this
->
_default_string
=
default_string
;
this
->
_option
=
option
;
this
->
_mandatory
=
mandatory
;
this
->
_option
=
option
;
this
->
_position
=
position
;
}
const
char
*
name
()
const
{
return
_name
;
}
const
char
*
description
()
const
{
return
_description
;
}
const
char
*
type
()
const
{
return
_type
;
}
const
char
*
default_string
()
const
{
return
_default_string
;
}
bool
is_mandatory
()
const
{
return
_mandatory
;
}
bool
is_option
()
const
{
return
_option
;
}
int
position
()
const
{
return
_position
;
}
};
// The DCmdParser class can be used to create an argument parser for a
// diagnostic command. It is not mandatory to use it to parse arguments.
class
DCmdParser
{
private:
GenDCmdArgument
*
_options
;
GenDCmdArgument
*
_arguments_list
;
char
_delim
;
public:
DCmdParser
()
{
_options
=
NULL
;
_arguments_list
=
NULL
;
}
void
add_dcmd_option
(
GenDCmdArgument
*
arg
);
void
add_dcmd_argument
(
GenDCmdArgument
*
arg
);
GenDCmdArgument
*
lookup_dcmd_option
(
const
char
*
name
,
size_t
len
);
GenDCmdArgument
*
arguments_list
()
{
return
_arguments_list
;
};
void
check
(
TRAPS
);
void
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
);
void
print_help
(
outputStream
*
out
,
const
char
*
cmd_name
);
void
reset
(
TRAPS
);
void
cleanup
();
int
num_arguments
();
GrowableArray
<
const
char
*>*
argument_name_array
();
GrowableArray
<
DCmdArgumentInfo
*>*
argument_info_array
();
};
// The DCmd class is the parent class of all diagnostic commands
// Diagnostic command instances should not be instantiated directly but
// created using the associated factory. The factory can be retrieved with
// the DCmdFactory::getFactory() method.
// A diagnostic command instance can either be allocated in the resource Area
// or in the C-heap. Allocation in the resource area is recommended when the
// current thread is the only one which will access the diagnostic command
// instance. Allocation in the C-heap is required when the diagnostic command
// is accessed by several threads (for instance to perform asynchronous
// execution).
// To ensure a proper cleanup, it's highly recommended to use a DCmdMark for
// each diagnostic command instance. In case of a C-heap allocated diagnostic
// command instance, the DCmdMark must be created in the context of the last
// thread that will access the instance.
class
DCmd
:
public
ResourceObj
{
protected:
outputStream
*
_output
;
bool
_is_heap_allocated
;
public:
DCmd
(
outputStream
*
output
,
bool
heap_allocated
)
{
_output
=
output
;
_is_heap_allocated
=
heap_allocated
;
}
static
const
char
*
name
()
{
return
"No Name"
;}
static
const
char
*
description
()
{
return
"No Help"
;}
static
const
char
*
disabled_message
()
{
return
"Diagnostic command currently disabled"
;
}
static
const
char
*
impact
()
{
return
"Low: No impact"
;
}
static
int
num_arguments
()
{
return
0
;
}
outputStream
*
output
()
{
return
_output
;
}
bool
is_heap_allocated
()
{
return
_is_heap_allocated
;
}
virtual
void
print_help
(
outputStream
*
out
)
{
};
virtual
void
parse
(
CmdLine
*
line
,
char
delim
,
TRAPS
)
{
}
virtual
void
execute
(
TRAPS
)
{
}
virtual
void
reset
(
TRAPS
)
{
}
virtual
void
cleanup
()
{
}
// support for the JMX interface
virtual
GrowableArray
<
const
char
*>*
argument_name_array
()
{
GrowableArray
<
const
char
*>*
array
=
new
GrowableArray
<
const
char
*>
(
0
);
return
array
;
}
virtual
GrowableArray
<
DCmdArgumentInfo
*>*
argument_info_array
()
{
GrowableArray
<
DCmdArgumentInfo
*>*
array
=
new
GrowableArray
<
DCmdArgumentInfo
*>
(
0
);
return
array
;
}
// main method to invoke the framework
static
void
parse_and_execute
(
outputStream
*
out
,
const
char
*
cmdline
,
char
delim
,
TRAPS
);
};
class
DCmdMark
:
public
StackObj
{
DCmd
*
_ref
;
public:
DCmdMark
(
DCmd
*
cmd
)
{
_ref
=
cmd
;
}
~
DCmdMark
()
{
if
(
_ref
!=
NULL
)
{
_ref
->
cleanup
();
if
(
_ref
->
is_heap_allocated
())
{
delete
_ref
;
}
}
}
};
// Diagnostic commands are not directly instantiated but created with a factory.
// Each diagnostic command class has its own factory. The DCmdFactory class also
// manages the status of the diagnostic command (hidden, enabled). A DCmdFactory
// has to be registered to make the diagnostic command available (see
// management.cpp)
class
DCmdFactory
:
public
CHeapObj
{
private:
static
Mutex
*
_dcmdFactory_lock
;
// Pointer to the next factory in the singly-linked list of registered
// diagnostic commands
DCmdFactory
*
_next
;
// When disabled, a diagnostic command cannot be executed. Any attempt to
// execute it will result in the printing of the disabled message without
// instantiating the command.
bool
_enabled
;
// When hidden, a diagnostic command doesn't appear in the list of commands
// provided by the 'help' command.
bool
_hidden
;
int
_num_arguments
;
static
DCmdFactory
*
_DCmdFactoryList
;
public:
DCmdFactory
(
int
num_arguments
,
bool
enabled
,
bool
hidden
)
{
_next
=
NULL
;
_enabled
=
enabled
;
_hidden
=
hidden
;
_num_arguments
=
num_arguments
;
}
bool
is_enabled
()
const
{
return
_enabled
;
}
void
set_enabled
(
bool
b
)
{
_enabled
=
b
;
}
bool
is_hidden
()
const
{
return
_hidden
;
}
void
set_hidden
(
bool
b
)
{
_hidden
=
b
;
}
int
num_arguments
()
{
return
_num_arguments
;
}
DCmdFactory
*
next
()
{
return
_next
;
}
virtual
DCmd
*
create_Cheap_instance
(
outputStream
*
output
)
=
0
;
virtual
DCmd
*
create_resource_instance
(
outputStream
*
output
)
=
0
;
virtual
const
char
*
name
()
const
=
0
;
virtual
const
char
*
description
()
const
=
0
;
virtual
const
char
*
impact
()
const
=
0
;
virtual
const
char
*
disabled_message
()
const
=
0
;
// Register a DCmdFactory to make a diagnostic command available.
// Once registered, a diagnostic command must not be unregistered.
// To prevent a diagnostic command from being executed, just set the
// enabled flag to false.
static
int
register_DCmdFactory
(
DCmdFactory
*
factory
);
static
DCmdFactory
*
factory
(
const
char
*
cmd
,
size_t
len
);
// Returns a C-heap allocated diagnostic command for the given command line
static
DCmd
*
create_global_DCmd
(
CmdLine
&
line
,
outputStream
*
out
,
TRAPS
);
// Returns a resourceArea allocated diagnostic command for the given command line
static
DCmd
*
create_local_DCmd
(
CmdLine
&
line
,
outputStream
*
out
,
TRAPS
);
static
GrowableArray
<
const
char
*>*
DCmd_list
();
static
GrowableArray
<
DCmdInfo
*>*
DCmdInfo_list
();
friend
class
HelpDCmd
;
};
// Template to easily create DCmdFactory instances. See management.cpp
// where this template is used to create and register factories.
template
<
class
DCmdClass
>
class
DCmdFactoryImpl
:
public
DCmdFactory
{
public:
DCmdFactoryImpl
(
bool
enabled
,
bool
hidden
)
:
DCmdFactory
(
DCmdClass
::
num_arguments
(),
enabled
,
hidden
)
{
}
// Returns a C-heap allocated instance
virtual
DCmd
*
create_Cheap_instance
(
outputStream
*
output
)
{
return
new
(
ResourceObj
::
C_HEAP
)
DCmdClass
(
output
,
true
);
}
// Returns a resourceArea allocated instance
virtual
DCmd
*
create_resource_instance
(
outputStream
*
output
)
{
return
new
DCmdClass
(
output
,
false
);
}
virtual
const
char
*
name
()
const
{
return
DCmdClass
::
name
();
}
virtual
const
char
*
description
()
const
{
return
DCmdClass
::
description
();
}
virtual
const
char
*
impact
()
const
{
return
DCmdClass
::
impact
();
}
virtual
const
char
*
disabled_message
()
const
{
return
DCmdClass
::
disabled_message
();
}
};
#endif // SHARE_VM_SERVICES_DIAGNOSTICFRAMEWORK_HPP
src/share/vm/services/jmm.h
浏览文件 @
4e06de41
...
@@ -48,7 +48,8 @@ enum {
...
@@ -48,7 +48,8 @@ enum {
JMM_VERSION_1_0
=
0x20010000
,
JMM_VERSION_1_0
=
0x20010000
,
JMM_VERSION_1_1
=
0x20010100
,
// JDK 6
JMM_VERSION_1_1
=
0x20010100
,
// JDK 6
JMM_VERSION_1_2
=
0x20010200
,
// JDK 7
JMM_VERSION_1_2
=
0x20010200
,
// JDK 7
JMM_VERSION
=
0x20010201
JMM_VERSION_1_2_1
=
0x20010201
,
// JDK 7 GA
JMM_VERSION
=
0x20010202
};
};
typedef
struct
{
typedef
struct
{
...
@@ -188,6 +189,24 @@ typedef struct {
...
@@ -188,6 +189,24 @@ typedef struct {
/* -1 indicates gc_ext_attribute_values is not big enough */
/* -1 indicates gc_ext_attribute_values is not big enough */
}
jmmGCStat
;
}
jmmGCStat
;
typedef
struct
{
const
char
*
name
;
const
char
*
description
;
const
char
*
impact
;
int
num_arguments
;
jboolean
enabled
;
}
dcmdInfo
;
typedef
struct
{
const
char
*
name
;
const
char
*
description
;
const
char
*
type
;
const
char
*
default_string
;
jboolean
mandatory
;
jboolean
option
;
int
position
;
}
dcmdArgInfo
;
typedef
struct
jmmInterface_1_
{
typedef
struct
jmmInterface_1_
{
void
*
reserved1
;
void
*
reserved1
;
void
*
reserved2
;
void
*
reserved2
;
...
@@ -296,6 +315,18 @@ typedef struct jmmInterface_1_ {
...
@@ -296,6 +315,18 @@ typedef struct jmmInterface_1_ {
void
(
JNICALL
*
SetGCNotificationEnabled
)
(
JNIEnv
*
env
,
void
(
JNICALL
*
SetGCNotificationEnabled
)
(
JNIEnv
*
env
,
jobject
mgr
,
jobject
mgr
,
jboolean
enabled
);
jboolean
enabled
);
jobjectArray
(
JNICALL
*
GetDiagnosticCommands
)
(
JNIEnv
*
env
);
void
(
JNICALL
*
GetDiagnosticCommandInfo
)
(
JNIEnv
*
env
,
jobjectArray
cmds
,
dcmdInfo
*
infoArray
);
void
(
JNICALL
*
GetDiagnosticCommandArgumentsInfo
)
(
JNIEnv
*
env
,
jstring
commandName
,
dcmdArgInfo
*
infoArray
);
jstring
(
JNICALL
*
ExecuteDiagnosticCommand
)
(
JNIEnv
*
env
,
jstring
command
);
}
JmmInterface
;
}
JmmInterface
;
#ifdef __cplusplus
#ifdef __cplusplus
...
...
src/share/vm/services/management.cpp
浏览文件 @
4e06de41
...
@@ -40,7 +40,10 @@
...
@@ -40,7 +40,10 @@
#include "runtime/os.hpp"
#include "runtime/os.hpp"
#include "runtime/serviceThread.hpp"
#include "runtime/serviceThread.hpp"
#include "services/classLoadingService.hpp"
#include "services/classLoadingService.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/diagnosticFramework.hpp"
#include "services/heapDumper.hpp"
#include "services/heapDumper.hpp"
#include "services/jmm.h"
#include "services/lowMemoryDetector.hpp"
#include "services/lowMemoryDetector.hpp"
#include "services/gcNotifier.hpp"
#include "services/gcNotifier.hpp"
#include "services/management.hpp"
#include "services/management.hpp"
...
@@ -113,6 +116,9 @@ void Management::init() {
...
@@ -113,6 +116,9 @@ void Management::init() {
_optional_support
.
isSynchronizerUsageSupported
=
1
;
_optional_support
.
isSynchronizerUsageSupported
=
1
;
#endif // SERVICES_KERNEL
#endif // SERVICES_KERNEL
_optional_support
.
isThreadAllocatedMemorySupported
=
1
;
_optional_support
.
isThreadAllocatedMemorySupported
=
1
;
DCmdFactory
::
register_DCmdFactory
(
new
DCmdFactoryImpl
<
HelpDCmd
>
(
true
,
false
));
DCmdFactory
::
register_DCmdFactory
(
new
DCmdFactoryImpl
<
VersionDCmd
>
(
true
,
false
));
}
}
void
Management
::
initialize
(
TRAPS
)
{
void
Management
::
initialize
(
TRAPS
)
{
...
@@ -2107,6 +2113,122 @@ JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
...
@@ -2107,6 +2113,122 @@ JVM_ENTRY(jint, jmm_DumpHeap0(JNIEnv *env, jstring outputfile, jboolean live))
#endif // SERVICES_KERNEL
#endif // SERVICES_KERNEL
JVM_END
JVM_END
JVM_ENTRY
(
jobjectArray
,
jmm_GetDiagnosticCommands
(
JNIEnv
*
env
))
ResourceMark
rm
(
THREAD
);
GrowableArray
<
const
char
*>*
dcmd_list
=
DCmdFactory
::
DCmd_list
();
objArrayOop
cmd_array_oop
=
oopFactory
::
new_objArray
(
SystemDictionary
::
String_klass
(),
dcmd_list
->
length
(),
CHECK_NULL
);
objArrayHandle
cmd_array
(
THREAD
,
cmd_array_oop
);
for
(
int
i
=
0
;
i
<
dcmd_list
->
length
();
i
++
)
{
oop
cmd_name
=
java_lang_String
::
create_oop_from_str
(
dcmd_list
->
at
(
i
),
CHECK_NULL
);
cmd_array
->
obj_at_put
(
i
,
cmd_name
);
}
return
(
jobjectArray
)
JNIHandles
::
make_local
(
env
,
cmd_array
());
JVM_END
JVM_ENTRY
(
void
,
jmm_GetDiagnosticCommandInfo
(
JNIEnv
*
env
,
jobjectArray
cmds
,
dcmdInfo
*
infoArray
))
if
(
cmds
==
NULL
||
infoArray
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_NullPointerException
());
}
ResourceMark
rm
(
THREAD
);
objArrayOop
ca
=
objArrayOop
(
JNIHandles
::
resolve_non_null
(
cmds
));
objArrayHandle
cmds_ah
(
THREAD
,
ca
);
// Make sure we have a String array
klassOop
element_klass
=
objArrayKlass
::
cast
(
cmds_ah
->
klass
())
->
element_klass
();
if
(
element_klass
!=
SystemDictionary
::
String_klass
())
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Array element type is not String class"
);
}
GrowableArray
<
DCmdInfo
*>*
info_list
=
DCmdFactory
::
DCmdInfo_list
();
int
num_cmds
=
cmds_ah
->
length
();
for
(
int
i
=
0
;
i
<
num_cmds
;
i
++
)
{
oop
cmd
=
cmds_ah
->
obj_at
(
i
);
if
(
cmd
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command name cannot be null."
);
}
char
*
cmd_name
=
java_lang_String
::
as_utf8_string
(
cmd
);
if
(
cmd_name
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command name cannot be null."
);
}
int
pos
=
info_list
->
find
((
void
*
)
cmd_name
,
DCmdInfo
::
by_name
);
if
(
pos
==
-
1
)
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Unknown diagnostic command"
);
}
DCmdInfo
*
info
=
info_list
->
at
(
pos
);
infoArray
[
i
].
name
=
info
->
name
();
infoArray
[
i
].
description
=
info
->
description
();
infoArray
[
i
].
impact
=
info
->
impact
();
infoArray
[
i
].
num_arguments
=
info
->
num_arguments
();
infoArray
[
i
].
enabled
=
info
->
is_enabled
();
}
JVM_END
JVM_ENTRY
(
void
,
jmm_GetDiagnosticCommandArgumentsInfo
(
JNIEnv
*
env
,
jstring
command
,
dcmdArgInfo
*
infoArray
))
ResourceMark
rm
(
THREAD
);
oop
cmd
=
JNIHandles
::
resolve_external_guard
(
command
);
if
(
cmd
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command line cannot be null."
);
}
char
*
cmd_name
=
java_lang_String
::
as_utf8_string
(
cmd
);
if
(
cmd_name
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command line content cannot be null."
);
}
DCmd
*
dcmd
=
NULL
;
DCmdFactory
*
factory
=
DCmdFactory
::
factory
(
cmd_name
,
strlen
(
cmd_name
));
if
(
factory
!=
NULL
)
{
dcmd
=
factory
->
create_resource_instance
(
NULL
);
}
if
(
dcmd
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_IllegalArgumentException
(),
"Unknown diagnostic command"
);
}
DCmdMark
mark
(
dcmd
);
GrowableArray
<
DCmdArgumentInfo
*>*
array
=
dcmd
->
argument_info_array
();
if
(
array
->
length
()
==
0
)
{
return
;
}
for
(
int
i
=
0
;
i
<
array
->
length
();
i
++
)
{
infoArray
[
i
].
name
=
array
->
at
(
i
)
->
name
();
infoArray
[
i
].
description
=
array
->
at
(
i
)
->
description
();
infoArray
[
i
].
type
=
array
->
at
(
i
)
->
type
();
infoArray
[
i
].
default_string
=
array
->
at
(
i
)
->
default_string
();
infoArray
[
i
].
mandatory
=
array
->
at
(
i
)
->
is_mandatory
();
infoArray
[
i
].
option
=
array
->
at
(
i
)
->
is_option
();
infoArray
[
i
].
position
=
array
->
at
(
i
)
->
position
();
}
return
;
JVM_END
JVM_ENTRY
(
jstring
,
jmm_ExecuteDiagnosticCommand
(
JNIEnv
*
env
,
jstring
commandline
))
ResourceMark
rm
(
THREAD
);
oop
cmd
=
JNIHandles
::
resolve_external_guard
(
commandline
);
if
(
cmd
==
NULL
)
{
THROW_MSG_NULL
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command line cannot be null."
);
}
char
*
cmdline
=
java_lang_String
::
as_utf8_string
(
cmd
);
if
(
cmdline
==
NULL
)
{
THROW_MSG_NULL
(
vmSymbols
::
java_lang_NullPointerException
(),
"Command line content cannot be null."
);
}
bufferedStream
output
;
DCmd
::
parse_and_execute
(
&
output
,
cmdline
,
' '
,
CHECK_NULL
);
oop
result
=
java_lang_String
::
create_oop_from_str
(
output
.
as_string
(),
CHECK_NULL
);
return
(
jstring
)
JNIHandles
::
make_local
(
env
,
result
);
JVM_END
jlong
Management
::
ticks_to_ms
(
jlong
ticks
)
{
jlong
Management
::
ticks_to_ms
(
jlong
ticks
)
{
assert
(
os
::
elapsed_frequency
()
>
0
,
"Must be non-zero"
);
assert
(
os
::
elapsed_frequency
()
>
0
,
"Must be non-zero"
);
return
(
jlong
)(((
double
)
ticks
/
(
double
)
os
::
elapsed_frequency
())
return
(
jlong
)(((
double
)
ticks
/
(
double
)
os
::
elapsed_frequency
())
...
@@ -2149,7 +2271,11 @@ const struct jmmInterface_1_ jmm_interface = {
...
@@ -2149,7 +2271,11 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_SetVMGlobal
,
jmm_SetVMGlobal
,
NULL
,
NULL
,
jmm_DumpThreads
,
jmm_DumpThreads
,
jmm_SetGCNotificationEnabled
jmm_SetGCNotificationEnabled
,
jmm_GetDiagnosticCommands
,
jmm_GetDiagnosticCommandInfo
,
jmm_GetDiagnosticCommandArgumentsInfo
,
jmm_ExecuteDiagnosticCommand
};
};
void
*
Management
::
get_jmm_interface
(
int
version
)
{
void
*
Management
::
get_jmm_interface
(
int
version
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录