Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
a775ffd6
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
3
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
a775ffd6
编写于
5月 11, 2011
作者:
S
schien
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
2dd0b245
009e8694
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
1541 addition
and
1 deletion
+1541
-1
make/java/management/Makefile
make/java/management/Makefile
+14
-0
make/java/management/mapfile-vers
make/java/management/mapfile-vers
+2
-0
src/share/classes/com/sun/management/OperatingSystemMXBean.java
...are/classes/com/sun/management/OperatingSystemMXBean.java
+35
-0
src/solaris/classes/com/sun/management/UnixOperatingSystem.java
...laris/classes/com/sun/management/UnixOperatingSystem.java
+2
-0
src/solaris/native/com/sun/management/LinuxOperatingSystem.c
src/solaris/native/com/sun/management/LinuxOperatingSystem.c
+332
-0
src/solaris/native/com/sun/management/SolarisOperatingSystem.c
...olaris/native/com/sun/management/SolarisOperatingSystem.c
+241
-0
src/windows/classes/com/sun/management/OperatingSystem.java
src/windows/classes/com/sun/management/OperatingSystem.java
+2
-0
src/windows/native/com/sun/management/OperatingSystem_md.c
src/windows/native/com/sun/management/OperatingSystem_md.c
+807
-1
test/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java
...n/management/OperatingSystemMXBean/GetProcessCpuLoad.java
+53
-0
test/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java
...un/management/OperatingSystemMXBean/GetSystemCpuLoad.java
+53
-0
未找到文件。
make/java/management/Makefile
浏览文件 @
a775ffd6
...
...
@@ -63,6 +63,20 @@ else # PLATFORM (i.e. solaris & linux)
FILES_c
+=
UnixOperatingSystem_md.c
FILES_export
+=
com/sun/management/UnixOperatingSystem.java
ifeq
($(PLATFORM),solaris)
FILES_c
+=
SolarisOperatingSystem.c
OTHER_LDLIBS
+=
-lkstat
endif
# PLATFORM solaris
ifeq
($(PLATFORM),linux)
FILES_c
+=
LinuxOperatingSystem.c
endif
# PLATFORM linux
endif
# PLATFORM
#
...
...
make/java/management/mapfile-vers
浏览文件 @
a775ffd6
...
...
@@ -32,7 +32,9 @@ SUNWprivate_1.1 {
Java_com_sun_management_UnixOperatingSystem_getFreeSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_getMaxFileDescriptorCount;
Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount;
Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad;
Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime;
Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad;
Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize;
Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize;
Java_com_sun_management_UnixOperatingSystem_initialize;
...
...
src/share/classes/com/sun/management/OperatingSystemMXBean.java
浏览文件 @
a775ffd6
...
...
@@ -92,4 +92,39 @@ public interface OperatingSystemMXBean extends
* @return the total amount of physical memory in bytes.
*/
public
long
getTotalPhysicalMemorySize
();
/**
* Returns the "recent cpu usage" for the whole system. This value is a
* double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs
* were idle during the recent period of time observed, while a value
* of 1.0 means that all CPUs were actively running 100% of the time
* during the recent period being observed. All values betweens 0.0 and
* 1.0 are possible depending of the activities going on in the system.
* If the system recent cpu usage is not available, the method returns a
* negative value.
*
* @return the "recent cpu usage" for the whole system; a negative
* value if not available.
* @since 1.7
*/
public
double
getSystemCpuLoad
();
/**
* Returns the "recent cpu usage" for the Java Virtual Machine process.
* This value is a double in the [0.0,1.0] interval. A value of 0.0 means
* that none of the CPUs were running threads from the JVM process during
* the recent period of time observed, while a value of 1.0 means that all
* CPUs were actively running threads from the JVM 100% of the time
* during the recent period being observed. Threads from the JVM include
* the application threads as well as the JVM internal threads. All values
* betweens 0.0 and 1.0 are possible depending of the activities going on
* in the JVM process and the whole system. If the Java Virtual Machine
* recent CPU usage is not available, the method returns a negative value.
*
* @return the "recent cpu usage" for the Java Virtual Machine process;
* a negative value if not available.
* @since 1.7
*/
public
double
getProcessCpuLoad
();
}
src/solaris/classes/com/sun/management/UnixOperatingSystem.java
浏览文件 @
a775ffd6
...
...
@@ -50,6 +50,8 @@ class UnixOperatingSystem
public
native
long
getTotalPhysicalMemorySize
();
public
native
long
getOpenFileDescriptorCount
();
public
native
long
getMaxFileDescriptorCount
();
public
native
double
getSystemCpuLoad
();
public
native
double
getProcessCpuLoad
();
static
{
initialize
();
...
...
src/solaris/native/com/sun/management/LinuxOperatingSystem.c
0 → 100644
浏览文件 @
a775ffd6
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <pthread.h>
#include "com_sun_management_UnixOperatingSystem.h"
struct
ticks
{
uint64_t
used
;
uint64_t
usedKernel
;
uint64_t
total
;
};
typedef
struct
ticks
ticks
;
typedef
enum
{
CPU_LOAD_VM_ONLY
,
CPU_LOAD_GLOBAL
,
}
CpuLoadTarget
;
static
struct
perfbuf
{
int
nProcs
;
ticks
jvmTicks
;
ticks
cpuTicks
;
ticks
*
cpus
;
}
counters
;
#define DEC_64 "%lld"
static
void
next_line
(
FILE
*
f
)
{
while
(
fgetc
(
f
)
!=
'\n'
);
}
/**
* Return the total number of ticks since the system was booted.
* If the usedTicks parameter is not NULL, it will be filled with
* the number of ticks spent on actual processes (user, system or
* nice processes) since system boot. Note that this is the total number
* of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
* n times the number of ticks that has passed in clock time.
*
* Returns a negative value if the reading of the ticks failed.
*/
static
int
get_totalticks
(
int
which
,
ticks
*
pticks
)
{
FILE
*
fh
;
uint64_t
userTicks
,
niceTicks
,
systemTicks
,
idleTicks
;
int
n
;
if
((
fh
=
fopen
(
"/proc/stat"
,
"r"
))
==
NULL
)
{
return
-
1
;
}
n
=
fscanf
(
fh
,
"cpu "
DEC_64
" "
DEC_64
" "
DEC_64
" "
DEC_64
,
&
userTicks
,
&
niceTicks
,
&
systemTicks
,
&
idleTicks
);
// Move to next line
next_line
(
fh
);
//find the line for requested cpu faster to just iterate linefeeds?
if
(
which
!=
-
1
)
{
int
i
;
for
(
i
=
0
;
i
<
which
;
i
++
)
{
if
(
fscanf
(
fh
,
"cpu%*d "
DEC_64
" "
DEC_64
" "
DEC_64
" "
DEC_64
,
&
userTicks
,
&
niceTicks
,
&
systemTicks
,
&
idleTicks
)
!=
4
)
{
fclose
(
fh
);
return
-
2
;
}
next_line
(
fh
);
}
n
=
fscanf
(
fh
,
"cpu%*d "
DEC_64
" "
DEC_64
" "
DEC_64
" "
DEC_64
"
\n
"
,
&
userTicks
,
&
niceTicks
,
&
systemTicks
,
&
idleTicks
);
}
fclose
(
fh
);
if
(
n
!=
4
)
{
return
-
2
;
}
pticks
->
used
=
userTicks
+
niceTicks
;
pticks
->
usedKernel
=
systemTicks
;
pticks
->
total
=
userTicks
+
niceTicks
+
systemTicks
+
idleTicks
;
return
0
;
}
static
int
vread_statdata
(
const
char
*
procfile
,
const
char
*
fmt
,
va_list
args
)
{
FILE
*
f
;
int
n
;
char
buf
[
2048
];
if
((
f
=
fopen
(
procfile
,
"r"
))
==
NULL
)
{
return
-
1
;
}
if
((
n
=
fread
(
buf
,
1
,
sizeof
(
buf
),
f
))
!=
-
1
)
{
char
*
tmp
;
buf
[
n
-
1
]
=
'\0'
;
/** skip through pid and exec name. the exec name _could be wacky_ (renamed) and
* make scanf go mupp.
*/
if
((
tmp
=
strrchr
(
buf
,
')'
))
!=
NULL
)
{
// skip the ')' and the following space but check that the buffer is long enough
tmp
+=
2
;
if
(
tmp
<
buf
+
n
)
{
n
=
vsscanf
(
tmp
,
fmt
,
args
);
}
}
}
fclose
(
f
);
return
n
;
}
static
int
read_statdata
(
const
char
*
procfile
,
const
char
*
fmt
,
...)
{
int
n
;
va_list
args
;
va_start
(
args
,
fmt
);
n
=
vread_statdata
(
procfile
,
fmt
,
args
);
va_end
(
args
);
return
n
;
}
/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
static
int
read_ticks
(
const
char
*
procfile
,
uint64_t
*
userTicks
,
uint64_t
*
systemTicks
)
{
return
read_statdata
(
procfile
,
"%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "
DEC_64
" "
DEC_64
,
userTicks
,
systemTicks
);
}
/**
* Return the number of ticks spent in any of the processes belonging
* to the JVM on any CPU.
*/
static
int
get_jvmticks
(
ticks
*
pticks
)
{
uint64_t
userTicks
;
uint64_t
systemTicks
;
if
(
read_ticks
(
"/proc/self/stat"
,
&
userTicks
,
&
systemTicks
)
<
0
)
{
return
-
1
;
}
// get the total
if
(
get_totalticks
(
-
1
,
pticks
)
<
0
)
{
return
-
1
;
}
pticks
->
used
=
userTicks
;
pticks
->
usedKernel
=
systemTicks
;
return
0
;
}
/**
* This method must be called first, before any data can be gathererd.
*/
int
perfInit
()
{
static
int
initialized
=
1
;
if
(
!
initialized
)
{
int
i
;
int
n
=
sysconf
(
_SC_NPROCESSORS_ONLN
);
if
(
n
<=
0
)
{
n
=
1
;
}
counters
.
cpus
=
calloc
(
n
,
sizeof
(
ticks
));
if
(
counters
.
cpus
!=
NULL
)
{
// For the CPU load
get_totalticks
(
-
1
,
&
counters
.
cpuTicks
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
get_totalticks
(
i
,
&
counters
.
cpus
[
i
]);
}
// For JVM load
get_jvmticks
(
&
counters
.
jvmTicks
);
initialized
=
1
;
}
}
return
initialized
?
0
:
-
1
;
}
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
static
pthread_mutex_t
lock
=
PTHREAD_MUTEX_INITIALIZER
;
/**
* Return the load of the CPU as a double. 1.0 means the CPU process uses all
* available time for user or system processes, 0.0 means the CPU uses all time
* being idle.
*
* Returns a negative value if there is a problem in determining the CPU load.
*/
static
double
get_cpuload_internal
(
int
which
,
double
*
pkernelLoad
,
CpuLoadTarget
target
)
{
uint64_t
udiff
,
kdiff
,
tdiff
;
ticks
*
pticks
,
tmp
;
double
user_load
=
-
1
.
0
;
int
failed
=
0
;
*
pkernelLoad
=
0
.
0
;
pthread_mutex_lock
(
&
lock
);
if
(
perfInit
()
==
0
)
{
if
(
target
==
CPU_LOAD_VM_ONLY
)
{
pticks
=
&
counters
.
jvmTicks
;
}
else
if
(
which
==
-
1
)
{
pticks
=
&
counters
.
cpuTicks
;
}
else
{
pticks
=
&
counters
.
cpus
[
which
];
}
tmp
=
*
pticks
;
if
(
target
==
CPU_LOAD_VM_ONLY
)
{
if
(
get_jvmticks
(
pticks
)
!=
0
)
{
failed
=
1
;
}
}
else
if
(
get_totalticks
(
which
,
pticks
)
<
0
)
{
failed
=
1
;
}
if
(
!
failed
)
{
// seems like we sometimes end up with less kernel ticks when
// reading /proc/self/stat a second time, timing issue between cpus?
if
(
pticks
->
usedKernel
<
tmp
.
usedKernel
)
{
kdiff
=
0
;
}
else
{
kdiff
=
pticks
->
usedKernel
-
tmp
.
usedKernel
;
}
tdiff
=
pticks
->
total
-
tmp
.
total
;
udiff
=
pticks
->
used
-
tmp
.
used
;
if
(
tdiff
==
0
)
{
user_load
=
0
;
}
else
{
if
(
tdiff
<
(
udiff
+
kdiff
))
{
tdiff
=
udiff
+
kdiff
;
}
*
pkernelLoad
=
(
kdiff
/
(
double
)
tdiff
);
// BUG9044876, normalize return values to sane values
*
pkernelLoad
=
MAX
(
*
pkernelLoad
,
0
.
0
);
*
pkernelLoad
=
MIN
(
*
pkernelLoad
,
1
.
0
);
user_load
=
(
udiff
/
(
double
)
tdiff
);
user_load
=
MAX
(
user_load
,
0
.
0
);
user_load
=
MIN
(
user_load
,
1
.
0
);
}
}
}
pthread_mutex_unlock
(
&
lock
);
return
user_load
;
}
double
get_cpu_load
(
int
which
)
{
double
u
,
s
;
u
=
get_cpuload_internal
(
which
,
&
s
,
CPU_LOAD_GLOBAL
);
if
(
u
<
0
)
{
return
-
1
.
0
;
}
// Cap total systemload to 1.0
return
MIN
((
u
+
s
),
1
.
0
);
}
double
get_process_load
()
{
double
u
,
s
;
u
=
get_cpuload_internal
(
-
1
,
&
s
,
CPU_LOAD_VM_ONLY
);
if
(
u
<
0
)
{
return
-
1
.
0
;
}
return
u
+
s
;
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
if
(
perfInit
()
==
0
)
{
return
get_cpu_load
(
-
1
);
}
else
{
return
-
1
.
0
;
}
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
if
(
perfInit
()
==
0
)
{
return
get_process_load
();
}
else
{
return
-
1
.
0
;
}
}
src/solaris/native/com/sun/management/SolarisOperatingSystem.c
0 → 100644
浏览文件 @
a775ffd6
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 <fcntl.h>
#include <kstat.h>
#include <procfs.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/sysinfo.h>
#include <sys/lwp.h>
#include <pthread.h>
#include <utmpx.h>
#include <dlfcn.h>
#include <sys/loadavg.h>
#include <jni.h>
#include "jvm.h"
#include "com_sun_management_UnixOperatingSystem.h"
typedef
struct
{
kstat_t
*
kstat
;
uint64_t
last_idle
;
uint64_t
last_total
;
double
last_ratio
;
}
cpuload_t
;
static
cpuload_t
*
cpu_loads
=
NULL
;
static
unsigned
int
num_cpus
;
static
kstat_ctl_t
*
kstat_ctrl
=
NULL
;
static
void
map_cpu_kstat_counters
()
{
kstat_t
*
kstat
;
int
i
;
// Get number of CPU(s)
if
((
num_cpus
=
sysconf
(
_SC_NPROCESSORS_ONLN
))
==
-
1
)
{
num_cpus
=
1
;
}
// Data structure for saving CPU load
if
((
cpu_loads
=
calloc
(
num_cpus
,
sizeof
(
cpuload_t
)))
==
NULL
)
{
return
;
}
// Get kstat cpu_stat counters for every CPU
// (loop over kstat to find our cpu_stat(s)
i
=
0
;
for
(
kstat
=
kstat_ctrl
->
kc_chain
;
kstat
!=
NULL
;
kstat
=
kstat
->
ks_next
)
{
if
(
strncmp
(
kstat
->
ks_module
,
"cpu_stat"
,
8
)
==
0
)
{
if
(
kstat_read
(
kstat_ctrl
,
kstat
,
NULL
)
==
-
1
)
{
// Failed to initialize kstat for this CPU so ignore it
continue
;
}
if
(
i
==
num_cpus
)
{
// Found more cpu_stats than reported CPUs
break
;
}
cpu_loads
[
i
++
].
kstat
=
kstat
;
}
}
}
static
int
init_cpu_kstat_counters
()
{
static
int
initialized
=
0
;
// Concurrence in this method is prevented by the lock in
// the calling method get_cpu_load();
if
(
!
initialized
)
{
if
((
kstat_ctrl
=
kstat_open
())
!=
NULL
)
{
map_cpu_kstat_counters
();
initialized
=
1
;
}
}
return
initialized
?
0
:
-
1
;
}
static
void
update_cpu_kstat_counters
()
{
if
(
kstat_chain_update
(
kstat_ctrl
)
!=
0
)
{
free
(
cpu_loads
);
map_cpu_kstat_counters
();
}
}
int
read_cpustat
(
cpuload_t
*
load
,
cpu_stat_t
*
cpu_stat
)
{
if
(
load
->
kstat
==
NULL
)
{
// no handle.
return
-
1
;
}
if
(
kstat_read
(
kstat_ctrl
,
load
->
kstat
,
cpu_stat
)
==
-
1
)
{
// disabling for now, a kstat chain update is likely to happen next time
load
->
kstat
=
NULL
;
return
-
1
;
}
return
0
;
}
double
get_single_cpu_load
(
unsigned
int
n
)
{
cpuload_t
*
load
;
cpu_stat_t
cpu_stat
;
uint_t
*
usage
;
uint64_t
c_idle
;
uint64_t
c_total
;
uint64_t
d_idle
;
uint64_t
d_total
;
int
i
;
if
(
n
>=
num_cpus
)
{
return
-
1
.
0
;
}
load
=
&
cpu_loads
[
n
];
if
(
read_cpustat
(
load
,
&
cpu_stat
)
<
0
)
{
return
-
1
.
0
;
}
usage
=
cpu_stat
.
cpu_sysinfo
.
cpu
;
c_idle
=
usage
[
CPU_IDLE
];
for
(
c_total
=
0
,
i
=
0
;
i
<
CPU_STATES
;
i
++
)
{
c_total
+=
usage
[
i
];
}
// Calculate diff against previous snapshot
d_idle
=
c_idle
-
load
->
last_idle
;
d_total
=
c_total
-
load
->
last_total
;
/** update if weve moved */
if
(
d_total
>
0
)
{
// Save current values for next time around
load
->
last_idle
=
c_idle
;
load
->
last_total
=
c_total
;
load
->
last_ratio
=
(
double
)
(
d_total
-
d_idle
)
/
d_total
;
}
return
load
->
last_ratio
;
}
int
get_info
(
const
char
*
path
,
void
*
info
,
size_t
s
,
off_t
o
)
{
int
fd
;
int
ret
=
0
;
if
((
fd
=
open
(
path
,
O_RDONLY
))
<
0
)
{
return
-
1
;
}
if
(
pread
(
fd
,
info
,
s
,
o
)
!=
s
)
{
ret
=
-
1
;
}
close
(
fd
);
return
ret
;
}
#define MIN(a, b) ((a < b) ? a : b)
static
pthread_mutex_t
lock
=
PTHREAD_MUTEX_INITIALIZER
;
/**
* Return the cpu load (0-1) for proc number 'which' (or average all if which == -1)
*/
double
get_cpu_load
(
int
which
)
{
double
load
=
.
0
;
pthread_mutex_lock
(
&
lock
);
if
(
init_cpu_kstat_counters
()
==
0
)
{
update_cpu_kstat_counters
();
if
(
which
==
-
1
)
{
unsigned
int
i
;
double
t
;
for
(
t
=
.
0
,
i
=
0
;
i
<
num_cpus
;
i
++
)
{
t
+=
get_single_cpu_load
(
i
);
}
// Cap total systemload to 1.0
load
=
MIN
((
t
/
num_cpus
),
1
.
0
);
}
else
{
load
=
MIN
(
get_single_cpu_load
(
which
),
1
.
0
);
}
}
else
{
load
=
-
1
.
0
;
}
pthread_mutex_unlock
(
&
lock
);
return
load
;
}
/**
* Return the cpu load (0-1) for the current process (i.e the JVM)
* or -1.0 if the get_info() call failed
*/
double
get_process_load
(
void
)
{
psinfo_t
info
;
// Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
// process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
if
(
get_info
(
"/proc/self/psinfo"
,
&
info
.
pr_pctcpu
,
sizeof
(
info
.
pr_pctcpu
),
offsetof
(
psinfo_t
,
pr_pctcpu
))
==
0
)
{
return
(
double
)
info
.
pr_pctcpu
/
0x8000
;
}
return
-
1
.
0
;
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_UnixOperatingSystem_getSystemCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
return
get_cpu_load
(
-
1
);
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
return
get_process_load
();
}
src/windows/classes/com/sun/management/OperatingSystem.java
浏览文件 @
a775ffd6
...
...
@@ -58,6 +58,8 @@ class OperatingSystem
public
native
long
getProcessCpuTime
();
public
native
long
getFreePhysicalMemorySize
();
public
native
long
getTotalPhysicalMemorySize
();
public
native
double
getSystemCpuLoad
();
public
native
double
getProcessCpuLoad
();
static
{
initialize
();
...
...
src/windows/native/com/sun/management/OperatingSystem_md.c
浏览文件 @
a775ffd6
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003,
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
...
...
@@ -34,9 +34,27 @@
#include <errno.h>
#include <stdlib.h>
#include <malloc.h>
#pragma warning (push,0)
#include <windows.h>
#pragma warning (pop)
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <assert.h>
/* Disable warnings due to broken header files from Microsoft... */
#pragma warning(push, 3)
#include <pdh.h>
#include <pdhmsg.h>
#include <process.h>
#pragma warning(pop)
typedef
unsigned
__int32
juint
;
typedef
unsigned
__int64
julong
;
typedef
enum
boolean_values
{
false
=
0
,
true
=
1
};
static
void
set_low
(
jlong
*
value
,
jint
low
)
{
*
value
&=
(
jlong
)
0xffffffff
<<
32
;
*
value
|=
(
jlong
)(
julong
)(
juint
)
low
;
...
...
@@ -56,11 +74,14 @@ static jlong jlong_from(jint h, jint l) {
static
HANDLE
main_process
;
int
perfiInit
(
void
);
JNIEXPORT
void
JNICALL
Java_com_sun_management_OperatingSystem_initialize
(
JNIEnv
*
env
,
jclass
cls
)
{
main_process
=
GetCurrentProcess
();
perfiInit
();
}
JNIEXPORT
jlong
JNICALL
...
...
@@ -132,3 +153,788 @@ Java_com_sun_management_OperatingSystem_getTotalPhysicalMemorySize
GlobalMemoryStatus
(
&
ms
);
return
ms
.
dwTotalPhys
;
}
// Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer.
// Let's just ignore it, since we make sure we have enough buffer anyway.
static
int
pdh_fail
(
PDH_STATUS
pdhStat
)
{
return
pdhStat
!=
ERROR_SUCCESS
&&
pdhStat
!=
PDH_MORE_DATA
;
}
// INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
// The index value for the base system counters and objects like processor,
// process, thread, memory, and so forth are always the same irrespective
// of the localized version of the operating system or service pack installed.
#define PDH_PROCESSOR_IDX ((DWORD) 238)
#define PDH_PROCESSOR_TIME_IDX ((DWORD) 6)
#define PDH_PRIV_PROCESSOR_TIME_IDX ((DWORD) 144)
#define PDH_PROCESS_IDX ((DWORD) 230)
#define PDH_ID_PROCESS_IDX ((DWORD) 784)
#define PDH_CONTEXT_SWITCH_RATE_IDX ((DWORD) 146)
#define PDH_SYSTEM_IDX ((DWORD) 2)
#define PDH_VIRTUAL_BYTES_IDX ((DWORD) 174)
typedef
PDH_STATUS
(
WINAPI
*
PdhAddCounterFunc
)(
HQUERY
hQuery
,
LPCSTR
szFullCounterPath
,
DWORD
dwUserData
,
HCOUNTER
*
phCounter
);
typedef
PDH_STATUS
(
WINAPI
*
PdhOpenQueryFunc
)(
LPCWSTR
szDataSource
,
DWORD
dwUserData
,
HQUERY
*
phQuery
);
typedef
DWORD
(
WINAPI
*
PdhCloseQueryFunc
)(
HQUERY
hQuery
);
typedef
PDH_STATUS
(
WINAPI
*
PdhCollectQueryDataFunc
)(
HQUERY
hQuery
);
typedef
DWORD
(
WINAPI
*
PdhGetFormattedCounterValueFunc
)(
HCOUNTER
hCounter
,
DWORD
dwFormat
,
LPDWORD
lpdwType
,
PPDH_FMT_COUNTERVALUE
pValue
);
typedef
PDH_STATUS
(
WINAPI
*
PdhEnumObjectItemsFunc
)(
LPCTSTR
szDataSource
,
LPCTSTR
szMachineName
,
LPCTSTR
szObjectName
,
LPTSTR
mszCounterList
,
LPDWORD
pcchCounterListLength
,
LPTSTR
mszInstanceList
,
LPDWORD
pcchInstanceListLength
,
DWORD
dwDetailLevel
,
DWORD
dwFlags
);
typedef
PDH_STATUS
(
WINAPI
*
PdhRemoveCounterFunc
)(
HCOUNTER
hCounter
);
typedef
PDH_STATUS
(
WINAPI
*
PdhLookupPerfNameByIndexFunc
)(
LPCSTR
szMachineName
,
DWORD
dwNameIndex
,
LPSTR
szNameBuffer
,
LPDWORD
pcchNameBufferSize
);
typedef
PDH_STATUS
(
WINAPI
*
PdhMakeCounterPathFunc
)(
PDH_COUNTER_PATH_ELEMENTS
*
pCounterPathElements
,
LPTSTR
szFullPathBuffer
,
LPDWORD
pcchBufferSize
,
DWORD
dwFlags
);
static
PdhAddCounterFunc
PdhAddCounter_i
;
static
PdhOpenQueryFunc
PdhOpenQuery_i
;
static
PdhCloseQueryFunc
PdhCloseQuery_i
;
static
PdhCollectQueryDataFunc
PdhCollectQueryData_i
;
static
PdhGetFormattedCounterValueFunc
PdhGetFormattedCounterValue_i
;
static
PdhEnumObjectItemsFunc
PdhEnumObjectItems_i
;
static
PdhRemoveCounterFunc
PdhRemoveCounter_i
;
static
PdhLookupPerfNameByIndexFunc
PdhLookupPerfNameByIndex_i
;
static
PdhMakeCounterPathFunc
PdhMakeCounterPath_i
;
static
HANDLE
thisProcess
;
static
double
cpuFactor
;
static
DWORD
num_cpus
;
#define FT2JLONG(X) ((((jlong)X.dwHighDateTime) << 32) | ((jlong)X.dwLowDateTime))
#define COUNTER_BUF_SIZE 256
// Min time between query updates.
#define MIN_UPDATE_INTERVAL 500
#define CONFIG_SUCCESSFUL 0
/**
* Struct for PDH queries.
*/
typedef
struct
{
HQUERY
query
;
uint64_t
lastUpdate
;
// Last time query was updated (current millis).
}
UpdateQueryS
,
*
UpdateQueryP
;
/**
* Struct for the processor load counters.
*/
typedef
struct
{
UpdateQueryS
query
;
HCOUNTER
*
counters
;
int
noOfCounters
;
}
MultipleCounterQueryS
,
*
MultipleCounterQueryP
;
/**
* Struct for the jvm process load counter.
*/
typedef
struct
{
UpdateQueryS
query
;
HCOUNTER
counter
;
}
SingleCounterQueryS
,
*
SingleCounterQueryP
;
static
char
*
getProcessPDHHeader
(
void
);
/**
* Currently available counters.
*/
static
SingleCounterQueryS
cntCtxtSwitchRate
;
static
SingleCounterQueryS
cntVirtualSize
;
static
SingleCounterQueryS
cntProcLoad
;
static
SingleCounterQueryS
cntProcSystemLoad
;
static
MultipleCounterQueryS
multiCounterCPULoad
;
static
CRITICAL_SECTION
processHeaderLock
;
static
CRITICAL_SECTION
initializationLock
;
/**
* Initialize the perf module at startup.
*/
int
perfiInit
(
void
)
{
InitializeCriticalSection
(
&
processHeaderLock
);
InitializeCriticalSection
(
&
initializationLock
);
return
0
;
}
/**
* Dynamically sets up function pointers to the PDH library.
*
* @return CONFIG_SUCCESSFUL on success, negative on failure.
*/
static
int
get_functions
(
HMODULE
h
,
char
*
ebuf
,
size_t
elen
)
{
// The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
PdhAddCounter_i
=
(
PdhAddCounterFunc
)
GetProcAddress
(
h
,
"PdhAddCounterA"
);
PdhOpenQuery_i
=
(
PdhOpenQueryFunc
)
GetProcAddress
(
h
,
"PdhOpenQueryA"
);
PdhCloseQuery_i
=
(
PdhCloseQueryFunc
)
GetProcAddress
(
h
,
"PdhCloseQuery"
);
PdhCollectQueryData_i
=
(
PdhCollectQueryDataFunc
)
GetProcAddress
(
h
,
"PdhCollectQueryData"
);
PdhGetFormattedCounterValue_i
=
(
PdhGetFormattedCounterValueFunc
)
GetProcAddress
(
h
,
"PdhGetFormattedCounterValue"
);
PdhEnumObjectItems_i
=
(
PdhEnumObjectItemsFunc
)
GetProcAddress
(
h
,
"PdhEnumObjectItemsA"
);
PdhRemoveCounter_i
=
(
PdhRemoveCounterFunc
)
GetProcAddress
(
h
,
"PdhRemoveCounter"
);
PdhLookupPerfNameByIndex_i
=
(
PdhLookupPerfNameByIndexFunc
)
GetProcAddress
(
h
,
"PdhLookupPerfNameByIndexA"
);
PdhMakeCounterPath_i
=
(
PdhMakeCounterPathFunc
)
GetProcAddress
(
h
,
"PdhMakeCounterPathA"
);
if
(
PdhAddCounter_i
==
NULL
||
PdhOpenQuery_i
==
NULL
||
PdhCloseQuery_i
==
NULL
||
PdhCollectQueryData_i
==
NULL
||
PdhGetFormattedCounterValue_i
==
NULL
||
PdhEnumObjectItems_i
==
NULL
||
PdhRemoveCounter_i
==
NULL
||
PdhLookupPerfNameByIndex_i
==
NULL
||
PdhMakeCounterPath_i
==
NULL
)
{
_snprintf
(
ebuf
,
elen
,
"Required method could not be found."
);
return
-
1
;
}
return
CONFIG_SUCCESSFUL
;
}
/**
* Returns the counter value as a double for the specified query.
* Will collect the query data and update the counter values as necessary.
*
* @param query the query to update (if needed).
* @param c the counter to read.
* @param value where to store the formatted value.
* @param format the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc)
* @return CONFIG_SUCCESSFUL if no error
* -1 if PdhCollectQueryData fails
* -2 if PdhGetFormattedCounterValue fails
*/
static
int
getPerformanceData
(
UpdateQueryP
query
,
HCOUNTER
c
,
PDH_FMT_COUNTERVALUE
*
value
,
DWORD
format
)
{
clock_t
now
;
now
=
clock
();
// Need to limit how often we update the query
// to mimise the heisenberg effect.
// (PDH behaves erratically if the counters are
// queried too often, especially counters that
// store and use values from two consecutive updates,
// like cpu load.)
if
(
now
-
query
->
lastUpdate
>
MIN_UPDATE_INTERVAL
)
{
if
(
PdhCollectQueryData_i
(
query
->
query
)
!=
ERROR_SUCCESS
)
{
return
-
1
;
}
query
->
lastUpdate
=
now
;
}
if
(
PdhGetFormattedCounterValue_i
(
c
,
format
,
NULL
,
value
)
!=
ERROR_SUCCESS
)
{
return
-
2
;
}
return
CONFIG_SUCCESSFUL
;
}
/**
* Places the resolved counter name of the counter at the specified index in the
* supplied buffer. There must be enough space in the buffer to hold the counter name.
*
* @param index the counter index as specified in the registry.
* @param buf the buffer in which to place the counter name.
* @param size the size of the counter name buffer.
* @param ebuf the error message buffer.
* @param elen the length of the error buffer.
* @return CONFIG_SUCCESSFUL if successful, negative on failure.
*/
static
int
find_name
(
DWORD
index
,
char
*
buf
,
DWORD
size
)
{
PDH_STATUS
res
;
if
((
res
=
PdhLookupPerfNameByIndex_i
(
NULL
,
index
,
buf
,
&
size
))
!=
ERROR_SUCCESS
)
{
/* printf("Could not open counter %d: error=0x%08x", index, res); */
/* if (res == PDH_CSTATUS_NO_MACHINE) { */
/* printf("User probably does not have sufficient privileges to use"); */
/* printf("performance counters. If you are running on Windows 2003"); */
/* printf("or Windows Vista, make sure the user is in the"); */
/* printf("Performance Logs user group."); */
/* } */
return
-
1
;
}
if
(
size
==
0
)
{
/* printf("Failed to get counter name for %d: empty string", index); */
return
-
1
;
}
// windows vista does not null-terminate the string (allthough the docs says it will)
buf
[
size
-
1
]
=
'\0'
;
return
CONFIG_SUCCESSFUL
;
}
/**
* Sets up the supplied SingleCounterQuery to listen for the specified counter.
* initPDH() must have been run prior to calling this function!
*
* @param counterQuery the counter query to set up.
* @param counterString the string specifying the path to the counter.
* @param ebuf the error buffer.
* @param elen the length of the error buffer.
* @returns CONFIG_SUCCESSFUL if successful, negative on failure.
*/
static
int
initSingleCounterQuery
(
SingleCounterQueryP
counterQuery
,
char
*
counterString
)
{
if
(
PdhOpenQuery_i
(
NULL
,
0
,
&
counterQuery
->
query
.
query
)
!=
ERROR_SUCCESS
)
{
/* printf("Could not open query for %s", counterString); */
return
-
1
;
}
if
(
PdhAddCounter_i
(
counterQuery
->
query
.
query
,
counterString
,
0
,
&
counterQuery
->
counter
)
!=
ERROR_SUCCESS
)
{
/* printf("Could not add counter %s for query", counterString); */
if
(
counterQuery
->
counter
!=
NULL
)
{
PdhRemoveCounter_i
(
counterQuery
->
counter
);
}
if
(
counterQuery
->
query
.
query
!=
NULL
)
{
PdhCloseQuery_i
(
counterQuery
->
query
.
query
);
}
memset
(
counterQuery
,
0
,
sizeof
(
SingleCounterQueryS
));
return
-
1
;
}
return
CONFIG_SUCCESSFUL
;
}
/**
* Sets up the supplied SingleCounterQuery to listen for the time spent
* by the HotSpot process.
*
* @param counterQuery the counter query to set up as a process counter.
* @param ebuf the error buffer.
* @param elen the length of the error buffer.
* @returns CONFIG_SUCCESSFUL if successful, negative on failure.
*/
static
int
initProcLoadCounter
(
void
)
{
char
time
[
COUNTER_BUF_SIZE
];
char
counter
[
COUNTER_BUF_SIZE
*
2
];
if
(
find_name
(
PDH_PROCESSOR_TIME_IDX
,
time
,
sizeof
(
time
)
-
1
)
<
0
)
{
return
-
1
;
}
_snprintf
(
counter
,
sizeof
(
counter
)
-
1
,
"%s
\\
%s"
,
getProcessPDHHeader
(),
time
);
return
initSingleCounterQuery
(
&
cntProcLoad
,
counter
);
}
static
int
initProcSystemLoadCounter
(
void
)
{
char
time
[
COUNTER_BUF_SIZE
];
char
counter
[
COUNTER_BUF_SIZE
*
2
];
if
(
find_name
(
PDH_PRIV_PROCESSOR_TIME_IDX
,
time
,
sizeof
(
time
)
-
1
)
<
0
)
{
return
-
1
;
}
_snprintf
(
counter
,
sizeof
(
counter
)
-
1
,
"%s
\\
%s"
,
getProcessPDHHeader
(),
time
);
return
initSingleCounterQuery
(
&
cntProcSystemLoad
,
counter
);
}
/**
* Sets up the supplied MultipleCounterQuery to check on the processors.
* (Comment: Refactor and prettify as with the the SingleCounter queries
* if more MultipleCounterQueries are discovered.)
*
* initPDH() must have been run prior to calling this function.
*
* @param multiQuery a pointer to a MultipleCounterQueryS, will be filled in with
* the necessary info to check the PDH processor counters.
* @return CONFIG_SUCCESSFUL if successful, negative on failure.
*/
static
int
initProcessorCounters
(
void
)
{
char
processor
[
COUNTER_BUF_SIZE
];
//'Processor' == #238
char
time
[
COUNTER_BUF_SIZE
];
//'Time' == 6
DWORD
c_size
,
i_size
;
HQUERY
tmpQuery
;
DWORD
i
,
p_count
;
BOOL
error
;
char
*
instances
,
*
tmp
;
PDH_STATUS
pdhStat
;
c_size
=
i_size
=
0
;
tmpQuery
=
NULL
;
error
=
false
;
// This __try / __except stuff is there since Windows 2000 beta (or so) sometimes triggered
// an access violation when the user had insufficient privileges to use the performance
// counters. This was previously guarded by a very ugly piece of code which disabled the
// global trap handling in JRockit. Don't know if this really is needed anymore, but otoh,
// if we keep it we don't crash on Win2k beta. /Ihse, 2005-05-30
__try
{
if
(
find_name
(
PDH_PROCESSOR_IDX
,
processor
,
sizeof
(
processor
)
-
1
)
<
0
)
{
return
-
1
;
}
}
__except
(
EXCEPTION_EXECUTE_HANDLER
)
{
// We'll catch all exceptions here.
/* printf("User does not have sufficient privileges to use performance counters"); */
return
-
1
;
}
if
(
find_name
(
PDH_PROCESSOR_TIME_IDX
,
time
,
sizeof
(
time
)
-
1
)
<
0
)
{
return
-
1
;
}
//ok, now we have enough to enumerate all processors.
pdhStat
=
PdhEnumObjectItems_i
(
NULL
,
// reserved
NULL
,
// local machine
processor
,
// object to enumerate
NULL
,
// pass in NULL buffers
&
c_size
,
// and 0 length to get
NULL
,
// required size
&
i_size
,
// of the buffers in chars
PERF_DETAIL_WIZARD
,
// counter detail level
0
);
if
(
pdh_fail
(
pdhStat
))
{
/* printf("could not enumerate processors (1) error=%d", pdhStat); */
return
-
1
;
}
// use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
instances
=
calloc
(
i_size
,
1
);
if
(
instances
==
NULL
)
{
/* printf("could not allocate memory (1) %d bytes", i_size); */
error
=
true
;
goto
end
;
}
c_size
=
0
;
pdhStat
=
PdhEnumObjectItems_i
(
NULL
,
// reserved
NULL
,
// local machine
processor
,
// object to enumerate
NULL
,
// pass in NULL buffers
&
c_size
,
// and 0 length to get
instances
,
// required size
&
i_size
,
// of the buffers in chars
PERF_DETAIL_WIZARD
,
// counter detail level
0
);
if
(
pdh_fail
(
pdhStat
))
{
/* printf("could not enumerate processors (2) error=%d", pdhStat); */
error
=
true
;
goto
end
;
}
//count perf count instances.
for
(
p_count
=
0
,
tmp
=
instances
;
*
tmp
!=
0
;
tmp
=
&
tmp
[
lstrlen
(
tmp
)
+
1
],
p_count
++
);
//is this correct for HT?
assert
(
p_count
==
num_cpus
+
1
);
//ok, have number of perf counters.
multiCounterCPULoad
.
counters
=
calloc
(
p_count
,
sizeof
(
HCOUNTER
));
if
(
multiCounterCPULoad
.
counters
==
NULL
)
{
/* printf("could not allocate memory (2) count=%d", p_count); */
error
=
true
;
goto
end
;
}
multiCounterCPULoad
.
noOfCounters
=
p_count
;
if
(
PdhOpenQuery_i
(
NULL
,
0
,
&
multiCounterCPULoad
.
query
.
query
)
!=
ERROR_SUCCESS
)
{
/* printf("could not create query"); */
error
=
true
;
goto
end
;
}
//now, fetch the counters.
for
(
i
=
0
,
tmp
=
instances
;
*
tmp
!=
'\0'
;
tmp
=
&
tmp
[
lstrlen
(
tmp
)
+
1
],
i
++
)
{
char
counter
[
2
*
COUNTER_BUF_SIZE
];
_snprintf
(
counter
,
sizeof
(
counter
)
-
1
,
"
\\
%s(%s)
\\
%s"
,
processor
,
tmp
,
time
);
if
(
PdhAddCounter_i
(
multiCounterCPULoad
.
query
.
query
,
counter
,
0
,
&
multiCounterCPULoad
.
counters
[
i
])
!=
ERROR_SUCCESS
)
{
/* printf("error adding processor counter %s", counter); */
error
=
true
;
goto
end
;
}
}
free
(
instances
);
instances
=
NULL
;
// Query once to initialize the counters needing at least two queries
// (like the % CPU usage) to calculate correctly.
if
(
PdhCollectQueryData_i
(
multiCounterCPULoad
.
query
.
query
)
!=
ERROR_SUCCESS
)
error
=
true
;
end:
if
(
instances
!=
NULL
)
{
free
(
instances
);
}
if
(
tmpQuery
!=
NULL
)
{
PdhCloseQuery_i
(
tmpQuery
);
}
if
(
error
)
{
int
i
;
if
(
multiCounterCPULoad
.
counters
!=
NULL
)
{
for
(
i
=
0
;
i
<
multiCounterCPULoad
.
noOfCounters
;
i
++
)
{
if
(
multiCounterCPULoad
.
counters
[
i
]
!=
NULL
)
{
PdhRemoveCounter_i
(
multiCounterCPULoad
.
counters
[
i
]);
}
}
free
(
multiCounterCPULoad
.
counters
[
i
]);
}
if
(
multiCounterCPULoad
.
query
.
query
!=
NULL
)
{
PdhCloseQuery_i
(
multiCounterCPULoad
.
query
.
query
);
}
memset
(
&
multiCounterCPULoad
,
0
,
sizeof
(
MultipleCounterQueryS
));
return
-
1
;
}
return
CONFIG_SUCCESSFUL
;
}
/**
* Help function that initializes the PDH process header for the JRockit process.
* (You should probably use getProcessPDHHeader() instead!)
*
* initPDH() must have been run prior to calling this function.
*
* @param ebuf the error buffer.
* @param elen the length of the error buffer.
*
* @return the PDH instance description corresponding to the JVM process.
*/
static
char
*
initProcessPDHHeader
(
void
)
{
static
char
hotspotheader
[
2
*
COUNTER_BUF_SIZE
];
char
counter
[
2
*
COUNTER_BUF_SIZE
];
char
processes
[
COUNTER_BUF_SIZE
];
//'Process' == #230
char
pid
[
COUNTER_BUF_SIZE
];
//'ID Process' == 784
char
module_name
[
MAX_PATH
];
PDH_STATUS
pdhStat
;
DWORD
c_size
=
0
,
i_size
=
0
;
HQUERY
tmpQuery
=
NULL
;
int
i
,
myPid
=
_getpid
();
BOOL
error
=
false
;
char
*
instances
,
*
tmp
,
*
instance_name
,
*
dot_pos
;
tmpQuery
=
NULL
;
myPid
=
_getpid
();
error
=
false
;
if
(
find_name
(
PDH_PROCESS_IDX
,
processes
,
sizeof
(
processes
)
-
1
)
<
0
)
{
return
NULL
;
}
if
(
find_name
(
PDH_ID_PROCESS_IDX
,
pid
,
sizeof
(
pid
)
-
1
)
<
0
)
{
return
NULL
;
}
//time is same.
c_size
=
0
;
i_size
=
0
;
pdhStat
=
PdhEnumObjectItems_i
(
NULL
,
// reserved
NULL
,
// local machine
processes
,
// object to enumerate
NULL
,
// pass in NULL buffers
&
c_size
,
// and 0 length to get
NULL
,
// required size
&
i_size
,
// of the buffers in chars
PERF_DETAIL_WIZARD
,
// counter detail level
0
);
//ok, now we have enough to enumerate all processes
if
(
pdh_fail
(
pdhStat
))
{
/* printf("Could not enumerate processes (1) error=%d", pdhStat); */
return
NULL
;
}
// use calloc because windows vista does not null terminate the instance names (allthough the docs says it will)
if
((
instances
=
calloc
(
i_size
,
1
))
==
NULL
)
{
/* printf("Could not allocate memory %d bytes", i_size); */
error
=
true
;
goto
end
;
}
c_size
=
0
;
pdhStat
=
PdhEnumObjectItems_i
(
NULL
,
// reserved
NULL
,
// local machine
processes
,
// object to enumerate
NULL
,
// pass in NULL buffers
&
c_size
,
// and 0 length to get
instances
,
// required size
&
i_size
,
// of the buffers in chars
PERF_DETAIL_WIZARD
,
// counter detail level
0
);
// ok, now we have enough to enumerate all processes
if
(
pdh_fail
(
pdhStat
))
{
/* printf("Could not enumerate processes (2) error=%d", pdhStat); */
error
=
true
;
goto
end
;
}
if
(
PdhOpenQuery_i
(
NULL
,
0
,
&
tmpQuery
)
!=
ERROR_SUCCESS
)
{
/* printf("Could not create temporary query"); */
error
=
true
;
goto
end
;
}
// Find our module name and use it to extract the instance name used by PDH
if
(
GetModuleFileName
(
NULL
,
module_name
,
MAX_PATH
)
>=
MAX_PATH
-
1
)
{
/* printf("Module name truncated"); */
error
=
true
;
goto
end
;
}
instance_name
=
strrchr
(
module_name
,
'\\'
);
//drop path
instance_name
++
;
//skip slash
dot_pos
=
strchr
(
instance_name
,
'.'
);
//drop .exe
dot_pos
[
0
]
=
'\0'
;
//now, fetch the counters.
for
(
tmp
=
instances
;
*
tmp
!=
0
&&
!
error
;
tmp
=
&
tmp
[
lstrlen
(
tmp
)
+
1
])
{
HCOUNTER
hc
=
NULL
;
BOOL
done
=
false
;
// Skip until we find our own process name
if
(
strcmp
(
tmp
,
instance_name
)
!=
0
)
{
continue
;
}
// iterate over all instance indexes and try to find our own pid
for
(
i
=
0
;
!
done
&&
!
error
;
i
++
){
PDH_STATUS
res
;
_snprintf
(
counter
,
sizeof
(
counter
)
-
1
,
"
\\
%s(%s#%d)
\\
%s"
,
processes
,
tmp
,
i
,
pid
);
if
(
PdhAddCounter_i
(
tmpQuery
,
counter
,
0
,
&
hc
)
!=
ERROR_SUCCESS
)
{
/* printf("Failed to create process id query"); */
error
=
true
;
goto
end
;
}
res
=
PdhCollectQueryData_i
(
tmpQuery
);
if
(
res
==
PDH_INVALID_HANDLE
)
{
/* printf("Failed to query process id"); */
res
=
-
1
;
done
=
true
;
}
else
if
(
res
==
PDH_NO_DATA
)
{
done
=
true
;
}
else
{
PDH_FMT_COUNTERVALUE
cv
;
PdhGetFormattedCounterValue_i
(
hc
,
PDH_FMT_LONG
,
NULL
,
&
cv
);
/*
* This check seems to be needed for Win2k SMP boxes, since
* they for some reason don't return PDH_NO_DATA for non existing
* counters.
*/
if
(
cv
.
CStatus
!=
PDH_CSTATUS_VALID_DATA
)
{
done
=
true
;
}
else
if
(
cv
.
longValue
==
myPid
)
{
_snprintf
(
hotspotheader
,
sizeof
(
hotspotheader
)
-
1
,
"
\\
%s(%s#%d)
\0
"
,
processes
,
tmp
,
i
);
PdhRemoveCounter_i
(
hc
);
goto
end
;
}
}
PdhRemoveCounter_i
(
hc
);
}
}
end:
if
(
instances
!=
NULL
)
{
free
(
instances
);
}
if
(
tmpQuery
!=
NULL
)
{
PdhCloseQuery_i
(
tmpQuery
);
}
if
(
error
)
{
return
NULL
;
}
return
hotspotheader
;
}
/**
* Returns the PDH string prefix identifying the HotSpot process. Use this prefix when getting
* counters from the PDH process object representing HotSpot.
*
* Note: this call may take some time to complete.
*
* @param ebuf error buffer.
* @param elen error buffer length.
*
* @return the header to be used when retrieving PDH counters from the HotSpot process.
* Will return NULL if the call failed.
*/
static
char
*
getProcessPDHHeader
(
void
)
{
static
char
*
processHeader
=
NULL
;
EnterCriticalSection
(
&
processHeaderLock
);
{
if
(
processHeader
==
NULL
)
{
processHeader
=
initProcessPDHHeader
();
}
}
LeaveCriticalSection
(
&
processHeaderLock
);
return
processHeader
;
}
int
perfInit
(
void
);
double
perfGetCPULoad
(
int
which
)
{
PDH_FMT_COUNTERVALUE
cv
;
HCOUNTER
c
;
if
(
perfInit
()
<
0
)
{
// warn?
return
-
1
.
0
;
}
if
(
multiCounterCPULoad
.
query
.
query
==
NULL
)
{
// warn?
return
-
1
.
0
;
}
if
(
which
==
-
1
)
{
c
=
multiCounterCPULoad
.
counters
[
multiCounterCPULoad
.
noOfCounters
-
1
];
}
else
{
if
(
which
<
multiCounterCPULoad
.
noOfCounters
)
{
c
=
multiCounterCPULoad
.
counters
[
which
];
}
else
{
return
-
1
.
0
;
}
}
if
(
getPerformanceData
(
&
multiCounterCPULoad
.
query
,
c
,
&
cv
,
PDH_FMT_DOUBLE
)
==
CONFIG_SUCCESSFUL
)
{
return
cv
.
doubleValue
/
100
;
}
return
-
1
.
0
;
}
double
perfGetProcessLoad
(
void
)
{
PDH_FMT_COUNTERVALUE
cv
;
if
(
perfInit
()
<
0
)
{
// warn?
return
-
1
.
0
;
}
if
(
cntProcLoad
.
query
.
query
==
NULL
)
{
// warn?
return
-
1
.
0
;
}
if
(
getPerformanceData
(
&
cntProcLoad
.
query
,
cntProcLoad
.
counter
,
&
cv
,
PDH_FMT_DOUBLE
|
PDH_FMT_NOCAP100
)
==
CONFIG_SUCCESSFUL
)
{
double
d
=
cv
.
doubleValue
/
cpuFactor
;
d
=
min
(
1
,
d
);
d
=
max
(
0
,
d
);
return
d
;
}
return
-
1
.
0
;
}
/**
* Helper to initialize the PDH library. Loads the library and sets up the functions.
* Note that once loaded, we will never unload the PDH library.
*
* @return CONFIG_SUCCESSFUL if successful, negative on failure.
*/
int
perfInit
(
void
)
{
static
HMODULE
h
;
static
BOOL
running
,
inited
;
int
error
;
if
(
running
)
{
return
CONFIG_SUCCESSFUL
;
}
error
=
CONFIG_SUCCESSFUL
;
// this is double checked locking again, but we try to bypass the worst by
// implicit membar at end of lock.
EnterCriticalSection
(
&
initializationLock
);
{
if
(
!
inited
)
{
char
buf
[
64
]
=
""
;
SYSTEM_INFO
si
;
// CMH. But windows will not care about our affinity when giving
// us measurements. Need the real, raw num cpus.
GetSystemInfo
(
&
si
);
num_cpus
=
si
.
dwNumberOfProcessors
;
// Initialize the denominator for the jvm load calculations
cpuFactor
=
num_cpus
*
100
;
/**
* Do this dynamically, so we don't fail to start on systems without pdh.
*/
if
((
h
=
LoadLibrary
(
"pdh.dll"
))
==
NULL
)
{
/* printf("Could not load pdh.dll (%d)", GetLastError()); */
error
=
-
2
;
}
else
if
(
get_functions
(
h
,
buf
,
sizeof
(
buf
))
<
0
)
{
FreeLibrary
(
h
);
h
=
NULL
;
error
=
-
2
;
/* printf("Failed to init pdh functions: %s.\n", buf); */
}
else
{
if
(
initProcessorCounters
()
!=
0
)
{
/* printf("Failed to init system load counters.\n"); */
}
else
if
(
initProcLoadCounter
()
!=
0
)
{
/* printf("Failed to init process load counter.\n"); */
}
else
if
(
initProcSystemLoadCounter
()
!=
0
)
{
/* printf("Failed to init process system load counter.\n"); */
}
else
{
inited
=
true
;
}
}
}
}
LeaveCriticalSection
(
&
initializationLock
);
if
(
inited
&&
error
==
CONFIG_SUCCESSFUL
)
{
running
=
true
;
}
return
error
;
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_OperatingSystem_getSystemCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
return
perfGetCPULoad
(
-
1
);
}
JNIEXPORT
jdouble
JNICALL
Java_com_sun_management_OperatingSystem_getProcessCpuLoad
(
JNIEnv
*
env
,
jobject
dummy
)
{
return
perfGetProcessLoad
();
}
test/com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java
0 → 100644
浏览文件 @
a775ffd6
/*
* 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.
*/
/*
* @test
* @bug 7028071
* @summary Basic unit test of OperatingSystemMXBean.getProcessCpuLoad()
*
* @run main GetProcessCpuLoad
*/
import
java.lang.management.*
;
import
com.sun.management.OperatingSystemMXBean
;
public
class
GetProcessCpuLoad
{
public
static
void
main
(
String
[]
argv
)
throws
Exception
{
OperatingSystemMXBean
mbean
=
(
com
.
sun
.
management
.
OperatingSystemMXBean
)
ManagementFactory
.
getOperatingSystemMXBean
();
double
load
;
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
load
=
mbean
.
getProcessCpuLoad
();
if
((
load
<
0.0
||
load
>
1.0
)
&&
load
!=
-
1.0
)
{
throw
new
RuntimeException
(
"getProcessCpuLoad() returns "
+
load
+
" which is not in the [0.0,1.0] interval"
);
}
try
{
Thread
.
sleep
(
200
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
}
}
test/com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java
0 → 100644
浏览文件 @
a775ffd6
/*
* 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.
*/
/*
* @test
* @bug 7028071
* @summary Basic unit test of OperatingSystemMXBean.getProcessCpuLoad()
*
* @run main GetSystemCpuLoad
*/
import
java.lang.management.*
;
import
com.sun.management.OperatingSystemMXBean
;
public
class
GetSystemCpuLoad
{
public
static
void
main
(
String
[]
argv
)
throws
Exception
{
OperatingSystemMXBean
mbean
=
(
com
.
sun
.
management
.
OperatingSystemMXBean
)
ManagementFactory
.
getOperatingSystemMXBean
();
double
load
;
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
load
=
mbean
.
getSystemCpuLoad
();
if
((
load
<
0.0
||
load
>
1.0
)
&&
load
!=
-
1.0
)
{
throw
new
RuntimeException
(
"getSystemCpuLoad() returns "
+
load
+
" which is not in the [0.0,1.0] interval"
);
}
try
{
Thread
.
sleep
(
200
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录