Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
a311994c
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
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看板
提交
a311994c
编写于
7月 25, 2008
作者:
X
xdono
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
ae759928
7610a76d
变更
66
隐藏空白更改
内联
并排
Showing
66 changed file
with
6322 addition
and
796 deletion
+6322
-796
.hgtags
.hgtags
+1
-0
src/share/back/eventFilter.c
src/share/back/eventFilter.c
+9
-6
src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
...om/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
+357
-162
src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
.../com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
+2
-2
src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java
src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java
+2
-12
src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
+178
-51
src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
+22
-7
src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java
src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java
+291
-0
src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java
...re/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java
+154
-7
src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java
src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java
+5
-1
src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
...e/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
+24
-8
src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java
src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java
+2
-2
src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java
src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java
+186
-0
src/share/classes/com/sun/jmx/mbeanserver/Repository.java
src/share/classes/com/sun/jmx/mbeanserver/Repository.java
+124
-37
src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java
...es/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java
+22
-11
src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java
...classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java
+21
-22
src/share/classes/com/sun/jmx/mbeanserver/Util.java
src/share/classes/com/sun/jmx/mbeanserver/Util.java
+5
-0
src/share/classes/com/sun/tools/jdi/EventSetImpl.java
src/share/classes/com/sun/tools/jdi/EventSetImpl.java
+3
-2
src/share/classes/com/sun/tools/jdi/MonitorInfoImpl.java
src/share/classes/com/sun/tools/jdi/MonitorInfoImpl.java
+2
-1
src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
+130
-125
src/share/classes/com/sun/tools/jdi/VMAction.java
src/share/classes/com/sun/tools/jdi/VMAction.java
+12
-0
src/share/classes/com/sun/tools/jdi/VMState.java
src/share/classes/com/sun/tools/jdi/VMState.java
+11
-2
src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
+2
-1
src/share/classes/java/nio/channels/SelectionKey.java
src/share/classes/java/nio/channels/SelectionKey.java
+1
-1
src/share/classes/javax/management/BinaryRelQueryExp.java
src/share/classes/javax/management/BinaryRelQueryExp.java
+1
-0
src/share/classes/javax/management/Description.java
src/share/classes/javax/management/Description.java
+180
-0
src/share/classes/javax/management/Descriptor.java
src/share/classes/javax/management/Descriptor.java
+15
-8
src/share/classes/javax/management/DescriptorFields.java
src/share/classes/javax/management/DescriptorFields.java
+137
-0
src/share/classes/javax/management/DescriptorKey.java
src/share/classes/javax/management/DescriptorKey.java
+45
-7
src/share/classes/javax/management/DynamicWrapperMBean.java
src/share/classes/javax/management/DynamicWrapperMBean.java
+62
-0
src/share/classes/javax/management/Impact.java
src/share/classes/javax/management/Impact.java
+105
-0
src/share/classes/javax/management/JMX.java
src/share/classes/javax/management/JMX.java
+26
-0
src/share/classes/javax/management/MBean.java
src/share/classes/javax/management/MBean.java
+68
-0
src/share/classes/javax/management/MBeanOperationInfo.java
src/share/classes/javax/management/MBeanOperationInfo.java
+26
-14
src/share/classes/javax/management/MBeanRegistration.java
src/share/classes/javax/management/MBeanRegistration.java
+98
-6
src/share/classes/javax/management/MBeanServer.java
src/share/classes/javax/management/MBeanServer.java
+7
-4
src/share/classes/javax/management/MBeanServerConnection.java
...share/classes/javax/management/MBeanServerConnection.java
+6
-0
src/share/classes/javax/management/MXBean.java
src/share/classes/javax/management/MXBean.java
+27
-4
src/share/classes/javax/management/ManagedAttribute.java
src/share/classes/javax/management/ManagedAttribute.java
+64
-0
src/share/classes/javax/management/ManagedOperation.java
src/share/classes/javax/management/ManagedOperation.java
+67
-0
src/share/classes/javax/management/NotQueryExp.java
src/share/classes/javax/management/NotQueryExp.java
+1
-0
src/share/classes/javax/management/NotificationBroadcasterSupport.java
...sses/javax/management/NotificationBroadcasterSupport.java
+2
-1
src/share/classes/javax/management/NotificationInfo.java
src/share/classes/javax/management/NotificationInfo.java
+117
-0
src/share/classes/javax/management/NotificationInfos.java
src/share/classes/javax/management/NotificationInfos.java
+72
-0
src/share/classes/javax/management/SendNotification.java
src/share/classes/javax/management/SendNotification.java
+38
-0
src/share/classes/javax/management/StandardEmitterMBean.java
src/share/classes/javax/management/StandardEmitterMBean.java
+157
-41
src/share/classes/javax/management/StandardMBean.java
src/share/classes/javax/management/StandardMBean.java
+139
-6
src/share/classes/javax/management/modelmbean/RequiredModelMBean.java
...asses/javax/management/modelmbean/RequiredModelMBean.java
+61
-7
src/share/classes/javax/management/monitor/package.html
src/share/classes/javax/management/monitor/package.html
+11
-8
src/share/classes/javax/management/package.html
src/share/classes/javax/management/package.html
+282
-191
src/share/classes/sun/nio/ch/SelectorImpl.java
src/share/classes/sun/nio/ch/SelectorImpl.java
+14
-12
test/com/sun/jdi/MonitorFrameInfo.java
test/com/sun/jdi/MonitorFrameInfo.java
+26
-6
test/com/sun/jdi/ResumeOneThreadTest.java
test/com/sun/jdi/ResumeOneThreadTest.java
+233
-0
test/com/sun/jdi/SourceNameFilterTest.java
test/com/sun/jdi/SourceNameFilterTest.java
+28
-7
test/com/sun/jdi/VMConnection.java
test/com/sun/jdi/VMConnection.java
+1
-1
test/java/nio/channels/FileChannel/ExpandingMap.java
test/java/nio/channels/FileChannel/ExpandingMap.java
+9
-2
test/java/nio/channels/Selector/Wakeup.java
test/java/nio/channels/Selector/Wakeup.java
+197
-0
test/javax/management/Introspector/AnnotatedMBeanTest.java
test/javax/management/Introspector/AnnotatedMBeanTest.java
+337
-0
test/javax/management/Introspector/AnnotatedNotificationInfoTest.java
...anagement/Introspector/AnnotatedNotificationInfoTest.java
+271
-0
test/javax/management/Introspector/MBeanDescriptionTest.java
test/javax/management/Introspector/MBeanDescriptionTest.java
+830
-0
test/javax/management/Introspector/ParameterNameTest.java
test/javax/management/Introspector/ParameterNameTest.java
+116
-0
test/javax/management/Introspector/ResourceInjectionTest.java
.../javax/management/Introspector/ResourceInjectionTest.java
+656
-0
test/javax/management/Introspector/annot/Name.java
test/javax/management/Introspector/annot/Name.java
+32
-0
test/javax/management/mxbean/ComparatorExceptionTest.java
test/javax/management/mxbean/ComparatorExceptionTest.java
+90
-0
test/javax/management/mxbean/MXBeanTest.java
test/javax/management/mxbean/MXBeanTest.java
+26
-11
test/javax/management/mxbean/SameObjectTwoNamesTest.java
test/javax/management/mxbean/SameObjectTwoNamesTest.java
+76
-0
未找到文件。
.hgtags
浏览文件 @
a311994c
...
...
@@ -5,3 +5,4 @@ fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26
02e4c5348592a8d7fc2cba28bc5f8e35c0e17277 jdk7-b28
e21f4266466cd1306b176aaa08b2cd8337a9be3d jdk7-b29
b6d6877c1155621a175dccd12dc14c54f938fb8b jdk7-b30
b7474b739d13bacd9972f88ac91f6350b7b0be12 jdk7-b31
src/share/back/eventFilter.c
浏览文件 @
a311994c
...
...
@@ -492,14 +492,17 @@ eventFilterRestricted_passesFilter(JNIEnv *env,
char
*
sourceName
=
0
;
jvmtiError
error
=
JVMTI_FUNC_PTR
(
gdata
->
jvmti
,
GetSourceFileName
)
(
gdata
->
jvmti
,
clazz
,
&
sourceName
);
if
(
error
==
JVMTI_ERROR_NONE
)
{
if
(
sourceName
==
0
||
!
patternStringMatch
(
sourceName
,
desiredNamePattern
))
{
/* We have no match */
jvmtiDeallocate
(
sourceName
);
return
JNI_FALSE
;
}
if
(
error
==
JVMTI_ERROR_NONE
&&
sourceName
!=
0
&&
patternStringMatch
(
sourceName
,
desiredNamePattern
))
{
// got a hit - report the event
jvmtiDeallocate
(
sourceName
)
;
break
;
}
// We have no match, we have no source file name,
// or we got a JVM TI error. Don't report the event.
jvmtiDeallocate
(
sourceName
);
return
JNI_FALSE
;
}
break
;
}
...
...
src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
浏览文件 @
a311994c
...
...
@@ -84,8 +84,13 @@ import com.sun.jmx.mbeanserver.MBeanInstantiator;
import
com.sun.jmx.mbeanserver.Repository
;
import
com.sun.jmx.mbeanserver.NamedObject
;
import
com.sun.jmx.mbeanserver.Introspector
;
import
com.sun.jmx.mbeanserver.MBeanInjector
;
import
com.sun.jmx.mbeanserver.NotifySupport
;
import
com.sun.jmx.mbeanserver.Repository.RegistrationContext
;
import
com.sun.jmx.mbeanserver.Util
;
import
com.sun.jmx.remote.util.EnvHelp
;
import
javax.management.DynamicWrapperMBean
;
import
javax.management.NotificationBroadcasterSupport
;
/**
* This is the default class for MBean manipulation on the agent side. It
...
...
@@ -433,36 +438,26 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
if
(
instance
instanceof
MBeanRegistration
)
preDeregisterInvoke
((
MBeanRegistration
)
instance
);
repository
.
remove
(
name
);
// may throw InstanceNotFoundException
/**
* Checks if the unregistered MBean is a ClassLoader
* If so, it removes the MBean from the default loader repository.
*/
Object
resource
=
getResource
(
instance
);
if
(
resource
instanceof
ClassLoader
&&
resource
!=
server
.
getClass
().
getClassLoader
())
{
final
ModifiableClassLoaderRepository
clr
=
instantiator
.
getClassLoaderRepository
();
if
(
clr
!=
null
)
clr
.
removeClassLoader
(
name
);
}
final
Object
resource
=
getResource
(
instance
);
// Unregisters the MBean from the repository.
// Returns the resource context that was used.
// The returned context does nothing for regular MBeans.
// For ClassLoader MBeans and JMXNamespace (and JMXDomain)
// MBeans - the context makes it possible to unregister these
// objects from the appropriate framework artifacts, such as
// the CLR or the dispatcher, from within the repository lock.
// In case of success, we also need to call context.done() at the
// end of this method.
//
final
ResourceContext
context
=
unregisterFromRepository
(
resource
,
instance
,
name
);
// ---------------------
// Send deletion event
// ---------------------
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
MBEANSERVER_LOGGER
.
logp
(
Level
.
FINER
,
DefaultMBeanServerInterceptor
.
class
.
getName
(),
"unregisterMBean"
,
"Send delete notification of object "
+
name
.
getCanonicalName
());
}
sendNotification
(
MBeanServerNotification
.
UNREGISTRATION_NOTIFICATION
,
name
);
if
(
instance
instanceof
MBeanRegistration
)
postDeregisterInvoke
((
MBeanRegistration
)
instance
);
context
.
done
();
}
public
ObjectInstance
getObjectInstance
(
ObjectName
name
)
...
...
@@ -939,15 +934,22 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
ObjectName
logicalName
=
name
;
logicalName
=
preRegister
(
mbean
,
server
,
name
);
// preRegister returned successfully, so from this point on we
// must call postRegister(false) if there is any problem.
boolean
registered
=
false
;
boolean
registerFailed
=
false
;
ResourceContext
context
=
null
;
try
{
mbean
=
injectResources
(
mbean
,
server
,
logicalName
);
if
(
mbean
instanceof
MBeanRegistration
)
{
MBeanRegistration
reg
=
(
MBeanRegistration
)
mbean
;
logicalName
=
preRegisterInvoke
(
reg
,
name
,
server
);
if
(
mbean
instanceof
DynamicMBean2
)
{
try
{
((
DynamicMBean2
)
mbean
).
preRegister2
(
server
,
logicalName
);
registerFailed
=
true
;
// until we succeed
}
catch
(
Exception
e
)
{
postRegisterInvoke
(
reg
,
false
,
false
);
if
(
e
instanceof
RuntimeException
)
throw
(
RuntimeException
)
e
;
if
(
e
instanceof
InstanceAlreadyExistsException
)
...
...
@@ -960,86 +962,102 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
logicalName
=
ObjectName
.
getInstance
(
nonDefaultDomain
(
logicalName
));
}
}
checkMBeanPermission
(
classname
,
null
,
logicalName
,
"registerMBean"
);
checkMBeanPermission
(
classname
,
null
,
logicalName
,
"registerMBean"
);
final
ObjectInstance
result
;
if
(
logicalName
!=
null
)
{
result
=
new
ObjectInstance
(
logicalName
,
classname
);
internal_addObject
(
mbean
,
logicalName
);
}
else
{
if
(
mbean
instanceof
MBeanRegistration
)
postRegisterInvoke
((
MBeanRegistration
)
mbean
,
false
,
true
);
final
RuntimeException
wrapped
=
new
IllegalArgumentException
(
"No object name specified"
);
throw
new
RuntimeOperationsException
(
wrapped
,
"Exception occurred trying to register the MBean"
);
}
if
(
mbean
instanceof
MBeanRegistration
)
postRegisterInvoke
((
MBeanRegistration
)
mbean
,
true
,
false
);
/**
* Checks if the newly registered MBean is a ClassLoader
* If so, tell the ClassLoaderRepository (CLR) about it. We do
* this even if the object is a PrivateClassLoader. In that
* case, the CLR remembers the loader for use when it is
* explicitly named (e.g. as the loader in createMBean) but
* does not add it to the list that is consulted by
* ClassLoaderRepository.loadClass.
*/
final
Object
resource
=
getResource
(
mbean
);
if
(
resource
instanceof
ClassLoader
)
{
final
ModifiableClassLoaderRepository
clr
=
instantiator
.
getClassLoaderRepository
();
if
(
clr
==
null
)
{
if
(
logicalName
==
null
)
{
final
RuntimeException
wrapped
=
new
IllegalArgumentException
(
"Dynamic addition of class loaders is not supported"
);
new
IllegalArgumentException
(
"No object name specified"
);
throw
new
RuntimeOperationsException
(
wrapped
,
"Exception occurred trying to register the MBean as a class loader
"
);
"Exception occurred trying to register the MBean
"
);
}
clr
.
addClassLoader
(
logicalName
,
(
ClassLoader
)
resource
);
}
return
result
;
}
final
Object
resource
=
getResource
(
mbean
);
// Register the MBean with the repository.
// Returns the resource context that was used.
// The returned context does nothing for regular MBeans.
// For ClassLoader MBeans and JMXNamespace (and JMXDomain)
// MBeans - the context makes it possible to register these
// objects with the appropriate framework artifacts, such as
// the CLR or the dispatcher, from within the repository lock.
// In case of success, we also need to call context.done() at the
// end of this method.
//
context
=
registerWithRepository
(
resource
,
mbean
,
logicalName
);
private
static
ObjectName
preRegisterInvoke
(
MBeanRegistration
moi
,
ObjectName
name
,
MBeanServer
mbs
)
throws
InstanceAlreadyExistsException
,
MBeanRegistrationException
{
registerFailed
=
false
;
registered
=
true
;
}
finally
{
postRegister
(
mbean
,
registered
,
registerFailed
);
}
final
ObjectName
newName
;
context
.
done
();
return
new
ObjectInstance
(
logicalName
,
classname
);
}
private
static
void
throwMBeanRegistrationException
(
Throwable
t
,
String
where
)
throws
MBeanRegistrationException
{
try
{
newName
=
moi
.
preRegister
(
mbs
,
name
)
;
throw
t
;
}
catch
(
RuntimeException
e
)
{
throw
new
RuntimeMBeanException
(
e
,
"RuntimeException thrown in preRegister method"
);
throw
new
RuntimeMBeanException
(
e
,
"RuntimeException thrown "
+
where
);
}
catch
(
Error
er
)
{
throw
new
RuntimeErrorException
(
er
,
"Error thrown in preRegister method"
);
throw
new
RuntimeErrorException
(
er
,
"Error thrown "
+
where
);
}
catch
(
MBeanRegistrationException
r
)
{
throw
r
;
}
catch
(
Exception
ex
)
{
throw
new
MBeanRegistrationException
(
ex
,
"Exception thrown in preRegister method"
);
throw
new
MBeanRegistrationException
(
ex
,
"Exception thrown "
+
where
);
}
catch
(
Throwable
t1
)
{
throw
new
RuntimeException
(
t
);
// neither Error nor Exception??
}
}
private
static
ObjectName
preRegister
(
DynamicMBean
mbean
,
MBeanServer
mbs
,
ObjectName
name
)
throws
InstanceAlreadyExistsException
,
MBeanRegistrationException
{
ObjectName
newName
=
null
;
try
{
if
(
mbean
instanceof
MBeanRegistration
)
newName
=
((
MBeanRegistration
)
mbean
).
preRegister
(
mbs
,
name
);
}
catch
(
Throwable
t
)
{
throwMBeanRegistrationException
(
t
,
"in preRegister method"
);
}
if
(
newName
!=
null
)
return
newName
;
else
return
name
;
}
private
static
void
postRegisterInvoke
(
MBeanRegistration
moi
,
boolean
registrationDone
,
boolean
registerFailed
)
{
private
static
DynamicMBean
injectResources
(
DynamicMBean
mbean
,
MBeanServer
mbs
,
ObjectName
name
)
throws
MBeanRegistrationException
{
try
{
Object
resource
=
getResource
(
mbean
);
MBeanInjector
.
inject
(
resource
,
mbs
,
name
);
if
(
MBeanInjector
.
injectsSendNotification
(
resource
))
{
NotificationBroadcasterSupport
nbs
=
new
NotificationBroadcasterSupport
();
MBeanInjector
.
injectSendNotification
(
resource
,
nbs
);
mbean
=
NotifySupport
.
wrap
(
mbean
,
nbs
);
}
return
mbean
;
}
catch
(
Throwable
t
)
{
throwMBeanRegistrationException
(
t
,
"injecting @Resources"
);
return
null
;
// not reached
}
}
private
static
void
postRegister
(
DynamicMBean
mbean
,
boolean
registrationDone
,
boolean
registerFailed
)
{
if
(
registerFailed
&&
m
oi
instanceof
DynamicMBean2
)
((
DynamicMBean2
)
m
oi
).
registerFailed
();
if
(
registerFailed
&&
m
bean
instanceof
DynamicMBean2
)
((
DynamicMBean2
)
m
bean
).
registerFailed
();
try
{
moi
.
postRegister
(
registrationDone
);
if
(
mbean
instanceof
MBeanRegistration
)
((
MBeanRegistration
)
mbean
).
postRegister
(
registrationDone
);
}
catch
(
RuntimeException
e
)
{
throw
new
RuntimeMBeanException
(
e
,
"RuntimeException thrown in postRegister method"
);
...
...
@@ -1053,17 +1071,8 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
throws
MBeanRegistrationException
{
try
{
moi
.
preDeregister
();
}
catch
(
RuntimeException
e
)
{
throw
new
RuntimeMBeanException
(
e
,
"RuntimeException thrown in preDeregister method"
);
}
catch
(
Error
er
)
{
throw
new
RuntimeErrorException
(
er
,
"Error thrown in preDeregister method"
);
}
catch
(
MBeanRegistrationException
t
)
{
throw
t
;
}
catch
(
Exception
ex
)
{
throw
new
MBeanRegistrationException
(
ex
,
"Exception thrown in preDeregister method"
);
}
catch
(
Throwable
t
)
{
throwMBeanRegistrationException
(
t
,
"in preDeregister method"
);
}
}
...
...
@@ -1104,12 +1113,19 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
private
static
Object
getResource
(
DynamicMBean
mbean
)
{
if
(
mbean
instanceof
Dynamic
MBean2
)
return
((
Dynamic
MBean2
)
mbean
).
getResource
();
if
(
mbean
instanceof
Dynamic
WrapperMBean
)
return
((
Dynamic
WrapperMBean
)
mbean
).
getWrappedObject
();
else
return
mbean
;
}
private
static
ClassLoader
getResourceLoader
(
DynamicMBean
mbean
)
{
if
(
mbean
instanceof
DynamicWrapperMBean
)
return
((
DynamicWrapperMBean
)
mbean
).
getWrappedClassLoader
();
else
return
mbean
.
getClass
().
getClassLoader
();
}
private
ObjectName
nonDefaultDomain
(
ObjectName
name
)
{
if
(
name
==
null
||
name
.
getDomain
().
length
()
>
0
)
return
name
;
...
...
@@ -1123,14 +1139,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
if one is supplied where it shouldn't be). */
final
String
completeName
=
domain
+
name
;
try
{
return
new
ObjectName
(
completeName
);
}
catch
(
MalformedObjectNameException
e
)
{
final
String
msg
=
"Unexpected default domain problem: "
+
completeName
+
": "
+
e
;
throw
EnvHelp
.
initCause
(
new
IllegalArgumentException
(
msg
),
e
);
}
return
Util
.
newObjectName
(
completeName
);
}
public
String
getDefaultDomain
()
{
...
...
@@ -1211,7 +1220,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
NotificationListener
listenerWrapper
=
getListenerWrapper
(
listener
,
name
,
broadcaster
,
true
);
getListenerWrapper
(
listener
,
name
,
instance
,
true
);
broadcaster
.
addNotificationListener
(
listenerWrapper
,
filter
,
handback
);
}
...
...
@@ -1335,7 +1344,6 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
DynamicMBean
instance
=
getMBean
(
name
);
checkMBeanPermission
(
instance
,
null
,
name
,
"removeNotificationListener"
);
Object
resource
=
getResource
(
instance
);
/* We could simplify the code by assigning broadcaster after
assigning listenerWrapper, but that would change the error
...
...
@@ -1348,7 +1356,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
getNotificationBroadcaster
(
name
,
instance
,
reqClass
);
NotificationListener
listenerWrapper
=
getListenerWrapper
(
listener
,
name
,
resour
ce
,
false
);
getListenerWrapper
(
listener
,
name
,
instan
ce
,
false
);
if
(
listenerWrapper
==
null
)
throw
new
ListenerNotFoundException
(
"Unknown listener"
);
...
...
@@ -1366,8 +1374,10 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
private
static
<
T
extends
NotificationBroadcaster
>
T
getNotificationBroadcaster
(
ObjectName
name
,
Object
instance
,
Class
<
T
>
reqClass
)
{
if
(
instance
instanceof
DynamicMBean2
)
instance
=
((
DynamicMBean2
)
instance
).
getResource
();
if
(
reqClass
.
isInstance
(
instance
))
return
reqClass
.
cast
(
instance
);
if
(
instance
instanceof
DynamicWrapperMBean
)
instance
=
((
DynamicWrapperMBean
)
instance
).
getWrappedObject
();
if
(
reqClass
.
isInstance
(
instance
))
return
reqClass
.
cast
(
instance
);
final
RuntimeException
exc
=
...
...
@@ -1415,24 +1425,31 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
checkMBeanPermission
(
instance
,
null
,
name
,
"isInstanceOf"
);
try
{
if
(
instance
instanceof
DynamicMBean2
)
{
Object
resource
=
((
DynamicMBean2
)
instance
).
getResource
();
ClassLoader
loader
=
resource
.
getClass
().
getClassLoader
();
Class
<?>
c
=
Class
.
forName
(
className
,
false
,
loader
);
return
c
.
isInstance
(
resource
);
}
Object
resource
=
getResource
(
instance
);
final
String
cn
=
getClassName
(
instance
);
if
(
cn
.
equals
(
className
))
final
String
resourceClassName
=
(
resource
instanceof
DynamicMBean
)
?
getClassName
((
DynamicMBean
)
resource
)
:
resource
.
getClass
().
getName
();
if
(
resourceClassName
.
equals
(
className
))
return
true
;
final
ClassLoader
cl
=
instance
.
getClass
().
getClassLoader
(
);
final
ClassLoader
cl
=
getResourceLoader
(
instance
);
final
Class
<?>
classNameClass
=
Class
.
forName
(
className
,
false
,
cl
);
if
(
classNameClass
.
isInstance
(
instance
))
if
(
classNameClass
.
isInstance
(
resource
))
return
true
;
// Ensure that isInstanceOf(NotificationEmitter) is true when
// the MBean is a NotificationEmitter by virtue of a @Resource
// annotation specifying a SendNotification resource.
// This is a hack.
if
(
instance
instanceof
NotificationBroadcaster
&&
classNameClass
.
isAssignableFrom
(
NotificationEmitter
.
class
))
return
true
;
final
Class
<?>
instanceClass
=
Class
.
forName
(
cn
,
false
,
cl
);
return
classNameClass
.
isAssignableFrom
(
instan
ceClass
);
final
Class
<?>
resourceClass
=
Class
.
forName
(
resourceClassName
,
false
,
cl
);
return
classNameClass
.
isAssignableFrom
(
resour
ceClass
);
}
catch
(
Exception
x
)
{
/* Could be SecurityException or ClassNotFoundException */
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINEST
))
{
...
...
@@ -1457,7 +1474,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
DynamicMBean
instance
=
getMBean
(
mbeanName
);
checkMBeanPermission
(
instance
,
null
,
mbeanName
,
"getClassLoaderFor"
);
return
getResource
(
instance
).
getClass
().
getClassLoader
(
);
return
getResource
Loader
(
instance
);
}
/**
...
...
@@ -1488,40 +1505,6 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
return
(
ClassLoader
)
resource
;
}
/**
* Adds a MBean in the repository
*/
private
void
internal_addObject
(
DynamicMBean
object
,
ObjectName
logicalName
)
throws
InstanceAlreadyExistsException
{
// ------------------------------
// ------------------------------
// Let the repository do the work.
try
{
repository
.
addMBean
(
object
,
logicalName
);
}
catch
(
InstanceAlreadyExistsException
e
)
{
if
(
object
instanceof
MBeanRegistration
)
{
postRegisterInvoke
((
MBeanRegistration
)
object
,
false
,
true
);
}
throw
e
;
}
// ---------------------
// Send create event
// ---------------------
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
MBEANSERVER_LOGGER
.
logp
(
Level
.
FINER
,
DefaultMBeanServerInterceptor
.
class
.
getName
(),
"addObject"
,
"Send create notification of object "
+
logicalName
.
getCanonicalName
());
}
sendNotification
(
MBeanServerNotification
.
REGISTRATION_NOTIFICATION
,
logicalName
)
;
}
/**
* Sends an MBeanServerNotifications with the specified type for the
* MBean with the specified ObjectName
...
...
@@ -1712,9 +1695,10 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
*/
private
NotificationListener
getListenerWrapper
(
NotificationListener
l
,
ObjectName
name
,
Object
mbean
,
DynamicMBean
mbean
,
boolean
create
)
{
ListenerWrapper
wrapper
=
new
ListenerWrapper
(
l
,
name
,
mbean
);
Object
resource
=
getResource
(
mbean
);
ListenerWrapper
wrapper
=
new
ListenerWrapper
(
l
,
name
,
resource
);
synchronized
(
listenerWrappers
)
{
WeakReference
<
ListenerWrapper
>
ref
=
listenerWrappers
.
get
(
wrapper
);
if
(
ref
!=
null
)
{
...
...
@@ -1758,6 +1742,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
listener
.
handleNotification
(
notification
,
handback
);
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
ListenerWrapper
))
return
false
;
...
...
@@ -1774,6 +1759,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
*/
}
@Override
public
int
hashCode
()
{
return
(
System
.
identityHashCode
(
listener
)
^
System
.
identityHashCode
(
mbean
));
...
...
@@ -1851,4 +1837,213 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
}
// ------------------------------------------------------------------
//
// Dealing with registration of special MBeans in the repository.
//
// ------------------------------------------------------------------
/**
* A RegistrationContext that makes it possible to perform additional
* post registration actions (or post unregistration actions) outside
* of the repository lock, once postRegister (or postDeregister) has
* been called.
* The method {@code done()} will be called in registerMBean or
* unregisterMBean, at the end.
*/
private
static
interface
ResourceContext
extends
RegistrationContext
{
public
void
done
();
/** An empty ResourceContext which does nothing **/
public
static
final
ResourceContext
NONE
=
new
ResourceContext
()
{
public
void
done
()
{}
public
void
registering
()
{}
public
void
unregistered
()
{}
};
}
/**
* Adds a MBean in the repository,
* sends MBeanServerNotification.REGISTRATION_NOTIFICATION,
* returns ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces. For regular MBean this method returns
* ResourceContext.NONE.
* @return a ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces.
*/
private
ResourceContext
registerWithRepository
(
final
Object
resource
,
final
DynamicMBean
object
,
final
ObjectName
logicalName
)
throws
InstanceAlreadyExistsException
,
MBeanRegistrationException
{
// Creates a registration context, if needed.
//
final
ResourceContext
context
=
makeResourceContextFor
(
resource
,
logicalName
);
repository
.
addMBean
(
object
,
logicalName
,
context
);
// May throw InstanceAlreadyExistsException
// ---------------------
// Send create event
// ---------------------
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
MBEANSERVER_LOGGER
.
logp
(
Level
.
FINER
,
DefaultMBeanServerInterceptor
.
class
.
getName
(),
"addObject"
,
"Send create notification of object "
+
logicalName
.
getCanonicalName
());
}
sendNotification
(
MBeanServerNotification
.
REGISTRATION_NOTIFICATION
,
logicalName
);
return
context
;
}
/**
* Removes a MBean in the repository,
* sends MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
* returns ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces, or null. For regular MBean this method returns
* ResourceContext.NONE.
*
* @return a ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces.
*/
private
ResourceContext
unregisterFromRepository
(
final
Object
resource
,
final
DynamicMBean
object
,
final
ObjectName
logicalName
)
throws
InstanceNotFoundException
{
// Creates a registration context, if needed.
//
final
ResourceContext
context
=
makeResourceContextFor
(
resource
,
logicalName
);
repository
.
remove
(
logicalName
,
context
);
// ---------------------
// Send deletion event
// ---------------------
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
MBEANSERVER_LOGGER
.
logp
(
Level
.
FINER
,
DefaultMBeanServerInterceptor
.
class
.
getName
(),
"unregisterMBean"
,
"Send delete notification of object "
+
logicalName
.
getCanonicalName
());
}
sendNotification
(
MBeanServerNotification
.
UNREGISTRATION_NOTIFICATION
,
logicalName
);
return
context
;
}
/**
* Registers a ClassLoader with the CLR.
* This method is called by the ResourceContext from within the
* repository lock.
* @param loader The ClassLoader.
* @param logicalName The ClassLoader MBean ObjectName.
*/
private
void
addClassLoader
(
ClassLoader
loader
,
final
ObjectName
logicalName
)
{
/**
* Called when the newly registered MBean is a ClassLoader
* If so, tell the ClassLoaderRepository (CLR) about it. We do
* this even if the loader is a PrivateClassLoader. In that
* case, the CLR remembers the loader for use when it is
* explicitly named (e.g. as the loader in createMBean) but
* does not add it to the list that is consulted by
* ClassLoaderRepository.loadClass.
*/
final
ModifiableClassLoaderRepository
clr
=
instantiator
.
getClassLoaderRepository
();
if
(
clr
==
null
)
{
final
RuntimeException
wrapped
=
new
IllegalArgumentException
(
"Dynamic addition of class loaders"
+
" is not supported"
);
throw
new
RuntimeOperationsException
(
wrapped
,
"Exception occurred trying to register"
+
" the MBean as a class loader"
);
}
clr
.
addClassLoader
(
logicalName
,
loader
);
}
/**
* Unregisters a ClassLoader from the CLR.
* This method is called by the ResourceContext from within the
* repository lock.
* @param loader The ClassLoader.
* @param logicalName The ClassLoader MBean ObjectName.
*/
private
void
removeClassLoader
(
ClassLoader
loader
,
final
ObjectName
logicalName
)
{
/**
* Removes the MBean from the default loader repository.
*/
if
(
loader
!=
server
.
getClass
().
getClassLoader
())
{
final
ModifiableClassLoaderRepository
clr
=
instantiator
.
getClassLoaderRepository
();
if
(
clr
!=
null
)
{
clr
.
removeClassLoader
(
logicalName
);
}
}
}
/**
* Creates a ResourceContext for a ClassLoader MBean.
* The resource context makes it possible to add the ClassLoader to
* (ResourceContext.registering) or resp. remove the ClassLoader from
* (ResourceContext.unregistered) the CLR
* when the associated MBean is added to or resp. removed from the
* repository.
*
* @param loader The ClassLoader MBean being registered or
* unregistered.
* @param logicalName The name of the ClassLoader MBean.
* @return a ResourceContext that takes in charge the addition or removal
* of the loader to or from the CLR.
*/
private
ResourceContext
createClassLoaderContext
(
final
ClassLoader
loader
,
final
ObjectName
logicalName
)
{
return
new
ResourceContext
()
{
public
void
registering
()
{
addClassLoader
(
loader
,
logicalName
);
}
public
void
unregistered
()
{
removeClassLoader
(
loader
,
logicalName
);
}
public
void
done
()
{
}
};
}
/**
* Creates a ResourceContext for the given resource.
* If the resource does not need a ResourceContext, returns
* ResourceContext.NONE.
* At this time, only JMXNamespaces and ClassLoaders need a
* ResourceContext.
*
* @param resource The resource being registered or unregistered.
* @param logicalName The name of the associated MBean.
* @return
*/
private
ResourceContext
makeResourceContextFor
(
Object
resource
,
ObjectName
logicalName
)
{
if
(
resource
instanceof
ClassLoader
)
{
return
createClassLoaderContext
((
ClassLoader
)
resource
,
logicalName
);
}
return
ResourceContext
.
NONE
;
}
}
src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
浏览文件 @
a311994c
...
...
@@ -686,7 +686,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final
String
msg
=
"Cannot convert SortedSet with non-null comparator: "
+
comparator
;
throw
new
OpenDataException
(
msg
);
throw
openDataException
(
msg
,
new
IllegalArgumentException
(
msg
)
);
}
}
final
Object
[]
openArray
=
(
Object
[])
...
...
@@ -800,7 +800,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final
String
msg
=
"Cannot convert SortedMap with non-null comparator: "
+
comparator
;
throw
new
OpenDataException
(
msg
);
throw
openDataException
(
msg
,
new
IllegalArgumentException
(
msg
)
);
}
}
final
TabularType
tabularType
=
(
TabularType
)
getOpenType
();
...
...
src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java
浏览文件 @
a311994c
...
...
@@ -25,7 +25,7 @@
package
com.sun.jmx.mbeanserver
;
import
javax.management.DynamicMBean
;
import
javax.management.Dynamic
Wrapper
MBean
;
import
javax.management.MBeanServer
;
import
javax.management.ObjectName
;
...
...
@@ -35,17 +35,7 @@ import javax.management.ObjectName;
*
* @since 1.6
*/
public
interface
DynamicMBean2
extends
DynamicMBean
{
/**
* The resource corresponding to this MBean. This is the object whose
* class name should be reflected by the MBean's
* getMBeanInfo().getClassName() for example. For a "plain"
* DynamicMBean it will be "this". For an MBean that wraps another
* object, like javax.management.StandardMBean, it will be the wrapped
* object.
*/
public
Object
getResource
();
public
interface
DynamicMBean2
extends
DynamicWrapperMBean
{
/**
* The name of this MBean's class, as used by permission checks.
* This is typically equal to getResource().getClass().getName().
...
...
src/share/classes/com/sun/jmx/mbeanserver/Introspector.java
浏览文件 @
a311994c
...
...
@@ -25,23 +25,39 @@
package
com.sun.jmx.mbeanserver
;
import
com.sun.jmx.remote.util.EnvHelp
;
import
java.beans.BeanInfo
;
import
java.beans.PropertyDescriptor
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.AnnotatedElement
;
import
java.lang.reflect.Array
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.lang.reflect.Proxy
;
import
java.lang.reflect.UndeclaredThrowableException
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.logging.Level
;
import
javax.management.AttributeNotFoundException
;
import
javax.management.Description
;
import
javax.management.Descriptor
;
import
javax.management.DescriptorFields
;
import
javax.management.DescriptorKey
;
import
javax.management.DynamicMBean
;
import
javax.management.ImmutableDescriptor
;
import
javax.management.MBean
;
import
javax.management.MBeanInfo
;
import
javax.management.MXBean
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
static
com
.
sun
.
jmx
.
defaults
.
JmxProperties
.
MBEANSERVER_LOGGER
;
import
com.sun.jmx.mbeanserver.Util
;
import
com.sun.jmx.remote.util.EnvHelp
;
import
java.beans.BeanInfo
;
import
java.beans.PropertyDescriptor
;
...
...
@@ -133,8 +149,12 @@ public class Introspector {
}
}
public
static
void
checkCompliance
(
Class
mbeanClass
)
throws
NotCompliantMBeanException
{
public
static
void
checkCompliance
(
Class
<?>
mbeanClass
)
throws
NotCompliantMBeanException
{
// Check that @Resource is used correctly (if it used).
MBeanInjector
.
validate
(
mbeanClass
);
// Is DynamicMBean?
//
if
(
DynamicMBean
.
class
.
isAssignableFrom
(
mbeanClass
))
...
...
@@ -157,21 +177,39 @@ public class Introspector {
}
catch
(
NotCompliantMBeanException
e
)
{
mxbeanException
=
e
;
}
// Is @MBean or @MXBean class?
// In fact we find @MBean or @MXBean as a hacky variant of
// getStandardMBeanInterface or getMXBeanInterface. If we get here
// then nothing worked.
final
String
msg
=
"MBean class "
+
mbeanClass
.
getName
()
+
" does not implement "
+
"DynamicMBean, neither follows the Standard MBean conventions ("
+
mbeanException
.
toString
()
+
") nor the MXBean conventions ("
+
mxbeanException
.
toString
()
+
")"
;
"DynamicMBean; does not follow the Standard MBean conventions ("
+
mbeanException
.
toString
()
+
"); does not follow the MXBean conventions ("
+
mxbeanException
.
toString
()
+
"); and does not have or inherit the @"
+
MBean
.
class
.
getSimpleName
()
+
" or @"
+
MXBean
.
class
.
getSimpleName
()
+
" annotation"
;
throw
new
NotCompliantMBeanException
(
msg
);
}
/**
* <p>Make a DynamicMBean out of the existing MBean object. The object
* may already be a DynamicMBean, or it may be a Standard MBean or
* MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p>
* @param mbean the object to convert to a DynamicMBean.
* @param <T> a type parameter defined for implementation convenience
* (which would have to be removed if this method were part of the public
* API).
* @return the converted DynamicMBean.
* @throws NotCompliantMBeanException if {@code mbean} is not a compliant
* MBean object, including the case where it is null.
*/
public
static
<
T
>
DynamicMBean
makeDynamicMBean
(
T
mbean
)
throws
NotCompliantMBeanException
{
if
(
mbean
==
null
)
throw
new
NotCompliantMBeanException
(
"Null MBean object"
);
if
(
mbean
instanceof
DynamicMBean
)
return
(
DynamicMBean
)
mbean
;
final
Class
mbeanClass
=
mbean
.
getClass
();
final
Class
<?>
mbeanClass
=
mbean
.
getClass
();
Class
<?
super
T
>
c
=
null
;
try
{
c
=
Util
.
cast
(
getStandardMBeanInterface
(
mbeanClass
));
...
...
@@ -270,7 +308,7 @@ public class Introspector {
* Return <code>null</code> if the MBean is a DynamicMBean,
* or if no MBean interface is found.
*/
public
static
Class
getMBeanInterface
(
Class
baseClass
)
{
public
static
Class
<?>
getMBeanInterface
(
Class
<?>
baseClass
)
{
// Check if the given class implements the MBean interface
// or the Dynamic MBean interface
if
(
isDynamic
(
baseClass
))
return
null
;
...
...
@@ -291,10 +329,12 @@ public class Introspector {
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant Standard MBean.
*/
public
static
Class
getStandardMBeanInterface
(
Class
baseClass
)
throws
NotCompliantMBeanException
{
Class
current
=
baseClass
;
Class
mbeanInterface
=
null
;
public
static
<
T
>
Class
<?
super
T
>
getStandardMBeanInterface
(
Class
<
T
>
baseClass
)
throws
NotCompliantMBeanException
{
if
(
baseClass
.
isAnnotationPresent
(
MBean
.
class
))
return
baseClass
;
Class
<?
super
T
>
current
=
baseClass
;
Class
<?
super
T
>
mbeanInterface
=
null
;
while
(
current
!=
null
)
{
mbeanInterface
=
findMBeanInterface
(
current
,
current
.
getName
());
...
...
@@ -321,8 +361,10 @@ public class Introspector {
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant MXBean.
*/
public
static
Class
getMXBeanInterface
(
Class
baseClass
)
public
static
<
T
>
Class
<?
super
T
>
getMXBeanInterface
(
Class
<
T
>
baseClass
)
throws
NotCompliantMBeanException
{
if
(
hasMXBeanAnnotation
(
baseClass
))
return
baseClass
;
try
{
return
MXBeanSupport
.
findMXBeanInterface
(
baseClass
);
}
catch
(
Exception
e
)
{
...
...
@@ -345,19 +387,24 @@ public class Introspector {
* ------------------------------------------
*/
static
boolean
hasMXBeanAnnotation
(
Class
<?>
c
)
{
MXBean
m
=
c
.
getAnnotation
(
MXBean
.
class
);
return
(
m
!=
null
&&
m
.
value
());
}
/**
* Try to find the MBean interface corresponding to the class aName
* - i.e. <i>aName</i>MBean, from within aClass and its superclasses.
**/
private
static
Class
findMBeanInterface
(
Class
aClass
,
String
aName
)
{
Class
current
=
aClass
;
private
static
<
T
>
Class
<?
super
T
>
findMBeanInterface
(
Class
<
T
>
aClass
,
String
aName
)
{
Class
<?
super
T
>
current
=
aClass
;
while
(
current
!=
null
)
{
final
Class
[]
interfaces
=
current
.
getInterfaces
();
final
Class
<?>
[]
interfaces
=
current
.
getInterfaces
();
final
int
len
=
interfaces
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
final
Class
inter
=
implementsMBean
(
interfaces
[
i
]
,
aName
);
Class
<?
super
T
>
inter
=
Util
.
cast
(
interfaces
[
i
]);
inter
=
implementsMBean
(
inter
,
aName
);
if
(
inter
!=
null
)
return
inter
;
}
current
=
current
.
getSuperclass
();
...
...
@@ -365,6 +412,48 @@ public class Introspector {
return
null
;
}
public
static
String
descriptionForElement
(
AnnotatedElement
elmt
)
{
if
(
elmt
==
null
)
return
null
;
Description
d
=
elmt
.
getAnnotation
(
Description
.
class
);
if
(
d
==
null
)
return
null
;
return
d
.
value
();
}
public
static
String
descriptionForParameter
(
Annotation
[]
parameterAnnotations
)
{
for
(
Annotation
a
:
parameterAnnotations
)
{
if
(
a
instanceof
Description
)
return
((
Description
)
a
).
value
();
}
return
null
;
}
public
static
String
nameForParameter
(
Annotation
[]
parameterAnnotations
)
{
for
(
Annotation
a
:
parameterAnnotations
)
{
Class
<?
extends
Annotation
>
ac
=
a
.
annotationType
();
// You'd really have to go out of your way to have more than
// one @Name annotation, so we don't check for that.
if
(
ac
.
getSimpleName
().
equals
(
"Name"
))
{
try
{
Method
value
=
ac
.
getMethod
(
"value"
);
if
(
value
.
getReturnType
()
==
String
.
class
&&
value
.
getParameterTypes
().
length
==
0
)
{
return
(
String
)
value
.
invoke
(
a
);
}
}
catch
(
Exception
e
)
{
MBEANSERVER_LOGGER
.
log
(
Level
.
WARNING
,
"Unexpected exception getting @"
+
ac
.
getName
(),
e
);
}
}
}
return
null
;
}
public
static
Descriptor
descriptorForElement
(
final
AnnotatedElement
elmt
)
{
if
(
elmt
==
null
)
return
ImmutableDescriptor
.
EMPTY_DESCRIPTOR
;
...
...
@@ -372,41 +461,18 @@ public class Introspector {
return
descriptorForAnnotations
(
annots
);
}
public
static
Descriptor
descriptorForAnnotation
(
Annotation
annot
)
{
return
descriptorForAnnotations
(
new
Annotation
[]
{
annot
});
}
public
static
Descriptor
descriptorForAnnotations
(
Annotation
[]
annots
)
{
if
(
annots
.
length
==
0
)
return
ImmutableDescriptor
.
EMPTY_DESCRIPTOR
;
Map
<
String
,
Object
>
descriptorMap
=
new
HashMap
<
String
,
Object
>();
for
(
Annotation
a
:
annots
)
{
Class
<?
extends
Annotation
>
c
=
a
.
annotationType
();
Method
[]
elements
=
c
.
getMethods
();
for
(
Method
element
:
elements
)
{
DescriptorKey
key
=
element
.
getAnnotation
(
DescriptorKey
.
class
);
if
(
key
!=
null
)
{
String
name
=
key
.
value
();
Object
value
;
try
{
value
=
element
.
invoke
(
a
);
}
catch
(
RuntimeException
e
)
{
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
//
throw
e
;
}
catch
(
Exception
e
)
{
// we don't expect this
throw
new
UndeclaredThrowableException
(
e
);
}
value
=
annotationToField
(
value
);
Object
oldValue
=
descriptorMap
.
put
(
name
,
value
);
if
(
oldValue
!=
null
&&
!
equals
(
oldValue
,
value
))
{
final
String
msg
=
"Inconsistent values for descriptor field "
+
name
+
" from annotations: "
+
value
+
" :: "
+
oldValue
;
throw
new
IllegalArgumentException
(
msg
);
}
}
}
if
(
a
instanceof
DescriptorFields
)
addDescriptorFieldsToMap
(
descriptorMap
,
(
DescriptorFields
)
a
);
addAnnotationFieldsToMap
(
descriptorMap
,
a
);
}
if
(
descriptorMap
.
isEmpty
())
...
...
@@ -415,6 +481,62 @@ public class Introspector {
return
new
ImmutableDescriptor
(
descriptorMap
);
}
private
static
void
addDescriptorFieldsToMap
(
Map
<
String
,
Object
>
descriptorMap
,
DescriptorFields
df
)
{
for
(
String
field
:
df
.
value
())
{
int
eq
=
field
.
indexOf
(
'='
);
if
(
eq
<
0
)
{
throw
new
IllegalArgumentException
(
"@DescriptorFields string must contain '=': "
+
field
);
}
String
name
=
field
.
substring
(
0
,
eq
);
String
value
=
field
.
substring
(
eq
+
1
);
addToMap
(
descriptorMap
,
name
,
value
);
}
}
private
static
void
addAnnotationFieldsToMap
(
Map
<
String
,
Object
>
descriptorMap
,
Annotation
a
)
{
Class
<?
extends
Annotation
>
c
=
a
.
annotationType
();
Method
[]
elements
=
c
.
getMethods
();
for
(
Method
element
:
elements
)
{
DescriptorKey
key
=
element
.
getAnnotation
(
DescriptorKey
.
class
);
if
(
key
!=
null
)
{
String
name
=
key
.
value
();
Object
value
;
try
{
value
=
element
.
invoke
(
a
);
}
catch
(
RuntimeException
e
)
{
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
throw
e
;
}
catch
(
Exception
e
)
{
// we don't expect this
throw
new
UndeclaredThrowableException
(
e
);
}
if
(!
key
.
omitIfDefault
()
||
!
equals
(
value
,
element
.
getDefaultValue
()))
{
value
=
annotationToField
(
value
);
addToMap
(
descriptorMap
,
name
,
value
);
}
}
}
}
private
static
void
addToMap
(
Map
<
String
,
Object
>
descriptorMap
,
String
name
,
Object
value
)
{
Object
oldValue
=
descriptorMap
.
put
(
name
,
value
);
if
(
oldValue
!=
null
&&
!
equals
(
oldValue
,
value
))
{
final
String
msg
=
"Inconsistent values for descriptor field "
+
name
+
" from annotations: "
+
value
+
" :: "
+
oldValue
;
throw
new
IllegalArgumentException
(
msg
);
}
}
/**
* Throws a NotCompliantMBeanException or a SecurityException.
* @param notCompliant the class which was under examination
...
...
@@ -473,8 +595,13 @@ public class Introspector {
// The only other possibility is that the value is another
// annotation, or that the language has evolved since this code
// was written. We don't allow for either of those currently.
// If it is indeed another annotation, then x will be a proxy
// with an unhelpful name like $Proxy2. So we extract the
// proxy's interface to use that in the exception message.
if
(
Proxy
.
isProxyClass
(
c
))
c
=
c
.
getInterfaces
()[
0
];
// array "can't be empty"
throw
new
IllegalArgumentException
(
"Illegal type for annotation "
+
"element
: "
+
x
.
getClass
()
.
getName
());
"element
using @DescriptorKey: "
+
c
.
getName
());
}
// This must be consistent with the check for duplicate field values in
...
...
@@ -490,15 +617,15 @@ public class Introspector {
* @param c The interface to be tested
* @param clName The name of the class implementing this interface
*/
private
static
Class
implementsMBean
(
Class
c
,
String
clName
)
{
private
static
<
T
>
Class
<?
super
T
>
implementsMBean
(
Class
<
T
>
c
,
String
clName
)
{
String
clMBeanName
=
clName
+
"MBean"
;
if
(
c
.
getName
().
equals
(
clMBeanName
))
{
return
c
;
}
Class
[]
interfaces
=
c
.
getInterfaces
();
Class
<?>
[]
interfaces
=
c
.
getInterfaces
();
for
(
int
i
=
0
;
i
<
interfaces
.
length
;
i
++)
{
if
(
interfaces
[
i
].
getName
().
equals
(
clMBeanName
))
return
interfaces
[
i
]
;
return
Util
.
cast
(
interfaces
[
i
])
;
}
return
null
;
...
...
src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
浏览文件 @
a311994c
...
...
@@ -33,6 +33,10 @@ import java.util.Comparator;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
javax.management.MBean
;
import
javax.management.MXBean
;
import
javax.management.ManagedAttribute
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
/**
...
...
@@ -125,18 +129,26 @@ class MBeanAnalyzer<M> {
for
(
Method
m
:
methods
)
{
final
String
name
=
m
.
getName
();
final
int
nParams
=
m
.
getParameterTypes
().
length
;
final
boolean
managedOp
=
m
.
isAnnotationPresent
(
ManagedOperation
.
class
);
final
boolean
managedAttr
=
m
.
isAnnotationPresent
(
ManagedAttribute
.
class
);
if
(
managedOp
&&
managedAttr
)
{
throw
new
NotCompliantMBeanException
(
"Method "
+
name
+
" has both @ManagedOperation and @ManagedAttribute"
);
}
final
M
cm
=
introspector
.
mFrom
(
m
);
String
attrName
=
""
;
if
(
name
.
startsWith
(
"get"
))
attrName
=
name
.
substring
(
3
);
else
if
(
name
.
startsWith
(
"is"
)
&&
m
.
getReturnType
()
==
boolean
.
class
)
attrName
=
name
.
substring
(
2
);
if
(!
managedOp
)
{
if
(
name
.
startsWith
(
"get"
))
attrName
=
name
.
substring
(
3
);
else
if
(
name
.
startsWith
(
"is"
)
&&
m
.
getReturnType
()
==
boolean
.
class
)
attrName
=
name
.
substring
(
2
);
}
if
(
attrName
.
length
()
!=
0
&&
nParams
==
0
&&
m
.
getReturnType
()
!=
void
.
class
)
{
&&
m
.
getReturnType
()
!=
void
.
class
&&
!
managedOp
)
{
// It's a getter
// Check we don't have both isX and getX
AttrMethods
<
M
>
am
=
attrMap
.
get
(
attrName
);
...
...
@@ -153,7 +165,7 @@ class MBeanAnalyzer<M> {
attrMap
.
put
(
attrName
,
am
);
}
else
if
(
name
.
startsWith
(
"set"
)
&&
name
.
length
()
>
3
&&
nParams
==
1
&&
m
.
getReturnType
()
==
void
.
class
)
{
m
.
getReturnType
()
==
void
.
class
&&
!
managedOp
)
{
// It's a setter
attrName
=
name
.
substring
(
3
);
AttrMethods
<
M
>
am
=
attrMap
.
get
(
attrName
);
...
...
@@ -166,6 +178,9 @@ class MBeanAnalyzer<M> {
}
am
.
setter
=
cm
;
attrMap
.
put
(
attrName
,
am
);
}
else
if
(
managedAttr
)
{
throw
new
NotCompliantMBeanException
(
"Method "
+
name
+
" has @ManagedAttribute but is not a valid getter or setter"
);
}
else
{
// It's an operation
List
<
M
>
cms
=
opMap
.
get
(
name
);
...
...
src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
com.sun.jmx.mbeanserver
;
import
java.lang.ref.WeakReference
;
import
java.security.PrivilegedAction
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
import
javax.annotation.Resource
;
import
javax.management.MBeanServer
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.ObjectName
;
import
static
com
.
sun
.
jmx
.
mbeanserver
.
Util
.
newMap
;
import
java.lang.reflect.AccessibleObject
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.security.AccessController
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
javax.management.SendNotification
;
public
class
MBeanInjector
{
private
static
Class
<?>[]
injectedClasses
=
{
MBeanServer
.
class
,
ObjectName
.
class
,
SendNotification
.
class
,
};
public
static
void
inject
(
Object
mbean
,
MBeanServer
mbs
,
ObjectName
name
)
throws
Exception
{
ClassInjector
injector
=
injectorForClass
(
mbean
.
getClass
());
injector
.
inject
(
mbean
,
MBeanServer
.
class
,
mbs
);
injector
.
inject
(
mbean
,
ObjectName
.
class
,
name
);
}
public
static
boolean
injectsSendNotification
(
Object
mbean
)
throws
NotCompliantMBeanException
{
ClassInjector
injector
=
injectorForClass
(
mbean
.
getClass
());
return
injector
.
injects
(
SendNotification
.
class
);
}
public
static
void
injectSendNotification
(
Object
mbean
,
SendNotification
sn
)
throws
Exception
{
ClassInjector
injector
=
injectorForClass
(
mbean
.
getClass
());
injector
.
inject
(
mbean
,
SendNotification
.
class
,
sn
);
}
public
static
void
validate
(
Class
<?>
c
)
throws
NotCompliantMBeanException
{
injectorForClass
(
c
);
}
private
static
class
ClassInjector
{
private
Map
<
Class
<?>,
List
<
Field
>>
fields
;
private
Map
<
Class
<?>,
List
<
Method
>>
methods
;
ClassInjector
(
Class
<?>
c
)
throws
NotCompliantMBeanException
{
fields
=
newMap
();
methods
=
newMap
();
Class
<?>
sup
=
c
.
getSuperclass
();
ClassInjector
supInjector
;
if
(
sup
==
null
)
{
supInjector
=
null
;
}
else
{
supInjector
=
injectorForClass
(
sup
);
fields
.
putAll
(
supInjector
.
fields
);
methods
.
putAll
(
supInjector
.
methods
);
}
addMembers
(
c
);
eliminateOverriddenMethods
();
// If we haven't added any new fields or methods to what we
// inherited, then we can share the parent's maps.
if
(
supInjector
!=
null
)
{
if
(
fields
.
equals
(
supInjector
.
fields
))
fields
=
supInjector
.
fields
;
if
(
methods
.
equals
(
supInjector
.
methods
))
methods
=
supInjector
.
methods
;
}
}
boolean
injects
(
Class
<?>
c
)
{
return
(
fields
.
get
(
c
)
!=
null
||
methods
.
get
(
c
)
!=
null
);
}
<
T
>
void
inject
(
Object
instance
,
Class
<
T
>
type
,
T
resource
)
throws
Exception
{
List
<
Field
>
fs
=
fields
.
get
(
type
);
if
(
fs
!=
null
)
{
for
(
Field
f
:
fs
)
f
.
set
(
instance
,
resource
);
}
List
<
Method
>
ms
=
methods
.
get
(
type
);
if
(
ms
!=
null
)
{
for
(
Method
m
:
ms
)
{
try
{
m
.
invoke
(
instance
,
resource
);
}
catch
(
InvocationTargetException
e
)
{
Throwable
cause
=
e
.
getCause
();
if
(
cause
instanceof
Error
)
throw
(
Error
)
cause
;
else
throw
(
Exception
)
cause
;
}
}
}
}
private
void
eliminateOverriddenMethods
()
{
/* Covariant overriding is unlikely, but it is possible that the
* parent has a @Resource method that we override with another
* @Resource method. We don't want to invoke both methods,
* because polymorphism means we would actually invoke the same
* method twice.
*/
for
(
Map
.
Entry
<
Class
<?>,
List
<
Method
>>
entry
:
methods
.
entrySet
())
{
List
<
Method
>
list
=
entry
.
getValue
();
list
=
MBeanAnalyzer
.
eliminateCovariantMethods
(
list
);
entry
.
setValue
(
list
);
}
}
/*
* Find Fields or Methods within the given Class that we can inject
* resource references into. Suppose we want to know if a Field can get
* a reference to an ObjectName. We'll accept fields like this:
*
* @Resource
* private transient ObjectName name;
*
* or like this:
*
* @Resource(type = ObjectName.class)
* private transient Object name;
*
* but not like this:
*
* @Resource
* private transient Object name;
*
* (Plain @Resource is equivalent to @Resource(type = Object.class).)
*
* We don't want to inject into everything that might possibly accept
* an ObjectName reference, because examples like the last one above
* could also accept an MBeanServer reference or any other sort of
* reference.
*
* So we accept a Field if it has a @Resource annotation and either
* (a) its type is ObjectName or a subclass and its @Resource type is
* compatible with ObjectName (e.g. it is Object); or
* (b) its type is compatible with ObjectName and its @Resource type
* is exactly ObjectName. Fields that meet these criteria will not
* meet the same criteria with respect to other types such as MBeanServer.
*
* The same logic applies mutatis mutandis to Methods such as this:
*
* @Resource
* private void setObjectName1(ObjectName name)
* @Resource(type = Object.class)
* private void setObjectName2(Object name)
*/
private
void
addMembers
(
final
Class
<?>
c
)
throws
NotCompliantMBeanException
{
AccessibleObject
[][]
memberArrays
=
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
AccessibleObject
[][]>()
{
public
AccessibleObject
[][]
run
()
{
return
new
AccessibleObject
[][]
{
c
.
getDeclaredFields
(),
c
.
getDeclaredMethods
()
};
}
});
for
(
AccessibleObject
[]
members
:
memberArrays
)
{
for
(
final
AccessibleObject
member
:
members
)
{
Resource
res
=
member
.
getAnnotation
(
Resource
.
class
);
if
(
res
==
null
)
continue
;
final
Field
field
;
final
Method
method
;
final
Class
<?>
memberType
;
final
int
modifiers
;
if
(
member
instanceof
Field
)
{
field
=
(
Field
)
member
;
memberType
=
field
.
getType
();
modifiers
=
field
.
getModifiers
();
method
=
null
;
}
else
{
field
=
null
;
method
=
(
Method
)
member
;
Class
<?>[]
paramTypes
=
method
.
getParameterTypes
();
if
(
paramTypes
.
length
!=
1
)
{
throw
new
NotCompliantMBeanException
(
"@Resource method must have exactly 1 "
+
"parameter: "
+
method
);
}
if
(
method
.
getReturnType
()
!=
void
.
class
)
{
throw
new
NotCompliantMBeanException
(
"@Resource method must return void: "
+
method
);
}
memberType
=
paramTypes
[
0
];
modifiers
=
method
.
getModifiers
();
}
if
(
Modifier
.
isStatic
(
modifiers
))
{
throw
new
NotCompliantMBeanException
(
"@Resource method or field cannot be static: "
+
member
);
}
for
(
Class
<?>
injectedClass
:
injectedClasses
)
{
Class
<?>[]
types
=
{
memberType
,
res
.
type
()};
boolean
accept
=
false
;
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
if
(
types
[
i
]
==
injectedClass
&&
types
[
1
-
i
].
isAssignableFrom
(
injectedClass
))
{
accept
=
true
;
break
;
}
}
if
(
accept
)
{
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
member
.
setAccessible
(
true
);
return
null
;
}
});
addToMap
(
fields
,
injectedClass
,
field
);
addToMap
(
methods
,
injectedClass
,
method
);
}
}
}
}
}
private
static
<
K
,
V
>
void
addToMap
(
Map
<
K
,
List
<
V
>>
map
,
K
key
,
V
value
)
{
if
(
value
==
null
)
return
;
List
<
V
>
list
=
map
.
get
(
key
);
if
(
list
==
null
)
list
=
Collections
.
singletonList
(
value
);
else
{
if
(
list
.
size
()
==
1
)
list
=
new
ArrayList
<
V
>(
list
);
list
.
add
(
value
);
}
map
.
put
(
key
,
list
);
}
}
private
static
synchronized
ClassInjector
injectorForClass
(
Class
<?>
c
)
throws
NotCompliantMBeanException
{
WeakReference
<
ClassInjector
>
wr
=
injectorMap
.
get
(
c
);
ClassInjector
ci
=
(
wr
==
null
)
?
null
:
wr
.
get
();
if
(
ci
==
null
)
{
ci
=
new
ClassInjector
(
c
);
injectorMap
.
put
(
c
,
new
WeakReference
<
ClassInjector
>(
ci
));
}
return
ci
;
}
private
static
Map
<
Class
<?>,
WeakReference
<
ClassInjector
>>
injectorMap
=
new
WeakHashMap
<
Class
<?>,
WeakReference
<
ClassInjector
>>();
}
src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java
浏览文件 @
a311994c
...
...
@@ -36,20 +36,28 @@ import java.lang.reflect.Method;
import
java.lang.reflect.Type
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
import
javax.management.Description
;
import
javax.management.Descriptor
;
import
javax.management.ImmutableDescriptor
;
import
javax.management.IntrospectionException
;
import
javax.management.InvalidAttributeValueException
;
import
javax.management.MBean
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanConstructorInfo
;
import
javax.management.MBeanException
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MXBean
;
import
javax.management.ManagedAttribute
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.NotificationBroadcaster
;
import
javax.management.NotificationInfo
;
import
javax.management.NotificationInfos
;
import
javax.management.ReflectionException
;
/**
...
...
@@ -153,6 +161,25 @@ abstract class MBeanIntrospector<M> {
abstract
MBeanAttributeInfo
getMBeanAttributeInfo
(
String
attributeName
,
M
getter
,
M
setter
)
throws
IntrospectionException
;
final
String
getAttributeDescription
(
String
attributeName
,
String
defaultDescription
,
Method
getter
,
Method
setter
)
throws
IntrospectionException
{
String
g
=
Introspector
.
descriptionForElement
(
getter
);
String
s
=
Introspector
.
descriptionForElement
(
setter
);
if
(
g
==
null
)
{
if
(
s
==
null
)
return
defaultDescription
;
else
return
s
;
}
else
if
(
s
==
null
||
g
.
equals
(
s
))
{
return
g
;
}
else
{
throw
new
IntrospectionException
(
"Inconsistent @Description on getter and setter for "
+
"attribute "
+
attributeName
);
}
}
/**
* Construct an MBeanOperationInfo for the given operation based on
* the M it was derived from.
...
...
@@ -184,8 +211,12 @@ abstract class MBeanIntrospector<M> {
}
void
checkCompliance
(
Class
<?>
mbeanType
)
throws
NotCompliantMBeanException
{
if
(!
mbeanType
.
isInterface
())
{
throw
new
NotCompliantMBeanException
(
"Not an interface: "
+
if
(!
mbeanType
.
isInterface
()
&&
!
mbeanType
.
isAnnotationPresent
(
MBean
.
class
)
&&
!
Introspector
.
hasMXBeanAnnotation
(
mbeanType
))
{
throw
new
NotCompliantMBeanException
(
"Not an interface and "
+
"does not have @"
+
MBean
.
class
.
getSimpleName
()
+
" or @"
+
MXBean
.
class
.
getSimpleName
()
+
" annotation: "
+
mbeanType
.
getName
());
}
}
...
...
@@ -194,7 +225,12 @@ abstract class MBeanIntrospector<M> {
* Get the methods to be analyzed to build the MBean interface.
*/
List
<
Method
>
getMethods
(
final
Class
<?>
mbeanType
)
throws
Exception
{
return
Arrays
.
asList
(
mbeanType
.
getMethods
());
if
(
mbeanType
.
isInterface
())
return
Arrays
.
asList
(
mbeanType
.
getMethods
());
final
List
<
Method
>
methods
=
newList
();
getAnnotatedMethods
(
mbeanType
,
methods
);
return
methods
;
}
final
PerInterface
<
M
>
getPerInterface
(
Class
<?>
mbeanInterface
)
...
...
@@ -232,8 +268,11 @@ abstract class MBeanIntrospector<M> {
MBeanAnalyzer
<
M
>
analyzer
)
throws
IntrospectionException
{
final
MBeanInfoMaker
maker
=
new
MBeanInfoMaker
();
analyzer
.
visit
(
maker
);
final
String
description
=
final
String
de
faultDe
scription
=
"Information on the management interface of the MBean"
;
String
description
=
Introspector
.
descriptionForElement
(
mbeanInterface
);
if
(
description
==
null
)
description
=
defaultDescription
;
return
maker
.
makeMBeanInfo
(
mbeanInterface
,
description
);
}
...
...
@@ -407,7 +446,15 @@ abstract class MBeanIntrospector<M> {
throws
NotCompliantMBeanException
{
MBeanInfo
mbi
=
getClassMBeanInfo
(
resource
.
getClass
(),
perInterface
);
MBeanNotificationInfo
[]
notifs
=
findNotifications
(
resource
);
MBeanNotificationInfo
[]
notifs
;
try
{
notifs
=
findNotifications
(
resource
);
}
catch
(
RuntimeException
e
)
{
NotCompliantMBeanException
x
=
new
NotCompliantMBeanException
(
e
.
getMessage
());
x
.
initCause
(
e
);
throw
x
;
}
Descriptor
d
=
getSpecificMBeanDescriptor
();
boolean
anyNotifs
=
(
notifs
!=
null
&&
notifs
.
length
>
0
);
if
(!
anyNotifs
&&
ImmutableDescriptor
.
EMPTY_DESCRIPTOR
.
equals
(
d
))
...
...
@@ -460,13 +507,43 @@ abstract class MBeanIntrospector<M> {
}
}
/*
* Add to "methods" every public method that has the @ManagedAttribute
* or @ManagedOperation annotation, in the given class or any of
* its superclasses or superinterfaces.
*
* We always add superclass or superinterface methods first, so that
* the stable sort used by eliminateCovariantMethods will put the
* method from the most-derived class last. This means that we will
* see the version of the @ManagedAttribute (or ...Operation) annotation
* from that method, which might have a different description or whatever.
*/
private
static
void
getAnnotatedMethods
(
Class
<?>
c
,
List
<
Method
>
methods
)
throws
Exception
{
Class
<?>
sup
=
c
.
getSuperclass
();
if
(
sup
!=
null
)
getAnnotatedMethods
(
sup
,
methods
);
Class
<?>[]
intfs
=
c
.
getInterfaces
();
for
(
Class
<?>
intf
:
intfs
)
getAnnotatedMethods
(
intf
,
methods
);
for
(
Method
m
:
c
.
getMethods
())
{
// We are careful not to add m if it is inherited from a parent
// class or interface, because duplicate methods lead to nasty
// behaviour in eliminateCovariantMethods.
if
(
m
.
getDeclaringClass
()
==
c
&&
(
m
.
isAnnotationPresent
(
ManagedAttribute
.
class
)
||
m
.
isAnnotationPresent
(
ManagedOperation
.
class
)))
methods
.
add
(
m
);
}
}
static
MBeanNotificationInfo
[]
findNotifications
(
Object
moi
)
{
if
(!(
moi
instanceof
NotificationBroadcaster
))
return
null
;
MBeanNotificationInfo
[]
mbn
=
((
NotificationBroadcaster
)
moi
).
getNotificationInfo
();
if
(
mbn
==
null
||
mbn
.
length
==
0
)
return
null
;
return
findNotificationsFromAnnotations
(
moi
.
getClass
())
;
MBeanNotificationInfo
[]
result
=
new
MBeanNotificationInfo
[
mbn
.
length
];
for
(
int
i
=
0
;
i
<
mbn
.
length
;
i
++)
{
...
...
@@ -478,11 +555,81 @@ abstract class MBeanIntrospector<M> {
return
result
;
}
private
static
MBeanNotificationInfo
[]
findNotificationsFromAnnotations
(
Class
<?>
mbeanClass
)
{
Class
<?>
c
=
getAnnotatedNotificationInfoClass
(
mbeanClass
);
if
(
c
==
null
)
return
null
;
NotificationInfo
ni
=
c
.
getAnnotation
(
NotificationInfo
.
class
);
NotificationInfos
nis
=
c
.
getAnnotation
(
NotificationInfos
.
class
);
List
<
NotificationInfo
>
list
=
newList
();
if
(
ni
!=
null
)
list
.
add
(
ni
);
if
(
nis
!=
null
)
list
.
addAll
(
Arrays
.
asList
(
nis
.
value
()));
if
(
list
.
isEmpty
())
return
null
;
List
<
MBeanNotificationInfo
>
mbnis
=
newList
();
for
(
NotificationInfo
x
:
list
)
{
// The Descriptor includes any fields explicitly specified by
// x.descriptorFields(), plus any fields from the contained
// @Description annotation.
Descriptor
d
=
new
ImmutableDescriptor
(
x
.
descriptorFields
());
d
=
ImmutableDescriptor
.
union
(
d
,
Introspector
.
descriptorForAnnotation
(
x
.
description
()));
MBeanNotificationInfo
mbni
=
new
MBeanNotificationInfo
(
x
.
types
(),
x
.
notificationClass
().
getName
(),
x
.
description
().
value
(),
d
);
mbnis
.
add
(
mbni
);
}
return
mbnis
.
toArray
(
new
MBeanNotificationInfo
[
mbnis
.
size
()]);
}
private
static
final
Map
<
Class
<?>,
WeakReference
<
Class
<?>>>
annotatedNotificationInfoClasses
=
newWeakHashMap
();
private
static
Class
<?>
getAnnotatedNotificationInfoClass
(
Class
<?>
baseClass
)
{
synchronized
(
annotatedNotificationInfoClasses
)
{
WeakReference
<
Class
<?>>
wr
=
annotatedNotificationInfoClasses
.
get
(
baseClass
);
if
(
wr
!=
null
)
return
wr
.
get
();
Class
<?>
c
=
null
;
if
(
baseClass
.
isAnnotationPresent
(
NotificationInfo
.
class
)
||
baseClass
.
isAnnotationPresent
(
NotificationInfos
.
class
))
{
c
=
baseClass
;
}
else
{
Class
<?>[]
intfs
=
baseClass
.
getInterfaces
();
for
(
Class
<?>
intf
:
intfs
)
{
Class
<?>
c1
=
getAnnotatedNotificationInfoClass
(
intf
);
if
(
c1
!=
null
)
{
if
(
c
!=
null
)
{
throw
new
IllegalArgumentException
(
"Class "
+
baseClass
.
getName
()
+
" inherits "
+
"@NotificationInfo(s) from both "
+
c
.
getName
()
+
" and "
+
c1
.
getName
());
}
c
=
c1
;
}
}
}
// Record the result of the search. If no @NotificationInfo(s)
// were found, c is null, and we store a WeakReference(null).
// This prevents us from having to search again and fail again.
annotatedNotificationInfoClasses
.
put
(
baseClass
,
new
WeakReference
<
Class
<?>>(
c
));
return
c
;
}
}
private
static
MBeanConstructorInfo
[]
findConstructors
(
Class
<?>
c
)
{
Constructor
[]
cons
=
c
.
getConstructors
();
MBeanConstructorInfo
[]
mbc
=
new
MBeanConstructorInfo
[
cons
.
length
];
for
(
int
i
=
0
;
i
<
cons
.
length
;
i
++)
{
final
String
descr
=
"Public constructor of the MBean"
;
String
descr
=
"Public constructor of the MBean"
;
Description
d
=
cons
[
i
].
getAnnotation
(
Description
.
class
);
if
(
d
!=
null
)
descr
=
d
.
value
();
mbc
[
i
]
=
new
MBeanConstructorInfo
(
descr
,
cons
[
i
]);
}
return
mbc
;
...
...
src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java
浏览文件 @
a311994c
...
...
@@ -263,10 +263,14 @@ public abstract class MBeanSupport<M>
return
resource
.
getClass
().
getName
();
}
public
final
Object
get
Resource
()
{
public
final
Object
get
WrappedObject
()
{
return
resource
;
}
public
final
ClassLoader
getWrappedClassLoader
()
{
return
resource
.
getClass
().
getClassLoader
();
}
public
final
Class
<?>
getMBeanInterface
()
{
return
perInterface
.
getMBeanInterface
();
}
...
...
src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
浏览文件 @
a311994c
...
...
@@ -35,6 +35,7 @@ import java.lang.reflect.Method;
import
java.lang.reflect.Type
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
import
javax.management.Description
;
import
javax.management.Descriptor
;
import
javax.management.ImmutableDescriptor
;
import
javax.management.IntrospectionException
;
...
...
@@ -43,6 +44,7 @@ import javax.management.MBeanAttributeInfo;
import
javax.management.MBeanException
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MBeanParameterInfo
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
javax.management.openmbean.OpenMBeanAttributeInfoSupport
;
...
...
@@ -180,7 +182,10 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
final
boolean
isWritable
=
(
setter
!=
null
);
final
boolean
isIs
=
isReadable
&&
getName
(
getter
).
startsWith
(
"is"
);
final
String
description
=
attributeName
;
final
String
description
=
getAttributeDescription
(
attributeName
,
attributeName
,
getter
==
null
?
null
:
getter
.
getMethod
(),
setter
==
null
?
null
:
setter
.
getMethod
());
final
OpenType
<?>
openType
;
final
Type
originalType
;
...
...
@@ -229,13 +234,17 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
MBeanOperationInfo
getMBeanOperationInfo
(
String
operationName
,
ConvertingMethod
operation
)
{
final
Method
method
=
operation
.
getMethod
();
final
String
description
=
operationName
;
String
description
=
operationName
;
/* Ideally this would be an empty string, but
OMBOperationInfo constructor forbids that. Also, we
could consult an annotation to get a useful
description. */
OMBOperationInfo constructor forbids that. */
Description
d
=
method
.
getAnnotation
(
Description
.
class
);
if
(
d
!=
null
)
description
=
d
.
value
();
final
int
impact
=
MBeanOperationInfo
.
UNKNOWN
;
int
impact
=
MBeanOperationInfo
.
UNKNOWN
;
ManagedOperation
annot
=
method
.
getAnnotation
(
ManagedOperation
.
class
);
if
(
annot
!=
null
)
impact
=
annot
.
impact
().
getCode
();
final
OpenType
<?>
returnType
=
operation
.
getOpenReturnType
();
final
Type
originalReturnType
=
operation
.
getGenericReturnType
();
...
...
@@ -247,8 +256,15 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
boolean
openParameterTypes
=
true
;
Annotation
[][]
annots
=
method
.
getParameterAnnotations
();
for
(
int
i
=
0
;
i
<
paramTypes
.
length
;
i
++)
{
final
String
paramName
=
"p"
+
i
;
final
String
paramDescription
=
paramName
;
String
paramName
=
Introspector
.
nameForParameter
(
annots
[
i
]);
if
(
paramName
==
null
)
paramName
=
"p"
+
i
;
String
paramDescription
=
Introspector
.
descriptionForParameter
(
annots
[
i
]);
if
(
paramDescription
==
null
)
paramDescription
=
paramName
;
final
OpenType
<?>
openType
=
paramTypes
[
i
];
final
Type
originalType
=
originalParamTypes
[
i
];
Descriptor
descriptor
=
...
...
src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java
浏览文件 @
a311994c
...
...
@@ -161,7 +161,7 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
synchronized
(
lock
)
{
this
.
mxbeanLookup
=
MXBeanLookup
.
Plain
.
lookupFor
(
server
);
this
.
mxbeanLookup
.
addReference
(
name
,
get
Resource
());
this
.
mxbeanLookup
.
addReference
(
name
,
get
WrappedObject
());
this
.
objectName
=
name
;
}
}
...
...
@@ -170,7 +170,7 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
public
void
unregister
()
{
synchronized
(
lock
)
{
if
(
mxbeanLookup
!=
null
)
{
if
(
mxbeanLookup
.
removeReference
(
objectName
,
get
Resource
()))
if
(
mxbeanLookup
.
removeReference
(
objectName
,
get
WrappedObject
()))
objectName
=
null
;
}
// XXX: need to revisit the whole register/unregister logic in
...
...
src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
com.sun.jmx.mbeanserver
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
import
javax.management.AttributeNotFoundException
;
import
javax.management.DynamicMBean
;
import
javax.management.DynamicWrapperMBean
;
import
javax.management.InvalidAttributeValueException
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanException
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanServer
;
import
javax.management.NotificationBroadcasterSupport
;
import
javax.management.NotificationEmitter
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectName
;
import
javax.management.ReflectionException
;
/**
* Create wrappers for DynamicMBean that implement NotificationEmitter
* and SendNotification.
*/
public
class
NotifySupport
implements
DynamicMBean2
,
NotificationEmitter
,
MBeanRegistration
{
private
final
DynamicMBean
mbean
;
private
final
NotificationBroadcasterSupport
nbs
;
public
static
DynamicMBean
wrap
(
DynamicMBean
mbean
,
NotificationBroadcasterSupport
nbs
)
{
return
new
NotifySupport
(
mbean
,
nbs
);
}
private
NotifySupport
(
DynamicMBean
mbean
,
NotificationBroadcasterSupport
nbs
)
{
this
.
mbean
=
mbean
;
this
.
nbs
=
nbs
;
}
public
static
NotificationBroadcasterSupport
getNB
(
DynamicMBean
mbean
)
{
if
(
mbean
instanceof
NotifySupport
)
return
((
NotifySupport
)
mbean
).
nbs
;
else
return
null
;
}
public
String
getClassName
()
{
if
(
mbean
instanceof
DynamicMBean2
)
return
((
DynamicMBean2
)
mbean
).
getClassName
();
Object
w
=
mbean
;
if
(
w
instanceof
DynamicWrapperMBean
)
w
=
((
DynamicWrapperMBean
)
w
).
getWrappedObject
();
return
w
.
getClass
().
getName
();
}
public
void
preRegister2
(
MBeanServer
mbs
,
ObjectName
name
)
throws
Exception
{
if
(
mbean
instanceof
DynamicMBean2
)
((
DynamicMBean2
)
mbean
).
preRegister2
(
mbs
,
name
);
}
public
void
registerFailed
()
{
if
(
mbean
instanceof
DynamicMBean2
)
((
DynamicMBean2
)
mbean
).
registerFailed
();
}
public
Object
getWrappedObject
()
{
if
(
mbean
instanceof
DynamicWrapperMBean
)
return
((
DynamicWrapperMBean
)
mbean
).
getWrappedObject
();
else
return
mbean
;
}
public
ClassLoader
getWrappedClassLoader
()
{
if
(
mbean
instanceof
DynamicWrapperMBean
)
return
((
DynamicWrapperMBean
)
mbean
).
getWrappedClassLoader
();
else
return
mbean
.
getClass
().
getClassLoader
();
}
public
Object
getAttribute
(
String
attribute
)
throws
AttributeNotFoundException
,
MBeanException
,
ReflectionException
{
return
mbean
.
getAttribute
(
attribute
);
}
public
void
setAttribute
(
Attribute
attribute
)
throws
AttributeNotFoundException
,
InvalidAttributeValueException
,
MBeanException
,
ReflectionException
{
mbean
.
setAttribute
(
attribute
);
}
public
AttributeList
setAttributes
(
AttributeList
attributes
)
{
return
mbean
.
setAttributes
(
attributes
);
}
public
Object
invoke
(
String
actionName
,
Object
[]
params
,
String
[]
signature
)
throws
MBeanException
,
ReflectionException
{
return
mbean
.
invoke
(
actionName
,
params
,
signature
);
}
public
MBeanInfo
getMBeanInfo
()
{
return
mbean
.
getMBeanInfo
();
}
public
AttributeList
getAttributes
(
String
[]
attributes
)
{
return
mbean
.
getAttributes
(
attributes
);
}
public
void
removeNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
throws
ListenerNotFoundException
{
nbs
.
removeNotificationListener
(
listener
,
filter
,
handback
);
}
public
void
removeNotificationListener
(
NotificationListener
listener
)
throws
ListenerNotFoundException
{
nbs
.
removeNotificationListener
(
listener
);
}
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
return
nbs
.
getNotificationInfo
();
}
public
void
addNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
{
nbs
.
addNotificationListener
(
listener
,
filter
,
handback
);
}
public
ObjectName
preRegister
(
MBeanServer
server
,
ObjectName
name
)
throws
Exception
{
if
(
mbr
()
!=
null
)
return
mbr
().
preRegister
(
server
,
name
);
else
return
name
;
}
public
void
postRegister
(
Boolean
registrationDone
)
{
if
(
mbr
()
!=
null
)
mbr
().
postRegister
(
registrationDone
);
}
public
void
preDeregister
()
throws
Exception
{
if
(
mbr
()
!=
null
)
mbr
().
preDeregister
();
}
public
void
postDeregister
()
{
if
(
mbr
()
!=
null
)
mbr
().
postDeregister
();
}
private
MBeanRegistration
mbr
()
{
if
(
mbean
instanceof
MBeanRegistration
)
return
(
MBeanRegistration
)
mbean
;
else
return
null
;
}
}
src/share/classes/com/sun/jmx/mbeanserver/Repository.java
浏览文件 @
a311994c
...
...
@@ -29,6 +29,7 @@ import com.sun.jmx.defaults.ServiceName;
import
static
com
.
sun
.
jmx
.
defaults
.
JmxProperties
.
MBEANSERVER_LOGGER
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
...
...
@@ -39,7 +40,6 @@ import java.util.Set;
import
javax.management.DynamicMBean
;
import
javax.management.InstanceAlreadyExistsException
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.ObjectName
;
import
javax.management.QueryExp
;
import
javax.management.RuntimeOperationsException
;
...
...
@@ -52,6 +52,27 @@ import javax.management.RuntimeOperationsException;
*/
public
class
Repository
{
/**
* An interface that allows the caller to get some control
* over the registration.
* @see #addMBean
* @see #remove
*/
public
interface
RegistrationContext
{
/**
* Called by {@link #addMBean}.
* Can throw a RuntimeOperationsException to cancel the
* registration.
*/
public
void
registering
();
/**
* Called by {@link #remove}.
* Any exception thrown by this method will be ignored.
*/
public
void
unregistered
();
}
// Private fields -------------------------------------------->
/**
...
...
@@ -115,7 +136,6 @@ public class Repository {
/**
* Builds a new ObjectNamePattern object from an ObjectName pattern
* constituents.
* @param domain pattern.getDomain().
* @param propertyListPattern pattern.isPropertyListPattern().
* @param propertyValuePattern pattern.isPropertyValuePattern().
* @param canonicalProps pattern.getCanonicalKeyPropertyListString().
...
...
@@ -216,16 +236,6 @@ public class Repository {
}
}
private
void
addNewDomMoi
(
final
DynamicMBean
object
,
final
String
dom
,
final
ObjectName
name
)
{
final
Map
<
String
,
NamedObject
>
moiTb
=
new
HashMap
<
String
,
NamedObject
>();
moiTb
.
put
(
name
.
getCanonicalKeyPropertyListString
(),
new
NamedObject
(
name
,
object
));
domainTb
.
put
(
dom
,
moiTb
);
nbElements
++;
}
/** Match a string against a shell-style pattern. The only pattern
characters recognised are <code>?</code>, standing for any one
character, and <code>*</code>, standing for any string of
...
...
@@ -306,6 +316,50 @@ public class Repository {
}
}
private
void
addNewDomMoi
(
final
DynamicMBean
object
,
final
String
dom
,
final
ObjectName
name
,
final
RegistrationContext
context
)
{
final
Map
<
String
,
NamedObject
>
moiTb
=
new
HashMap
<
String
,
NamedObject
>();
final
String
key
=
name
.
getCanonicalKeyPropertyListString
();
addMoiToTb
(
object
,
name
,
key
,
moiTb
,
context
);
domainTb
.
put
(
dom
,
moiTb
);
nbElements
++;
}
private
void
registering
(
RegistrationContext
context
)
{
if
(
context
==
null
)
return
;
try
{
context
.
registering
();
}
catch
(
RuntimeOperationsException
x
)
{
throw
x
;
}
catch
(
RuntimeException
x
)
{
throw
new
RuntimeOperationsException
(
x
);
}
}
private
void
unregistering
(
RegistrationContext
context
,
ObjectName
name
)
{
if
(
context
==
null
)
return
;
try
{
context
.
unregistered
();
}
catch
(
Exception
x
)
{
// shouldn't come here...
MBEANSERVER_LOGGER
.
log
(
Level
.
FINE
,
"Unexpected exception while unregistering "
+
name
,
x
);
}
}
private
void
addMoiToTb
(
final
DynamicMBean
object
,
final
ObjectName
name
,
final
String
key
,
final
Map
<
String
,
NamedObject
>
moiTb
,
final
RegistrationContext
context
)
{
registering
(
context
);
moiTb
.
put
(
key
,
new
NamedObject
(
name
,
object
));
}
/**
* Retrieves the named object contained in repository
* from the given objectname.
...
...
@@ -355,12 +409,12 @@ public class Repository {
domainTb
=
new
HashMap
<
String
,
Map
<
String
,
NamedObject
>>(
5
);
if
(
domain
!=
null
&&
domain
.
length
()
!=
0
)
this
.
domain
=
domain
;
this
.
domain
=
domain
.
intern
();
// we use == domain later on...
else
this
.
domain
=
ServiceName
.
DOMAIN
;
// Creates a
n new has
table for the default domain
domainTb
.
put
(
this
.
domain
.
intern
()
,
new
HashMap
<
String
,
NamedObject
>());
// Creates a
new hash
table for the default domain
domainTb
.
put
(
this
.
domain
,
new
HashMap
<
String
,
NamedObject
>());
}
/**
...
...
@@ -395,10 +449,21 @@ public class Repository {
/**
* Stores an MBean associated with its object name in the repository.
*
* @param object MBean to be stored in the repository.
* @param name MBean object name.
* @param object MBean to be stored in the repository.
* @param name MBean object name.
* @param context A registration context. If non null, the repository
* will call {@link RegistrationContext#registering()
* context.registering()} from within the repository
* lock, when it has determined that the {@code object}
* can be stored in the repository with that {@code name}.
* If {@link RegistrationContext#registering()
* context.registering()} throws an exception, the
* operation is abandonned, the MBean is not added to the
* repository, and a {@link RuntimeOperationsException}
* is thrown.
*/
public
void
addMBean
(
final
DynamicMBean
object
,
ObjectName
name
)
public
void
addMBean
(
final
DynamicMBean
object
,
ObjectName
name
,
final
RegistrationContext
context
)
throws
InstanceAlreadyExistsException
{
if
(
MBEANSERVER_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
...
...
@@ -431,7 +496,7 @@ public class Repository {
lock
.
writeLock
().
lock
();
try
{
// Domain cannot be JMImplementation if entry does not exist
s
// Domain cannot be JMImplementation if entry does not exist
if
(
!
to_default_domain
&&
dom
.
equals
(
"JMImplementation"
)
&&
domainTb
.
containsKey
(
"JMImplementation"
))
{
...
...
@@ -440,21 +505,21 @@ public class Repository {
"Repository: domain name cannot be JMImplementation"
));
}
// If domain
not already exists
, add it to the hash table
// If domain
does not already exist
, add it to the hash table
final
Map
<
String
,
NamedObject
>
moiTb
=
domainTb
.
get
(
dom
);
if
(
moiTb
==
null
)
{
addNewDomMoi
(
object
,
dom
,
name
);
addNewDomMoi
(
object
,
dom
,
name
,
context
);
return
;
}
// Add instance if not already present
String
cstr
=
name
.
getCanonicalKeyPropertyListString
();
NamedObject
elmt
=
moiTb
.
get
(
cstr
);
if
(
elmt
!=
null
)
{
throw
new
InstanceAlreadyExistsException
(
name
.
toString
());
}
else
{
nbElements
++;
moiTb
.
put
(
cstr
,
new
NamedObject
(
name
,
object
));
// Add instance if not already present
String
cstr
=
name
.
getCanonicalKeyPropertyListString
();
NamedObject
elmt
=
moiTb
.
get
(
cstr
);
if
(
elmt
!=
null
)
{
throw
new
InstanceAlreadyExistsException
(
name
.
toString
());
}
else
{
nbElements
++;
addMoiToTb
(
object
,
name
,
cstr
,
moiTb
,
context
);
}
}
}
finally
{
...
...
@@ -533,7 +598,7 @@ public class Repository {
// ":*", ":[key=value],*" : names in defaultDomain
// "domain:*", "domain:[key=value],*" : names in the specified domain
// Surely one of the most frequent case ... query on the whole world
// Surely one of the most frequent case
s
... query on the whole world
ObjectName
name
;
if
(
pattern
==
null
||
pattern
.
getCanonicalName
().
length
()
==
0
||
...
...
@@ -546,8 +611,7 @@ public class Repository {
// If pattern is not a pattern, retrieve this mbean !
if
(!
name
.
isPattern
())
{
final
NamedObject
no
;
no
=
retrieveNamedObject
(
name
);
final
NamedObject
no
=
retrieveNamedObject
(
name
);
if
(
no
!=
null
)
result
.
add
(
no
);
return
result
;
}
...
...
@@ -577,12 +641,22 @@ public class Repository {
return
result
;
}
if
(!
name
.
isDomainPattern
())
{
final
Map
<
String
,
NamedObject
>
moiTb
=
domainTb
.
get
(
name
.
getDomain
());
if
(
moiTb
==
null
)
return
Collections
.
emptySet
();
if
(
allNames
)
result
.
addAll
(
moiTb
.
values
());
else
addAllMatching
(
moiTb
,
result
,
namePattern
);
return
result
;
}
// Pattern matching in the domain name (*, ?)
char
[]
dom2Match
=
name
.
getDomain
().
toCharArray
();
for
(
String
dom
ain
:
domainTb
.
keySet
())
{
char
[]
theDom
=
dom
ain
.
toCharArray
();
for
(
String
dom
:
domainTb
.
keySet
())
{
char
[]
theDom
=
dom
.
toCharArray
();
if
(
wildmatch
(
theDom
,
dom2Match
))
{
final
Map
<
String
,
NamedObject
>
moiTb
=
domainTb
.
get
(
dom
ain
);
final
Map
<
String
,
NamedObject
>
moiTb
=
domainTb
.
get
(
dom
);
if
(
allNames
)
result
.
addAll
(
moiTb
.
values
());
else
...
...
@@ -599,11 +673,21 @@ public class Repository {
* Removes an MBean from the repository.
*
* @param name name of the MBean to remove.
* @param context A registration context. If non null, the repository
* will call {@link RegistrationContext#unregistered()
* context.unregistered()} from within the repository
* lock, just after the mbean associated with
* {@code name} is removed from the repository.
* If {@link RegistrationContext#unregistered()
* context.unregistered()} is not expected to throw any
* exception. If it does, the exception is logged
* and swallowed.
*
* @exception InstanceNotFoundException The MBean does not exist in
* the repository.
*/
public
void
remove
(
final
ObjectName
name
)
public
void
remove
(
final
ObjectName
name
,
final
RegistrationContext
context
)
throws
InstanceNotFoundException
{
// Debugging stuff
...
...
@@ -645,6 +729,9 @@ public class Repository {
if
(
dom
==
domain
)
domainTb
.
put
(
domain
,
new
HashMap
<
String
,
NamedObject
>());
}
unregistering
(
context
,
name
);
}
finally
{
lock
.
writeLock
().
unlock
();
}
...
...
src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java
浏览文件 @
a311994c
...
...
@@ -35,6 +35,7 @@ import javax.management.IntrospectionException;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanException
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.NotificationBroadcaster
;
import
javax.management.NotificationBroadcasterSupport
;
...
...
@@ -118,22 +119,32 @@ class StandardMBeanIntrospector extends MBeanIntrospector<Method> {
@Override
MBeanAttributeInfo
getMBeanAttributeInfo
(
String
attributeName
,
Method
getter
,
Method
setter
)
{
final
String
description
=
"Attribute exposed for management"
;
try
{
return
new
MBeanAttributeInfo
(
attributeName
,
description
,
getter
,
setter
);
}
catch
(
IntrospectionException
e
)
{
throw
new
RuntimeException
(
e
);
// should not happen
}
Method
getter
,
Method
setter
)
throws
IntrospectionException
{
String
description
=
getAttributeDescription
(
attributeName
,
"Attribute exposed for management"
,
getter
,
setter
);
return
new
MBeanAttributeInfo
(
attributeName
,
description
,
getter
,
setter
);
}
@Override
MBeanOperationInfo
getMBeanOperationInfo
(
String
operationName
,
Method
operation
)
{
final
String
description
=
"Operation exposed for management"
;
return
new
MBeanOperationInfo
(
description
,
operation
);
final
String
defaultDescription
=
"Operation exposed for management"
;
String
description
=
Introspector
.
descriptionForElement
(
operation
);
if
(
description
==
null
)
description
=
defaultDescription
;
int
impact
=
MBeanOperationInfo
.
UNKNOWN
;
ManagedOperation
annot
=
operation
.
getAnnotation
(
ManagedOperation
.
class
);
if
(
annot
!=
null
)
impact
=
annot
.
impact
().
getCode
();
MBeanOperationInfo
mboi
=
new
MBeanOperationInfo
(
description
,
operation
);
return
new
MBeanOperationInfo
(
mboi
.
getName
(),
mboi
.
getDescription
(),
mboi
.
getSignature
(),
mboi
.
getReturnType
(),
impact
,
mboi
.
getDescriptor
());
}
@Override
...
...
src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java
浏览文件 @
a311994c
...
...
@@ -41,26 +41,24 @@ import javax.management.openmbean.MXBeanMappingFactory;
public
class
StandardMBeanSupport
extends
MBeanSupport
<
Method
>
{
/**
<p>Construct a Standard MBean that wraps the given resource using the
given Standard MBean interface.</p>
@param resource the underlying resource for the new MBean.
@param mbeanInterface the interface to be used to determine
the MBean's management interface.
@param <T> a type parameter that allows the compiler to check
that {@code resource} implements {@code mbeanInterface},
provided that {@code mbeanInterface} is a class constant like
{@code SomeMBean.class}.
@throws IllegalArgumentException if {@code resource} is null or
if it does not implement the class {@code mbeanInterface} or if
that class is not a valid Standard MBean interface.
*/
public
<
T
>
StandardMBeanSupport
(
T
resource
,
Class
<
T
>
mbeanInterface
)
* <p>Construct a Standard MBean that wraps the given resource using the
* given Standard MBean interface.</p>
*
* @param resource the underlying resource for the new MBean.
* @param mbeanInterfaceType the class or interface to be used to determine
* the MBean's management interface. An interface if this is a
* classic Standard MBean; a class if this is a {@code @ManagedResource}.
* @param <T> a type parameter that allows the compiler to check
* that {@code resource} implements {@code mbeanInterfaceType},
* provided that {@code mbeanInterfaceType} is a class constant like
* {@code SomeMBean.class}.
* @throws IllegalArgumentException if {@code resource} is null or
* if it does not implement the class {@code mbeanInterfaceType} or if
* that class is not a valid Standard MBean interface.
*/
public
<
T
>
StandardMBeanSupport
(
T
resource
,
Class
<
T
>
mbeanInterfaceType
)
throws
NotCompliantMBeanException
{
super
(
resource
,
mbeanInterface
,
(
MXBeanMappingFactory
)
null
);
super
(
resource
,
mbeanInterface
Type
,
(
MXBeanMappingFactory
)
null
);
}
@Override
...
...
@@ -86,13 +84,14 @@ public class StandardMBeanSupport extends MBeanSupport<Method> {
@Override
public
MBeanInfo
getMBeanInfo
()
{
MBeanInfo
mbi
=
super
.
getMBeanInfo
();
Class
<?>
resourceClass
=
getResource
().
getClass
();
if
(
StandardMBeanIntrospector
.
isDefinitelyImmutableInfo
(
resourceClass
))
Class
<?>
resourceClass
=
getWrappedObject
().
getClass
();
if
(!
getMBeanInterface
().
isInterface
()
||
StandardMBeanIntrospector
.
isDefinitelyImmutableInfo
(
resourceClass
))
return
mbi
;
return
new
MBeanInfo
(
mbi
.
getClassName
(),
mbi
.
getDescription
(),
mbi
.
getAttributes
(),
mbi
.
getConstructors
(),
mbi
.
getOperations
(),
MBeanIntrospector
.
findNotifications
(
get
Resource
()),
MBeanIntrospector
.
findNotifications
(
get
WrappedObject
()),
mbi
.
getDescriptor
());
}
}
src/share/classes/com/sun/jmx/mbeanserver/Util.java
浏览文件 @
a311994c
...
...
@@ -38,6 +38,7 @@ import java.util.Map;
import
java.util.Set
;
import
java.util.SortedMap
;
import
java.util.TreeMap
;
import
java.util.WeakHashMap
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.ObjectName
;
...
...
@@ -71,6 +72,10 @@ public class Util {
return
new
LinkedHashMap
<
K
,
V
>();
}
static
<
K
,
V
>
WeakHashMap
<
K
,
V
>
newWeakHashMap
()
{
return
new
WeakHashMap
<
K
,
V
>();
}
static
<
E
>
Set
<
E
>
newSet
()
{
return
new
HashSet
<
E
>();
}
...
...
src/share/classes/com/sun/tools/jdi/EventSetImpl.java
浏览文件 @
a311994c
...
...
@@ -208,8 +208,9 @@ public class EventSetImpl extends ArrayList<Event> implements EventSet {
}
public
String
toString
()
{
return
eventName
()
+
"@"
+
location
().
toString
()
+
" in thread "
+
thread
().
name
();
return
eventName
()
+
"@"
+
((
location
()
==
null
)
?
" null"
:
location
().
toString
())
+
" in thread "
+
thread
().
name
();
}
}
...
...
src/share/classes/com/sun/tools/jdi/MonitorInfoImpl.java
浏览文件 @
a311994c
...
...
@@ -40,11 +40,12 @@ public class MonitorInfoImpl extends MirrorImpl
int
stack_depth
;
MonitorInfoImpl
(
VirtualMachine
vm
,
ObjectReference
mon
,
ThreadReference
thread
,
int
dpth
)
{
ThreadReference
Impl
thread
,
int
dpth
)
{
super
(
vm
);
this
.
monitor
=
mon
;
this
.
thread
=
thread
;
this
.
stack_depth
=
dpth
;
thread
.
addListener
(
this
);
}
...
...
src/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
浏览文件 @
a311994c
...
...
@@ -35,12 +35,34 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
static
final
int
SUSPEND_STATUS_SUSPENDED
=
0x1
;
static
final
int
SUSPEND_STATUS_BREAK
=
0x2
;
private
ThreadGroupReference
threadGroup
;
private
int
suspendedZombieCount
=
0
;
// This is cached only while the VM is suspended
private
static
class
Cache
extends
ObjectReferenceImpl
.
Cache
{
String
name
=
null
;
/*
* Some objects can only be created while a thread is suspended and are valid
* only while the thread remains suspended. Examples are StackFrameImpl
* and MonitorInfoImpl. When the thread resumes, these objects have to be
* marked as invalid so that their methods can throw
* InvalidStackFrameException if they are called. To do this, such objects
* register themselves as listeners of the associated thread. When the
* thread is resumed, its listeners are notified and mark themselves
* invalid.
* Also, note that ThreadReferenceImpl itself caches some info that
* is valid only as long as the thread is suspended. When the thread
* is resumed, that cache must be purged.
* Lastly, note that ThreadReferenceImpl and its super, ObjectReferenceImpl
* cache some info that is only valid as long as the entire VM is suspended.
* If _any_ thread is resumed, this cache must be purged. To handle this,
* both ThreadReferenceImpl and ObjectReferenceImpl register themselves as
* VMListeners so that they get notified when all threads are suspended and
* when any thread is resumed.
*/
// This is cached for the life of the thread
private
ThreadGroupReference
threadGroup
;
// This is cached only while this one thread is suspended. Each time
// the thread is resumed, we clear this and start with a fresh one.
private
static
class
LocalCache
{
JDWP
.
ThreadReference
.
Status
status
=
null
;
List
<
StackFrame
>
frames
=
null
;
int
framesStart
=
-
1
;
...
...
@@ -52,6 +74,17 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
boolean
triedCurrentContended
=
false
;
}
private
LocalCache
localCache
;
private
void
resetLocalCache
()
{
localCache
=
new
LocalCache
();
}
// This is cached only while all threads in the VM are suspended
// Yes, someone could change the name of a thread while it is suspended.
private
static
class
Cache
extends
ObjectReferenceImpl
.
Cache
{
String
name
=
null
;
}
protected
ObjectReferenceImpl
.
Cache
newCache
()
{
return
new
Cache
();
}
...
...
@@ -59,8 +92,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
// Listeners - synchronized on vm.state()
private
List
<
WeakReference
<
ThreadListener
>>
listeners
=
new
ArrayList
<
WeakReference
<
ThreadListener
>>();
ThreadReferenceImpl
(
VirtualMachine
aVm
,
long
aRef
)
{
super
(
aVm
,
aRef
);
resetLocalCache
();
vm
.
state
().
addListener
(
this
);
}
...
...
@@ -72,10 +107,24 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
* VMListener implementation
*/
public
boolean
vmNotSuspended
(
VMAction
action
)
{
synchronized
(
vm
.
state
())
{
processThreadAction
(
new
ThreadAction
(
this
,
ThreadAction
.
THREAD_RESUMABLE
));
if
(
action
.
resumingThread
()
==
null
)
{
// all threads are being resumed
synchronized
(
vm
.
state
())
{
processThreadAction
(
new
ThreadAction
(
this
,
ThreadAction
.
THREAD_RESUMABLE
));
}
}
/*
* Othewise, only one thread is being resumed:
* if it is us,
* we have already done our processThreadAction to notify our
* listeners when we processed the resume.
* if it is not us,
* we don't want to notify our listeners
* because we are not being resumed.
*/
return
super
.
vmNotSuspended
(
action
);
}
...
...
@@ -191,23 +240,19 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
private
JDWP
.
ThreadReference
.
Status
jdwpStatus
()
{
JDWP
.
ThreadReference
.
Status
status
=
null
;
JDWP
.
ThreadReference
.
Status
myStatus
=
localCache
.
status
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
)
{
status
=
local
.
status
;
}
if
(
status
==
null
)
{
status
=
JDWP
.
ThreadReference
.
Status
.
process
(
vm
,
this
);
if
(
local
!=
null
)
{
local
.
status
=
status
;
if
(
myStatus
==
null
)
{
myStatus
=
JDWP
.
ThreadReference
.
Status
.
process
(
vm
,
this
);
if
((
myStatus
.
suspendStatus
&
SUSPEND_STATUS_SUSPENDED
)
!=
0
)
{
// thread is suspended, we can cache the status.
localCache
.
status
=
myStatus
;
}
}
}
catch
(
JDWPException
exc
)
{
}
catch
(
JDWPException
exc
)
{
throw
exc
.
toJDIException
();
}
return
s
tatus
;
return
myS
tatus
;
}
public
int
status
()
{
...
...
@@ -245,8 +290,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
public
ThreadGroupReference
threadGroup
()
{
/*
* Thread group can't change, so it's cached more conventionally
* than other things in this class.
* Thread group can't change, so it's cached once and for all.
*/
if
(
threadGroup
==
null
)
{
try
{
...
...
@@ -260,19 +304,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
public
int
frameCount
()
throws
IncompatibleThreadStateException
{
int
frameCount
=
-
1
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
)
{
frameCount
=
local
.
frameCount
;
}
if
(
frameCount
==
-
1
)
{
frameCount
=
JDWP
.
ThreadReference
.
FrameCount
if
(
localCache
.
frameCount
==
-
1
)
{
localCache
.
frameCount
=
JDWP
.
ThreadReference
.
FrameCount
.
process
(
vm
,
this
).
frameCount
;
if
(
local
!=
null
)
{
local
.
frameCount
=
frameCount
;
}
}
}
catch
(
JDWPException
exc
)
{
switch
(
exc
.
errorCode
())
{
...
...
@@ -283,7 +318,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw
exc
.
toJDIException
();
}
}
return
frameCount
;
return
localCache
.
frameCount
;
}
public
List
<
StackFrame
>
frames
()
throws
IncompatibleThreadStateException
{
...
...
@@ -297,23 +332,25 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
/**
* Is the requested subrange within what has been retrieved?
* local is known to be non-null
* local is known to be non-null. Should only be called from
* a sync method.
*/
private
boolean
isSubrange
(
Cache
local
,
int
start
,
int
length
,
List
frames
)
{
if
(
start
<
local
.
framesStart
)
{
private
boolean
isSubrange
(
LocalCache
localCache
,
int
start
,
int
length
)
{
if
(
start
<
local
Cache
.
framesStart
)
{
return
false
;
}
if
(
length
==
-
1
)
{
return
(
local
.
framesLength
==
-
1
);
return
(
local
Cache
.
framesLength
==
-
1
);
}
if
(
local
.
framesLength
==
-
1
)
{
if
((
start
+
length
)
>
(
local
.
framesStart
+
frames
.
size
()))
{
if
(
localCache
.
framesLength
==
-
1
)
{
if
((
start
+
length
)
>
(
localCache
.
framesStart
+
localCache
.
frames
.
size
()))
{
throw
new
IndexOutOfBoundsException
();
}
return
true
;
}
return
((
start
+
length
)
<=
(
local
.
framesStart
+
local
.
framesLength
));
return
((
start
+
length
)
<=
(
local
Cache
.
framesStart
+
localCache
.
framesLength
));
}
public
List
<
StackFrame
>
frames
(
int
start
,
int
length
)
...
...
@@ -329,51 +366,42 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
* Private version of frames() allows "-1" to specify all
* remaining frames.
*/
private
List
<
StackFrame
>
privateFrames
(
int
start
,
int
length
)
synchronized
private
List
<
StackFrame
>
privateFrames
(
int
start
,
int
length
)
throws
IncompatibleThreadStateException
{
List
<
StackFrame
>
frames
=
null
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
)
{
frames
=
local
.
frames
;
}
if
(
frames
==
null
||
!
isSubrange
(
local
,
start
,
length
,
frames
))
{
// Lock must be held while creating stack frames so if that two threads
// do this at the same time, one won't clobber the subset created by the other.
try
{
if
(
localCache
.
frames
==
null
||
!
isSubrange
(
localCache
,
start
,
length
))
{
JDWP
.
ThreadReference
.
Frames
.
Frame
[]
jdwpFrames
=
JDWP
.
ThreadReference
.
Frames
.
process
(
vm
,
this
,
start
,
length
).
frames
;
process
(
vm
,
this
,
start
,
length
).
frames
;
int
count
=
jdwpFrames
.
length
;
frames
=
new
ArrayList
<
StackFrame
>(
count
);
// Lock must be held while creating stack frames.
// so that a resume will not resume a partially
// created stack.
synchronized
(
vm
.
state
())
{
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
if
(
jdwpFrames
[
i
].
location
==
null
)
{
throw
new
InternalException
(
"Invalid frame location"
);
}
StackFrame
frame
=
new
StackFrameImpl
(
vm
,
this
,
jdwpFrames
[
i
].
frameID
,
jdwpFrames
[
i
].
location
);
// Add to the frame list
frames
.
add
(
frame
);
localCache
.
frames
=
new
ArrayList
<
StackFrame
>(
count
);
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
if
(
jdwpFrames
[
i
].
location
==
null
)
{
throw
new
InternalException
(
"Invalid frame location"
);
}
StackFrame
frame
=
new
StackFrameImpl
(
vm
,
this
,
jdwpFrames
[
i
].
frameID
,
jdwpFrames
[
i
].
location
);
// Add to the frame list
localCache
.
frames
.
add
(
frame
);
}
if
(
local
!=
null
)
{
local
.
frames
=
frames
;
local
.
framesStart
=
start
;
local
.
framesLength
=
length
;
}
localCache
.
framesStart
=
start
;
localCache
.
framesLength
=
length
;
return
Collections
.
unmodifiableList
(
localCache
.
frames
);
}
else
{
int
fromIndex
=
start
-
local
.
framesStart
;
int
fromIndex
=
start
-
local
Cache
.
framesStart
;
int
toIndex
;
if
(
length
==
-
1
)
{
toIndex
=
frames
.
size
()
-
fromIndex
;
toIndex
=
localCache
.
frames
.
size
()
-
fromIndex
;
}
else
{
toIndex
=
fromIndex
+
length
;
}
frames
=
frames
.
subList
(
fromIndex
,
toIndex
);
return
Collections
.
unmodifiableList
(
localCache
.
frames
.
subList
(
fromIndex
,
toIndex
)
);
}
}
catch
(
JDWPException
exc
)
{
switch
(
exc
.
errorCode
())
{
...
...
@@ -384,28 +412,18 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw
exc
.
toJDIException
();
}
}
return
Collections
.
unmodifiableList
(
frames
);
}
public
List
<
ObjectReference
>
ownedMonitors
()
throws
IncompatibleThreadStateException
{
List
<
ObjectReference
>
monitors
=
null
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
)
{
monitors
=
local
.
ownedMonitors
;
}
if
(
monitors
==
null
)
{
monitors
=
Arrays
.
asList
(
if
(
localCache
.
ownedMonitors
==
null
)
{
localCache
.
ownedMonitors
=
Arrays
.
asList
(
(
ObjectReference
[])
JDWP
.
ThreadReference
.
OwnedMonitors
.
process
(
vm
,
this
).
owned
);
if
(
local
!=
null
)
{
local
.
ownedMonitors
=
monitors
;
if
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
)
{
vm
.
printTrace
(
description
()
+
" temporarily caching owned monitors"
+
" (count = "
+
monitors
.
size
()
+
")"
);
}
if
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
)
{
vm
.
printTrace
(
description
()
+
" temporarily caching owned monitors"
+
" (count = "
+
localCache
.
ownedMonitors
.
size
()
+
")"
);
}
}
}
catch
(
JDWPException
exc
)
{
...
...
@@ -417,29 +435,22 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw
exc
.
toJDIException
();
}
}
return
m
onitors
;
return
localCache
.
ownedM
onitors
;
}
public
ObjectReference
currentContendedMonitor
()
throws
IncompatibleThreadStateException
{
ObjectReference
monitor
=
null
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
&&
local
.
triedCurrentContended
)
{
monitor
=
local
.
contendedMonitor
;
}
else
{
monitor
=
JDWP
.
ThreadReference
.
CurrentContendedMonitor
.
if
(
localCache
.
contendedMonitor
==
null
&&
!
localCache
.
triedCurrentContended
)
{
localCache
.
contendedMonitor
=
JDWP
.
ThreadReference
.
CurrentContendedMonitor
.
process
(
vm
,
this
).
monitor
;
if
(
local
!=
null
)
{
local
.
triedCurrentContended
=
true
;
local
.
contendedMonitor
=
monitor
;
if
((
monitor
!=
null
)
&&
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
))
{
vm
.
printTrace
(
description
()
+
" temporarily caching contended monitor"
+
" (id = "
+
monitor
.
uniqueID
()
+
")"
);
}
localCache
.
triedCurrentContended
=
true
;
if
((
localCache
.
contendedMonitor
!=
null
)
&&
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
))
{
vm
.
printTrace
(
description
()
+
" temporarily caching contended monitor"
+
" (id = "
+
localCache
.
contendedMonitor
.
uniqueID
()
+
")"
);
}
}
}
catch
(
JDWPException
exc
)
{
...
...
@@ -450,40 +461,31 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw
exc
.
toJDIException
();
}
}
return
m
onitor
;
return
localCache
.
contendedM
onitor
;
}
public
List
<
MonitorInfo
>
ownedMonitorsAndFrames
()
throws
IncompatibleThreadStateException
{
List
<
MonitorInfo
>
monitors
=
null
;
try
{
Cache
local
=
(
Cache
)
getCache
();
if
(
local
!=
null
)
{
monitors
=
local
.
ownedMonitorsInfo
;
}
if
(
monitors
==
null
)
{
if
(
localCache
.
ownedMonitorsInfo
==
null
)
{
JDWP
.
ThreadReference
.
OwnedMonitorsStackDepthInfo
.
monitor
[]
minfo
;
minfo
=
JDWP
.
ThreadReference
.
OwnedMonitorsStackDepthInfo
.
process
(
vm
,
this
).
owned
;
monitors
=
new
ArrayList
<
MonitorInfo
>(
minfo
.
length
);
localCache
.
ownedMonitorsInfo
=
new
ArrayList
<
MonitorInfo
>(
minfo
.
length
);
for
(
int
i
=
0
;
i
<
minfo
.
length
;
i
++)
{
JDWP
.
ThreadReference
.
OwnedMonitorsStackDepthInfo
.
monitor
mi
=
minfo
[
i
];
MonitorInfo
mon
=
new
MonitorInfoImpl
(
vm
,
minfo
[
i
].
monitor
,
this
,
minfo
[
i
].
stack_depth
);
monitors
.
add
(
mon
);
localCache
.
ownedMonitorsInfo
.
add
(
mon
);
}
if
(
local
!=
null
)
{
local
.
ownedMonitorsInfo
=
monitors
;
if
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
)
{
vm
.
printTrace
(
description
()
+
" temporarily caching owned monitors"
+
" (count = "
+
monitors
.
size
()
+
")"
);
if
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
)
{
vm
.
printTrace
(
description
()
+
" temporarily caching owned monitors"
+
" (count = "
+
localCache
.
ownedMonitorsInfo
.
size
()
+
")"
);
}
}
}
}
catch
(
JDWPException
exc
)
{
switch
(
exc
.
errorCode
())
{
case
JDWP
.
Error
.
THREAD_NOT_SUSPENDED
:
...
...
@@ -493,7 +495,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw
exc
.
toJDIException
();
}
}
return
monitors
;
return
localCache
.
ownedMonitorsInfo
;
}
public
void
popFrames
(
StackFrame
frame
)
throws
IncompatibleThreadStateException
{
...
...
@@ -511,7 +513,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
public
void
forceEarlyReturn
(
Value
returnValue
)
throws
InvalidTypeException
,
ClassNotLoadedException
,
ClassNotLoadedException
,
IncompatibleThreadStateException
{
if
(!
vm
.
canForceEarlyReturn
())
{
throw
new
UnsupportedOperationException
(
...
...
@@ -604,6 +606,9 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
iter
.
remove
();
}
}
// Discard our local cache
resetLocalCache
();
}
}
}
src/share/classes/com/sun/tools/jdi/VMAction.java
浏览文件 @
a311994c
...
...
@@ -38,10 +38,18 @@ class VMAction extends EventObject {
static
final
int
VM_NOT_SUSPENDED
=
2
;
int
id
;
ThreadReference
resumingThread
;
VMAction
(
VirtualMachine
vm
,
int
id
)
{
this
(
vm
,
null
,
id
);
}
// For id = VM_NOT_SUSPENDED, if resumingThread != null, then it is
// the only thread that is being resumed.
VMAction
(
VirtualMachine
vm
,
ThreadReference
resumingThread
,
int
id
)
{
super
(
vm
);
this
.
id
=
id
;
this
.
resumingThread
=
resumingThread
;
}
VirtualMachine
vm
()
{
return
(
VirtualMachine
)
getSource
();
...
...
@@ -49,4 +57,8 @@ class VMAction extends EventObject {
int
id
()
{
return
id
;
}
ThreadReference
resumingThread
()
{
return
resumingThread
;
}
}
src/share/classes/com/sun/tools/jdi/VMState.java
浏览文件 @
a311994c
...
...
@@ -115,17 +115,26 @@ class VMState {
return
stream
;
}
/**
* All threads are resuming
*/
void
thaw
()
{
thaw
(
null
);
}
/**
* Tell listeners to invalidate suspend-sensitive caches.
* If resumingThread != null, then only that thread is being
* resumed.
*/
synchronized
void
thaw
()
{
synchronized
void
thaw
(
ThreadReference
resumingThread
)
{
if
(
cache
!=
null
)
{
if
((
vm
.
traceFlags
&
vm
.
TRACE_OBJREFS
)
!=
0
)
{
vm
.
printTrace
(
"Clearing VM suspended cache"
);
}
disableCache
();
}
processVMAction
(
new
VMAction
(
vm
,
VMAction
.
VM_NOT_SUSPENDED
));
processVMAction
(
new
VMAction
(
vm
,
resumingThread
,
VMAction
.
VM_NOT_SUSPENDED
));
}
private
synchronized
void
processVMAction
(
VMAction
action
)
{
...
...
src/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
浏览文件 @
a311994c
...
...
@@ -146,8 +146,9 @@ class VirtualMachineImpl extends MirrorImpl
public
boolean
threadResumable
(
ThreadAction
action
)
{
/*
* If any thread is resumed, the VM is considered not suspended.
* Just one thread is being resumed so pass it to thaw.
*/
state
.
thaw
();
state
.
thaw
(
action
.
thread
()
);
return
true
;
}
...
...
src/share/classes/java/nio/channels/SelectionKey.java
浏览文件 @
a311994c
...
...
@@ -191,7 +191,7 @@ public abstract class SelectionKey {
* @throws IllegalArgumentException
* If a bit in the set does not correspond to an operation that
* is supported by this key's channel, that is, if
* <tt>
set & ~(
channel().validOps()) != 0</tt>
* <tt>
(ops & ~
channel().validOps()) != 0</tt>
*
* @throws CancelledKeyException
* If this key has been cancelled
...
...
src/share/classes/javax/management/BinaryRelQueryExp.java
浏览文件 @
a311994c
...
...
@@ -192,6 +192,7 @@ class BinaryRelQueryExp extends QueryEval implements QueryExp {
return
"("
+
exp1
+
") "
+
relOpString
()
+
" ("
+
exp2
+
")"
;
}
@Override
String
toQueryString
()
{
return
exp1
+
" "
+
relOpString
()
+
" "
+
exp2
;
}
...
...
src/share/classes/javax/management/Description.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.ResourceBundle
;
/**
* <p>The textual description of an MBean or part of an MBean. This
* description is intended to be displayed to users to help them
* understand what the MBean does. Ultimately it will be the value of
* the {@code getDescription()} method of an {@link MBeanInfo}, {@link
* MBeanAttributeInfo}, or similar.</p>
*
* <p>This annotation applies to Standard MBean interfaces and to
* MXBean interfaces, as well as to MBean classes defined using the
* {@link MBean @MBean} or {@link MXBean @MXBean} annotations. For
* example, a Standard MBean might be defined like this:</p>
*
* <pre>
* <b>{@code @Description}</b>("Application configuration")
* public interface ConfigurationMBean {
* <b>{@code @Description}</b>("Cache size in bytes")
* public int getCacheSize();
* public void setCacheSize(int size);
*
* <b>{@code @Description}</b>("Last time the configuration was changed, " +
* "in milliseconds since 1 Jan 1970")
* public long getLastChangedTime();
*
* <b>{@code @Description}</b>("Save the configuration to a file")
* public void save(
* <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
* String fileName);
* }
* </pre>
*
* <p>The {@code MBeanInfo} for this MBean will have a {@link
* MBeanInfo#getDescription() getDescription()} that is {@code
* "Application configuration"}. It will contain an {@code
* MBeanAttributeInfo} for the {@code CacheSize} attribute that is
* defined by the methods {@code getCacheSize} and {@code
* setCacheSize}, and another {@code MBeanAttributeInfo} for {@code
* LastChangedTime}. The {@link MBeanAttributeInfo#getDescription()
* getDescription()} for {@code CacheSize} will be {@code "Cache size
* in bytes"}. Notice that there is no need to add a
* {@code @Description} to both {@code getCacheSize} and {@code
* setCacheSize} - either alone will do. But if you do add a
* {@code @Description} to both, it must be the same.</p>
*
* <p>The {@code MBeanInfo} will also contain an {@link
* MBeanOperationInfo} where {@link
* MBeanOperationInfo#getDescription() getDescription()} is {@code
* "Save the configuration to a file"}. This {@code
* MBeanOperationInfo} will contain an {@link MBeanParameterInfo}
* where {@link MBeanParameterInfo#getDescription() getDescription()}
* is {@code "Optional name of the file, or null for the default
* name"}.</p>
*
* <p>The {@code @Description} annotation can also be applied to the
* public constructors of the implementation class. Continuing the
* above example, the {@code Configuration} class implementing {@code
* ConfigurationMBean} might look like this:</p>
*
* <pre>
* public class Configuration implements ConfigurationMBean {
* <b>{@code @Description}</b>("A Configuration MBean with the default file name")
* public Configuration() {
* this(DEFAULT_FILE_NAME);
* }
*
* <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
* public Configuration(
* <b>{@code @Description}</b>("Name of the file the configuration is stored in")
* String fileName) {...}
* ...
* }
* </pre>
*
* <p>The {@code @Description} annotation also works in MBeans that
* are defined using the {@code @MBean} or {@code @MXBean} annotation
* on classes. Here is an alternative implementation of {@code
* Configuration} that does not use an {@code ConfigurationMBean}
* interface.</p>
*
* <pre>
* <b>{@code @MBean}</b>
* <b>{@code @Description}</b>("Application configuration")
* public class Configuration {
* <b>{@code @Description}</b>("A Configuration MBean with the default file name")
* public Configuration() {
* this(DEFAULT_FILE_NAME);
* }
*
* <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
* public Configuration(
* <b>{@code @Description}</b>("Name of the file the configuration is stored in")
* String fileName) {...}
*
* <b>{@code @ManagedAttribute}</b>
* <b>{@code @Description}</b>("Cache size in bytes")
* public int getCacheSize() {...}
* <b>{@code @ManagedAttribute}</b>
* public void setCacheSize(int size) {...}
*
* <b>{@code @ManagedOperation}</b>
* <b>{@code @Description}</b>("Last time the configuration was changed, " +
* "in milliseconds since 1 Jan 1970")
* public long getLastChangedTime() {...}
*
* <b>{@code @ManagedOperation}</b>
* <b>{@code @Description}</b>("Save the configuration to a file")
* public void save(
* <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
* String fileName) {...}
* ...
* }
* </pre>
*/
@Documented
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
({
ElementType
.
CONSTRUCTOR
,
ElementType
.
METHOD
,
ElementType
.
PARAMETER
,
ElementType
.
TYPE
})
public
@interface
Description
{
/**
* <p>The description.</p>
*/
String
value
();
/**
* <p>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}. If a non-default value
* is supplied for this element, it will appear in the
* <a href="Descriptor.html#descriptionResourceBundleBaseName"><!--
* -->{@code Descriptor}</a> for the annotated item.</p>
*/
@DescriptorKey
(
value
=
"descriptionResourceBundleBaseName"
,
omitIfDefault
=
true
)
String
bundleBaseName
()
default
""
;
/**
* <p>A resource key for the description of this element. In
* conjunction with the {@link #bundleBaseName bundleBaseName},
* this can be used to find a localized version of the description.
* If a non-default value
* is supplied for this element, it will appear in the
* <a href="Descriptor.html#descriptionResourceKey"><!--
* -->{@code Descriptor}</a> for the annotated item.</p>
*/
@DescriptorKey
(
value
=
"descriptionResourceKey"
,
omitIfDefault
=
true
)
String
key
()
default
""
;
}
src/share/classes/javax/management/Descriptor.java
浏览文件 @
a311994c
...
...
@@ -38,6 +38,7 @@ import java.util.Arrays;
import
java.util.ResourceBundle
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
javax.management.openmbean.OpenMBeanAttributeInfoSupport
;
import
javax.management.openmbean.OpenMBeanOperationInfoSupport
;
import
javax.management.openmbean.OpenMBeanParameterInfoSupport
;
...
...
@@ -117,21 +118,19 @@ import javax.management.openmbean.OpenType;
* deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td>
*
* <tr><td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
* <tr id="descriptionResourceBundleBaseName">
* <td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
*
* <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}. The meaning of this
* field is defined by this specification but the field is not set or
* used by the JMX API itself.</td>
* {@code "com.example.myapp.MBeanResources"}.</td>
*
* <tr><td>descriptionResourceKey</td><td>String</td><td>Any</td>
* <tr id="descriptionResourceKey">
* <td>descriptionResourceKey</td><td>String</td><td>Any</td>
*
* <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName},
* this can be used to find a localized version of the description.
* The meaning of this field is defined by this specification but the
* field is not set or used by the JMX API itself.</td>
* this can be used to find a localized version of the description.</td>
*
* <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
...
...
@@ -216,6 +215,14 @@ import javax.management.openmbean.OpenType;
* StandardMBean} class will have this field in its MBeanInfo
* Descriptor.</td>
*
* <tr><td id="mxbeanMappingFactoryClass"><i>mxbeanMappingFactoryClass</i>
* </td><td>String</td>
* <td>MBeanInfo</td>
*
* <td>The name of the {@link MXBeanMappingFactory} class that was used for this
* MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default}
* one.</td>
*
* <tr><td><a name="openType"><i>openType</i></a><td>{@link OpenType}</td>
* <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
*
...
...
src/share/classes/javax/management/DescriptorFields.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* <p>Annotation that adds fields to a {@link Descriptor}. This can be the
* Descriptor for an MBean, or for an attribute, operation, or constructor
* in an MBean, or for a parameter of an operation or constructor.</p>
*
* <p>Consider this Standard MBean interface, for example:</p>
*
* <pre>
* public interface CacheControlMBean {
* <b>@DescriptorFields("units=bytes")</b>
* public long getCacheSize();
* }
* </pre>
*
* <p>When a Standard MBean is made using this interface, the usual rules
* mean that it will have an attribute called {@code CacheSize} of type
* {@code long}. The {@code DescriptorFields} annotation will ensure
* that the {@link MBeanAttributeInfo} for this attribute will have a
* {@code Descriptor} that has a field called {@code units} with
* corresponding value {@code bytes}.</p>
*
* <p>Similarly, if the interface looks like this:</p>
*
* <pre>
* public interface CacheControlMBean {
* <b>@DescriptorFields({"units=bytes", "since=1.5"})</b>
* public long getCacheSize();
* }
* </pre>
*
* <p>then the resulting {@code Descriptor} will contain the following
* fields:</p>
*
* <table border="2">
* <tr><th>Name</th><th>Value</th></tr>
* <tr><td>units</td><td>"bytes"</td></tr>
* <tr><td>since</td><td>"1.5"</td></tr>
* </table>
*
* <p>The {@code @DescriptorFields} annotation can be applied to:</p>
*
* <ul>
* <li>a Standard MBean or MXBean interface;
* <li>a method in such an interface;
* <li>a parameter of a method in a Standard MBean or MXBean interface
* when that method is an operation (not a getter or setter for an attribute);
* <li>a public constructor in the class that implements a Standard MBean
* or MXBean;
* <li>a parameter in such a constructor.
* </ul>
*
* <p>Other uses of the annotation will either fail to compile or be
* ignored.</p>
*
* <p>Interface annotations are checked only on the exact interface
* that defines the management interface of a Standard MBean or an
* MXBean, not on its parent interfaces. Method annotations are
* checked only in the most specific interface in which the method
* appears; in other words, if a child interface overrides a method
* from a parent interface, only {@code @DescriptorFields} annotations in
* the method in the child interface are considered.
*
* <p>The Descriptor fields contributed in this way must be consistent
* with each other and with any fields contributed by {@link
* DescriptorKey @DescriptorKey} annotations. That is, two
* different annotations, or two members of the same annotation, must
* not define a different value for the same Descriptor field. Fields
* from annotations on a getter method must also be consistent with
* fields from annotations on the corresponding setter method.</p>
*
* <p>The Descriptor resulting from these annotations will be merged
* with any Descriptor fields provided by the implementation, such as
* the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field for an MBean. The fields from the annotations
* must be consistent with these fields provided by the implementation.</p>
*
* <h4>{@literal @DescriptorFields and @DescriptorKey}</h4>
*
* <p>The {@link DescriptorKey @DescriptorKey} annotation provides
* another way to use annotations to define Descriptor fields.
* <code>@DescriptorKey</code> requires more work but is also more
* robust, because there is less risk of mistakes such as misspelling
* the name of the field or giving an invalid value.
* <code>@DescriptorFields</code> is more convenient but includes
* those risks. <code>@DescriptorFields</code> is more
* appropriate for occasional use, but for a Descriptor field that you
* add in many places, you should consider a purpose-built annotation
* using <code>@DescriptorKey</code>.
*
* @since 1.7
*/
@Documented
@Inherited
// for @MBean and @MXBean classes
@Target
({
ElementType
.
CONSTRUCTOR
,
ElementType
.
METHOD
,
ElementType
.
PARAMETER
,
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
DescriptorFields
{
/**
* <p>The descriptor fields. Each element of the string looks like
* {@code "name=value"}.</p>
*/
public
String
[]
value
();
}
src/share/classes/javax/management/DescriptorKey.java
浏览文件 @
a311994c
...
...
@@ -33,6 +33,11 @@ import java.lang.annotation.*;
* an MBean, or for an attribute, operation, or constructor in an
* MBean, or for a parameter of an operation or constructor.</p>
*
* <p>(The {@link DescriptorFields @DescriptorFields} annotation
* provides another way to add fields to a {@code Descriptor}. See
* the documentation for that annotation for a comparison of the
* two possibilities.)</p>
*
* <p>Consider this annotation for example:</p>
*
* <pre>
...
...
@@ -57,7 +62,7 @@ import java.lang.annotation.*;
* <p>When a Standard MBean is made from the {@code CacheControlMBean},
* the usual rules mean that it will have an attribute called
* {@code CacheSize} of type {@code long}. The {@code @Units}
* a
ttribute
, given the above definition, will ensure that the
* a
nnotation
, given the above definition, will ensure that the
* {@link MBeanAttributeInfo} for this attribute will have a
* {@code Descriptor} that has a field called {@code units} with
* corresponding value {@code bytes}.</p>
...
...
@@ -125,12 +130,13 @@ import java.lang.annotation.*;
* the method in the child interface are considered.
*
* <p>The Descriptor fields contributed in this way by different
* annotations on the same program element must be consistent. That
* is, two different annotations, or two members of the same
* annotation, must not define a different value for the same
* Descriptor field. Fields from annotations on a getter method must
* also be consistent with fields from annotations on the
* corresponding setter method.</p>
* annotations on the same program element must be consistent with
* each other and with any fields contributed by a {@link
* DescriptorFields @DescriptorFields} annotation. That is, two
* different annotations, or two members of the same annotation, must
* not define a different value for the same Descriptor field. Fields
* from annotations on a getter method must also be consistent with
* fields from annotations on the corresponding setter method.</p>
*
* <p>The Descriptor resulting from these annotations will be merged
* with any Descriptor fields provided by the implementation, such as
...
...
@@ -169,4 +175,36 @@ import java.lang.annotation.*;
@Target
(
ElementType
.
METHOD
)
public
@interface
DescriptorKey
{
String
value
();
/**
* <p>Do not include this field in the Descriptor if the annotation
* element has its default value. For example, suppose {@code @Units} is
* defined like this:</p>
*
* <pre>
* @Documented
* @Target(ElementType.METHOD)
* @Retention(RetentionPolicy.RUNTIME)
* public @interface Units {
* @DescriptorKey("units")
* String value();
*
* <b>@DescriptorKey(value = "descriptionResourceKey",
* omitIfDefault = true)</b>
* String resourceKey() default "";
*
* <b>@DescriptorKey(value = "descriptionResourceBundleBaseName",
* omitIfDefault = true)</b>
* String resourceBundleBaseName() default "";
* }
* </pre>
*
* <p>Then consider a usage such as {@code @Units("bytes")} or
* {@code @Units(value = "bytes", resourceKey = "")}, where the
* {@code resourceKey} and {@code resourceBundleBaseNames} elements
* have their default values. In this case the Descriptor resulting
* from these annotations will not include a {@code descriptionResourceKey}
* or {@code descriptionResourceBundleBaseName} field.</p>
*/
boolean
omitIfDefault
()
default
false
;
}
src/share/classes/javax/management/DynamicWrapperMBean.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2005 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
/**
* <p>An MBean can implement this interface to affect how the MBeanServer's
* {@link MBeanServer#getClassLoaderFor getClassLoaderFor} and
* {@link MBeanServer#isInstanceOf isInstanceOf} methods behave.
* If these methods should refer to a wrapped object rather than the
* MBean object itself, then the {@link #getWrappedObject} method should
* return that wrapped object.</p>
*
* @see MBeanServer#getClassLoaderFor
* @see MBeanServer#isInstanceOf
*/
public
interface
DynamicWrapperMBean
extends
DynamicMBean
{
/**
* <p>The resource corresponding to this MBean. This is the object whose
* class name should be reflected by the MBean's
* {@link MBeanServer#getMBeanInfo getMBeanInfo()}.<!--
* -->{@link MBeanInfo#getClassName getClassName()} for example. For a "plain"
* DynamicMBean it will be "this". For an MBean that wraps another
* object, in the manner of {@link javax.management.StandardMBean}, it will be the
* wrapped object.</p>
*
* @return The resource corresponding to this MBean.
*/
public
Object
getWrappedObject
();
/**
* <p>The {@code ClassLoader} for this MBean, which can be used to
* retrieve resources associated with the MBean for example. Usually,
* it will be
* {@link #getWrappedObject()}.{@code getClass().getClassLoader()}.
*
* @return The {@code ClassLoader} for this MBean.
*/
public
ClassLoader
getWrappedClassLoader
();
}
src/share/classes/javax/management/Impact.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
/**
* <p>Defines the impact of an MBean operation, in particular whether it
* has an effect on the MBean or simply returns information. This enum
* is used in the {@link ManagedOperation @ManagedOperation} annotation.
* Its {@link #getCode()} method can be used to get an {@code int} suitable
* for use as the {@code impact} parameter in an {@link MBeanOperationInfo}
* constructor.</p>
*/
public
enum
Impact
{
/**
* The operation is read-like: it returns information but does not change
* any state.
* @see MBeanOperationInfo#INFO
*/
INFO
(
MBeanOperationInfo
.
INFO
),
/**
* The operation is write-like: it has an effect but does not return
* any information from the MBean.
* @see MBeanOperationInfo#ACTION
*/
ACTION
(
MBeanOperationInfo
.
ACTION
),
/**
* The operation is both read-like and write-like: it has an effect,
* and it also returns information from the MBean.
* @see MBeanOperationInfo#ACTION_INFO
*/
ACTION_INFO
(
MBeanOperationInfo
.
ACTION_INFO
),
/**
* The impact of the operation is unknown or cannot be expressed
* using one of the other values.
* @see MBeanOperationInfo#UNKNOWN
*/
UNKNOWN
(
MBeanOperationInfo
.
UNKNOWN
);
private
final
int
code
;
/**
* An instance of this enumeration, with the corresponding {@code int}
* code used by the {@link MBeanOperationInfo} constructors.
*
* @param code the code used by the {@code MBeanOperationInfo} constructors.
*/
Impact
(
int
code
)
{
this
.
code
=
code
;
}
/**
* The equivalent {@code int} code used by the {@link MBeanOperationInfo}
* constructors.
* @return the {@code int} code.
*/
public
int
getCode
()
{
return
code
;
}
/**
* Return the {@code Impact} value corresponding to the given {@code int}
* code. The {@code code} is the value that would be used in an
* {@code MBeanOperationInfo} constructor.
*
* @param code the {@code int} code.
*
* @return an {@code Impact} value {@code x} such that
* {@code code == x.}{@link #getCode()}, or {@code Impact.UNKNOWN}
* if there is no such value.
*/
public
static
Impact
forCode
(
int
code
)
{
switch
(
code
)
{
case
MBeanOperationInfo
.
ACTION
:
return
ACTION
;
case
MBeanOperationInfo
.
INFO
:
return
INFO
;
case
MBeanOperationInfo
.
ACTION_INFO
:
return
ACTION_INFO
;
default
:
return
UNKNOWN
;
}
}
}
src/share/classes/javax/management/JMX.java
浏览文件 @
a311994c
...
...
@@ -26,6 +26,7 @@
package
javax.management
;
import
com.sun.jmx.mbeanserver.Introspector
;
import
com.sun.jmx.mbeanserver.MBeanInjector
;
import
com.sun.jmx.remote.util.ClassLogger
;
import
java.beans.BeanInfo
;
import
java.beans.PropertyDescriptor
;
...
...
@@ -130,6 +131,7 @@ public class JMX {
* </pre>
*
* @see javax.management.JMX.ProxyOptions
* @see javax.management.StandardMBean.Options
*/
public
static
class
MBeanOptions
implements
Serializable
,
Cloneable
{
private
static
final
long
serialVersionUID
=
-
6380842449318177843L
;
...
...
@@ -739,4 +741,28 @@ public class JMX {
// exactly the string "MXBean" since that would mean there
// was no package name, which is pretty unlikely in practice.
}
/**
* <p>Test if an MBean can emit notifications. An MBean can emit
* notifications if either it implements {@link NotificationBroadcaster}
* (perhaps through its child interface {@link NotificationEmitter}), or
* it uses <a href="MBeanRegistration.html#injection">resource
* injection</a> to obtain an instance of {@link SendNotification}
* through which it can send notifications.</p>
*
* @param mbean an MBean object.
* @return true if the given object is a valid MBean that can emit
* notifications; false if the object is a valid MBean but that
* cannot emit notifications.
* @throws NotCompliantMBeanException if the given object is not
* a valid MBean.
*/
public
static
boolean
isNotificationSource
(
Object
mbean
)
throws
NotCompliantMBeanException
{
if
(
mbean
instanceof
NotificationBroadcaster
)
return
true
;
Object
resource
=
(
mbean
instanceof
DynamicWrapperMBean
)
?
((
DynamicWrapperMBean
)
mbean
).
getWrappedObject
()
:
mbean
;
return
(
MBeanInjector
.
injectsSendNotification
(
resource
));
}
}
src/share/classes/javax/management/MBean.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* <p>Indicates that the annotated class is a Standard MBean. A Standard
* MBean class can be defined as in this example:</p>
*
* <pre>
* {@code @MBean}
* public class Configuration {
* {@link ManagedAttribute @ManagedAttribute}
* public int getCacheSize() {...}
* {@code @ManagedAttribute}
* public void setCacheSize(int size);
*
* {@code @ManagedAttribute}
* public long getLastChangedTime();
*
* {@link ManagedOperation @ManagedOperation}
* public void save();
* }
* </pre>
*
* <p>The class must be public. Public methods within the class can be
* annotated with {@code @ManagedOperation} to indicate that they are
* MBean operations. Public getter and setter methods within the class
* can be annotated with {@code @ManagedAttribute} to indicate that they define
* MBean attributes.</p>
*
* <p>If the MBean is to be an MXBean rather than a Standard MBean, then
* the {@link MXBean @MXBean} annotation must be used instead of
* {@code @MBean}.</p>
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
@Inherited
public
@interface
MBean
{
}
src/share/classes/javax/management/MBeanOperationInfo.java
浏览文件 @
a311994c
...
...
@@ -46,25 +46,30 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
new
MBeanOperationInfo
[
0
];
/**
* Indicates that the operation is read-like,
* it basically returns information.
* Indicates that the operation is read-like:
* it returns information but does not change any state.
* @see Impact#INFO
*/
public
static
final
int
INFO
=
0
;
/**
* Indicates that the operation is
a write-like,
*
and would modify the MBean in some way, typically by writing some value
*
or changing a configuration.
* Indicates that the operation is
write-like: it has an effect but does
*
not return any information from the MBean.
*
@see Impact#ACTION
*/
public
static
final
int
ACTION
=
1
;
/**
* Indicates that the operation is both read-like and write-like.
* Indicates that the operation is both read-like and write-like:
* it has an effect, and it also returns information from the MBean.
* @see Impact#ACTION_INFO
*/
public
static
final
int
ACTION_INFO
=
2
;
/**
* Indicates that the operation has an "unknown" nature.
* Indicates that the impact of the operation is unknown or cannot be
* expressed using one of the other values.
* @see Impact#UNKNOWN
*/
public
static
final
int
UNKNOWN
=
3
;
...
...
@@ -120,8 +125,9 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
* describing the parameters(arguments) of the method. This may be
* null with the same effect as a zero-length array.
* @param type The type of the method's return value.
* @param impact The impact of the method, one of <CODE>INFO,
* ACTION, ACTION_INFO, UNKNOWN</CODE>.
* @param impact The impact of the method, one of
* {@link #INFO}, {@link #ACTION}, {@link #ACTION_INFO},
* {@link #UNKNOWN}.
*/
public
MBeanOperationInfo
(
String
name
,
String
description
,
...
...
@@ -140,8 +146,9 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
* describing the parameters(arguments) of the method. This may be
* null with the same effect as a zero-length array.
* @param type The type of the method's return value.
* @param impact The impact of the method, one of <CODE>INFO,
* ACTION, ACTION_INFO, UNKNOWN</CODE>.
* @param impact The impact of the method, one of
* {@link #INFO}, {@link #ACTION}, {@link #ACTION_INFO},
* {@link #UNKNOWN}.
* @param descriptor The descriptor for the operation. This may be null
* which is equivalent to an empty descriptor.
*
...
...
@@ -319,9 +326,14 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
for
(
int
i
=
0
;
i
<
classes
.
length
;
i
++)
{
Descriptor
d
=
Introspector
.
descriptorForAnnotations
(
annots
[
i
]);
final
String
pn
=
"p"
+
(
i
+
1
);
params
[
i
]
=
new
MBeanParameterInfo
(
pn
,
classes
[
i
].
getName
(),
""
,
d
);
String
description
=
Introspector
.
descriptionForParameter
(
annots
[
i
]);
if
(
description
==
null
)
description
=
""
;
String
name
=
Introspector
.
nameForParameter
(
annots
[
i
]);
if
(
name
==
null
)
name
=
"p"
+
(
i
+
1
);
params
[
i
]
=
new
MBeanParameterInfo
(
name
,
classes
[
i
].
getName
(),
description
,
d
);
}
return
params
;
...
...
src/share/classes/javax/management/MBeanRegistration.java
浏览文件 @
a311994c
...
...
@@ -27,9 +27,101 @@ package javax.management;
/**
* Can be implemented by an MBean in order to
*
<p>
Can be implemented by an MBean in order to
* carry out operations before and after being registered or unregistered from
* the MBean server.
* the MBean Server. An MBean can also implement this interface in order
* to get a reference to the MBean Server and/or its name within that
* MBean Server.</p>
*
* <h4 id="injection">Resource injection</h4>
*
* <p>As an alternative to implementing {@code MBeanRegistration}, if all that
* is needed is the MBean Server or ObjectName then an MBean can use
* <em>resource injection</em>.</p>
*
* <p>If a field in the MBean object has type {@link ObjectName} and has
* the {@link javax.annotation.Resource @Resource} annotation,
* then the {@code ObjectName} under which the MBean is registered is
* assigned to that field during registration. Likewise, if a field has type
* {@link MBeanServer} and the <code>@Resource</code> annotation, then it will
* be set to the {@code MBeanServer} in which the MBean is registered.</p>
*
* <p>For example:</p>
*
* <pre>
* public Configuration implements ConfigurationMBean {
* @Resource
* private volatile MBeanServer mbeanServer;
* @Resource
* private volatile ObjectName objectName;
* ...
* void unregisterSelf() throws Exception {
* mbeanServer.unregisterMBean(objectName);
* }
* }
* </pre>
*
* <p>Resource injection can also be used on fields of type
* {@link SendNotification} to simplify notification sending. Such a field
* will get a reference to an object of type {@code SendNotification} when
* the MBean is registered, and it can use this reference to send notifications.
* For example:</p>
*
* <pre>
* public Configuration implements ConfigurationMBean {
* @Resource
* private volatile SendNotification sender;
* ...
* private void updated() {
* Notification n = new Notification(...);
* sender.sendNotification(n);
* }
* }
* </pre>
*
* <p>A field to be injected must not be static. It is recommended that
* such fields be declared {@code volatile}.</p>
*
* <p>It is also possible to use the <code>@Resource</code> annotation on
* methods. Such a method must have a {@code void} return type and a single
* argument of the appropriate type, for example {@code ObjectName}.</p>
*
* <p>Any number of fields and methods may have the <code>@Resource</code>
* annotation. All fields and methods with type {@code ObjectName}
* (for example) will receive the same {@code ObjectName} value.</p>
*
* <p>Resource injection is available for all types of MBeans, not just
* Standard MBeans.</p>
*
* <p>If an MBean implements the {@link DynamicWrapperMBean} interface then
* resource injection happens on the object returned by that interface's
* {@link DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method
* rather than on the MBean object itself.
*
* <p>Resource injection happens after the {@link #preRegister preRegister}
* method is called (if any), and before the MBean is actually registered
* in the MBean Server. If a <code>@Resource</code> method throws
* an exception, the effect is the same as if {@code preRegister} had
* thrown the exception. In particular it will prevent the MBean from being
* registered.</p>
*
* <p>Resource injection can be used on a field or method where the type
* is a parent of the injected type, if the injected type is explicitly
* specified in the <code>@Resource</code> annotation. For example:</p>
*
* <pre>
* @Resource(type = MBeanServer.class)
* private volatile MBeanServerConnection mbsc;
* </pre>
*
* <p>Formally, suppose <em>R</em> is the type in the <code>@Resource</code>
* annotation and <em>T</em> is the type of the method parameter or field.
* Then one of <em>R</em> and <em>T</em> must be a subtype of the other
* (or they must be the same type). Injection happens if this subtype
* is {@code MBeanServer}, {@code ObjectName}, or {@code SendNotification}.
* Otherwise the <code>@Resource</code> annotation is ignored.</p>
*
* <p>Resource injection in MBeans is new in version 2.0 of the JMX API.</p>
*
* @since 1.5
*/
...
...
@@ -38,12 +130,12 @@ public interface MBeanRegistration {
/**
* Allows the MBean to perform any operations it needs before
* being registered in the MBean
s
erver. If the name of the MBean
* being registered in the MBean
S
erver. If the name of the MBean
* is not specified, the MBean can provide a name for its
* registration. If any exception is raised, the MBean will not be
* registered in the MBean
s
erver.
* registered in the MBean
S
erver.
*
* @param server The MBean
s
erver in which the MBean will be registered.
* @param server The MBean
S
erver in which the MBean will be registered.
*
* @param name The object name of the MBean. This name is null if
* the name parameter to one of the <code>createMBean</code> or
...
...
@@ -57,7 +149,7 @@ public interface MBeanRegistration {
* the returned value.
*
* @exception java.lang.Exception This exception will be caught by
* the MBean
s
erver and re-thrown as an {@link
* the MBean
S
erver and re-thrown as an {@link
* MBeanRegistrationException}.
*/
public
ObjectName
preRegister
(
MBeanServer
server
,
...
...
src/share/classes/javax/management/MBeanServer.java
浏览文件 @
a311994c
...
...
@@ -61,7 +61,7 @@ import javax.management.loading.ClassLoaderRepository;
* <CODE>ObjectName</CODE> is: <BR>
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.</p>
*
* <p>An object obtained from the {@link
* <p
id="security"
>An object obtained from the {@link
* MBeanServerFactory#createMBeanServer(String) createMBeanServer} or
* {@link MBeanServerFactory#newMBeanServer(String) newMBeanServer}
* methods of the {@link MBeanServerFactory} class applies security
...
...
@@ -661,13 +661,16 @@ public interface MBeanServer extends MBeanServerConnection {
ReflectionException
;
/**
* <p>Return the {@link java.lang.ClassLoader} that was used for
* loading the class of the named MBean.</p>
* <p>Return the {@link java.lang.ClassLoader} that was used for loading
* the class of the named MBean. If the MBean implements the {@link
* DynamicWrapperMBean} interface, then the returned value is the
* result of the {@link DynamicWrapperMBean#getWrappedClassLoader()}
* method.</p>
*
* @param mbeanName The ObjectName of the MBean.
*
* @return The ClassLoader used for that MBean. If <var>l</var>
* is the
MBean's actual ClassLoader
, and <var>r</var> is the
* is the
value specified by the rules above
, and <var>r</var> is the
* returned value, then either:
*
* <ul>
...
...
src/share/classes/javax/management/MBeanServerConnection.java
浏览文件 @
a311994c
...
...
@@ -839,6 +839,12 @@ public interface MBeanServerConnection {
*
* <p>Otherwise, the result is false.</p>
*
* <p>If the MBean implements the {@link DynamicWrapperMBean}
* interface, then in the above rules X is the result of the MBean's {@link
* DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method and L
* is the result of its {@link DynamicWrapperMBean#getWrappedClassLoader()
* getWrappedClassLoader()} method.
*
* @param name The <CODE>ObjectName</CODE> of the MBean.
* @param className The name of the class.
*
...
...
src/share/classes/javax/management/MXBean.java
浏览文件 @
a311994c
...
...
@@ -27,6 +27,7 @@ package javax.management;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
...
...
@@ -57,11 +58,13 @@ import javax.management.openmbean.TabularDataSupport;
import
javax.management.openmbean.TabularType
;
/**
<p>Annotation to mark a
n interface explicitly as being an MXBean
interface, or as not being an MXBean interface
. By default, an
<p>Annotation to mark a
class or interface explicitly as being an MXBean,
or as not being an MXBean
. By default, an
interface is an MXBean interface if its name ends with {@code
MXBean}, as in {@code SomethingMXBean}. The following interfaces
are MXBean interfaces:</p>
MXBean}, as in {@code SomethingMXBean}. A class is never an MXBean by
default.</p>
<p>The following interfaces are MXBean interfaces:</p>
<pre>
public interface WhatsitMXBean {}
...
...
@@ -82,6 +85,11 @@ import javax.management.openmbean.TabularType;
public interface MisleadingMXBean {}
</pre>
<p>A class can be annotated with {@code @MXBean} to indicate that it
is an MXBean. In this case, its methods should have <code>@{@link
ManagedAttribute}</code> or <code>@{@link ManagedOperation}</code>
annotations, as described for <code>@{@link MBean}</code>.</p>
<h3 id="MXBean-spec">MXBean specification</h3>
<p>The MXBean concept provides a simple way to code an MBean
...
...
@@ -1246,9 +1254,24 @@ public interface Node {
@since 1.6
*/
/*
* This annotation is @Inherited because if an MXBean is defined as a
* class using annotations, then its subclasses are also MXBeans.
* For example:
* @MXBean
* public class Super {
* @ManagedAttribute
* public String getName() {...}
* }
* public class Sub extends Super {}
* Here Sub is an MXBean.
*
* The @Inherited annotation has no effect when applied to an interface.
*/
@Documented
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
@Inherited
public
@interface
MXBean
{
/**
True if the annotated interface is an MXBean interface.
...
...
src/share/classes/javax/management/ManagedAttribute.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* <p>Indicates that a method in an MBean class defines an MBean attribute.
* This annotation must be applied to a public method of a public class
* that is itself annotated with an {@link MBean @MBean} or
* {@link MXBean @MXBean} annotation, or inherits such an annotation from
* a superclass.</p>
*
* <p>The annotated method must be a getter or setter. In other words,
* it must look like one of the following...</p>
*
* <pre>
* <i>T</i> get<i>Foo</i>()
* void set<i>Foo</i>(<i>T</i> param)
* </pre>
*
* <p>...where <i>{@code T}</i> is any type and <i>{@code Foo}</i> is the
* name of the attribute. For any attribute <i>{@code Foo}</i>, if only
* a {@code get}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
* annotation, then <i>{@code Foo}</i> is a read-only attribute. If only
* a {@code set}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
* annotation, then <i>{@code Foo}</i> is a write-only attribute. If
* both {@code get}<i>{@code Foo}</i> and {@code set}<i>{@code Foo}</i>
* methods have the annotation, then <i>{@code Foo}</i> is a read-write
* attribute. In this last case, the type <i>{@code T}</i> must be the
* same in both methods.</p>
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
METHOD
)
@Documented
public
@interface
ManagedAttribute
{
}
src/share/classes/javax/management/ManagedOperation.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* <p>Indicates that a method in an MBean class defines an MBean operation.
* This annotation can be applied to:</p>
*
* <ul>
* <li>A public method of a public class
* that is itself annotated with an {@link MBean @MBean} or
* {@link MXBean @MXBean} annotation, or inherits such an annotation from
* a superclass.</li>
* <li>A method of an MBean or MXBean interface.
* </ul>
*
* <p>Every method in an MBean or MXBean interface defines an MBean
* operation even without this annotation, but the annotation allows
* you to specify the impact of the operation:</p>
*
* <pre>
* public interface ConfigurationMBean {
* {@code @ManagedOperation}(impact = {@link Impact#ACTION Impact.ACTION})
* public void save();
* ...
* }
* </pre>
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
METHOD
)
@Documented
public
@interface
ManagedOperation
{
/**
* <p>The impact of this operation, as shown by
* {@link MBeanOperationInfo#getImpact()}.
*/
Impact
impact
()
default
Impact
.
UNKNOWN
;
}
src/share/classes/javax/management/NotQueryExp.java
浏览文件 @
a311994c
...
...
@@ -91,6 +91,7 @@ class NotQueryExp extends QueryEval implements QueryExp {
return
"not ("
+
exp
+
")"
;
}
@Override
String
toQueryString
()
{
return
"not ("
+
Query
.
toString
(
exp
)
+
")"
;
}
...
...
src/share/classes/javax/management/NotificationBroadcasterSupport.java
浏览文件 @
a311994c
...
...
@@ -58,7 +58,8 @@ import com.sun.jmx.remote.util.ClassLogger;
*
* @since 1.5
*/
public
class
NotificationBroadcasterSupport
implements
NotificationEmitter
{
public
class
NotificationBroadcasterSupport
implements
NotificationEmitter
,
SendNotification
{
/**
* Constructs a NotificationBroadcasterSupport where each listener is invoked by the
* thread sending the notification. This constructor is equivalent to
...
...
src/share/classes/javax/management/NotificationInfo.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* <p>Specifies the kinds of notification an MBean can emit. In both the
* following examples, the MBean emits notifications of type
* {@code "com.example.notifs.create"} and of type
* {@code "com.example.notifs.destroy"}:</p>
*
* <pre>
* // Example one: a Standard MBean
* {@code @NotificationInfo}(types={"com.example.notifs.create",
* "com.example.notifs.destroy"})
* public interface CacheMBean {...}
*
* public class Cache implements CacheMBean {...}
* </pre>
*
* <pre>
* // Example two: an annotated MBean
* {@link MBean @MBean}
* {@code @NotificationInfo}(types={"com.example.notifs.create",
* "com.example.notifs.destroy"})
* public class Cache {...}
* </pre>
*
* <p>Each {@code @NotificationInfo} produces an {@link
* MBeanNotificationInfo} inside the {@link MBeanInfo} of each MBean
* to which the annotation applies.</p>
*
* <p>If you need to specify different notification classes, or different
* descriptions for different notification types, then you can group
* several {@code @NotificationInfo} annotations into a containing
* {@link NotificationInfos @NotificationInfos} annotation.
*
* <p>The {@code NotificationInfo} and {@code NotificationInfos}
* annotations can be applied to the MBean implementation class, or to
* any parent class or interface. These annotations on a class take
* precedence over annotations on any superclass or superinterface.
* If an MBean does not have these annotations on its class or any
* superclass, then superinterfaces are examined. It is an error for
* more than one superinterface to have these annotations, unless one
* of them is a child of all the others.</p>
*/
@Documented
@Inherited
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
NotificationInfo
{
/**
* <p>The {@linkplain Notification#getType() notification types}
* that this MBean can emit.</p>
*/
String
[]
types
();
/**
* <p>The class that emitted notifications will have. It is recommended
* that this be {@link Notification}, or one of its standard subclasses
* in the JMX API.</p>
*/
Class
<?
extends
Notification
>
notificationClass
()
default
Notification
.
class
;
/**
* <p>The description of this notification. For example:
*
* <pre>
* {@code @NotificationInfo}(
* types={"com.example.notifs.create"},
* description={@code @Description}("object created"))
* </pre>
*/
Description
description
()
default
@Description
(
""
);
/**
* <p>Additional descriptor fields for the derived {@code
* MBeanNotificationInfo}. They are specified in the same way as
* for the {@link DescriptorFields @DescriptorFields} annotation,
* for example:</p>
* <pre>
* {@code @NotificationInfo}(
* types={"com.example.notifs.create"},
* descriptorFields={"severity=6"})
* </pre>
*/
String
[]
descriptorFields
()
default
{};
}
src/share/classes/javax/management/NotificationInfos.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Inherited
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
javax.management.remote.JMXConnectionNotification
;
/**
* <p>Specifies the kinds of notification an MBean can emit, when this
* cannot be represented by a single {@link NotificationInfo
* @NotificationInfo} annotation.</p>
*
* <p>For example, this annotation specifies that an MBean can emit
* {@link AttributeChangeNotification} and {@link
* JMXConnectionNotification}:</p>
*
* <pre>
* {@code @NotificationInfos}(
* {@code @NotificationInfo}(
* types = {{@link AttributeChangeNotification#ATTRIBUTE_CHANGE}},
* notificationClass = AttributeChangeNotification.class),
* {@code @NotificationInfo}(
* types = {{@link JMXConnectionNotification#OPENED},
* {@link JMXConnectionNotification#CLOSED}},
* notificationClass = JMXConnectionNotification.class)
* )
* </pre>
*
* <p>If an MBean has both {@code NotificationInfo} and {@code
* NotificationInfos} on the same class or interface, the effect is
* the same as if the {@code NotificationInfo} were moved inside the
* {@code NotificationInfos}.</p>
*/
@Documented
@Inherited
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
NotificationInfos
{
/**
* <p>The {@link NotificationInfo} annotations.</p>
*/
NotificationInfo
[]
value
();
}
src/share/classes/javax/management/SendNotification.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
/**
* Interface implemented by objects that can be asked to send a notification.
*/
public
interface
SendNotification
{
/**
* Sends a notification.
*
* @param notification The notification to send.
*/
public
void
sendNotification
(
Notification
notification
);
}
src/share/classes/javax/management/StandardEmitterMBean.java
浏览文件 @
a311994c
...
...
@@ -25,6 +25,9 @@
package
javax.management
;
import
com.sun.jmx.mbeanserver.MBeanInjector
;
import
static
javax
.
management
.
JMX
.
MBeanOptions
;
/**
* <p>An MBean whose management interface is determined by reflection
* on a Java interface, and that emits notifications.</p>
...
...
@@ -62,7 +65,7 @@ package javax.management;
* @since 1.6
*/
public
class
StandardEmitterMBean
extends
StandardMBean
implements
NotificationEmitter
{
implements
NotificationEmitter
,
SendNotification
{
private
final
NotificationEmitter
emitter
;
private
final
MBeanNotificationInfo
[]
notificationInfo
;
...
...
@@ -76,9 +79,10 @@ public class StandardEmitterMBean extends StandardMBean
* for {@code implementation} and {@code emitter} to be the same object.</p>
*
* <p>If {@code emitter} is an instance of {@code
* NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
*
NotificationBroadcasterSupport
#sendNotification sendNotification}.</p>
*
SendNotification
#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
...
...
@@ -90,20 +94,18 @@ public class StandardEmitterMBean extends StandardMBean
*
* @param implementation the implementation of the MBean interface.
* @param mbeanInterface a Standard MBean interface.
* @param emitter the object that will handle notifications.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if the given {@code implementation} does not implement the
* specified interface
, or if {@code emitter} is null
.
* specified interface.
*/
public
<
T
>
StandardEmitterMBean
(
T
implementation
,
Class
<
T
>
mbeanInterface
,
NotificationEmitter
emitter
)
{
super
(
implementation
,
mbeanInterface
,
false
);
if
(
emitter
==
null
)
throw
new
IllegalArgumentException
(
"Null emitter"
);
this
.
emitter
=
emitter
;
this
.
notificationInfo
=
emitter
.
getNotificationInfo
();
this
(
implementation
,
mbeanInterface
,
false
,
emitter
);
}
/**
...
...
@@ -118,9 +120,10 @@ public class StandardEmitterMBean extends StandardMBean
* same object.</p>
*
* <p>If {@code emitter} is an instance of {@code
* NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
*
NotificationBroadcasterSupport
#sendNotification sendNotification}.</p>
*
SendNotification
#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
...
...
@@ -134,21 +137,69 @@ public class StandardEmitterMBean extends StandardMBean
* @param mbeanInterface a Standard MBean interface.
* @param isMXBean If true, the {@code mbeanInterface} parameter
* names an MXBean interface and the resultant MBean is an MXBean.
* @param emitter the object that will handle notifications.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if the given {@code implementation} does not implement the
* specified interface
, or if {@code emitter} is null
.
* specified interface.
*/
public
<
T
>
StandardEmitterMBean
(
T
implementation
,
Class
<
T
>
mbeanInterface
,
boolean
isMXBean
,
NotificationEmitter
emitter
)
{
super
(
implementation
,
mbeanInterface
,
isMXBean
);
this
(
implementation
,
mbeanInterface
,
isMXBean
?
MBeanOptions
.
MXBEAN
:
null
,
emitter
);
}
/**
* <p>Make an MBean whose management interface is specified by {@code
* mbeanInterface}, with the given implementation and options, and where
* notifications are handled by the given {@code NotificationEmitter}.
* Options select whether to make a Standard MBean or an MXBean, and
* whether the result of {@link #getWrappedObject()} is the {@code
* StandardEmitterMBean} object or the given implementation. The resultant
* MBean implements the {@code NotificationEmitter} interface by forwarding
* its methods to {@code emitter}. It is legal and useful for {@code
* implementation} and {@code emitter} to be the same object.</p>
*
* <p>If {@code emitter} is an instance of {@code
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
* SendNotification#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
* {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
* getNotificationInfo()} at the time of construction. If the array
* returned by {@code emitter.getNotificationInfo()} later changes,
* that will have no effect on this object's
* {@code getNotificationInfo()}.</p>
*
* @param implementation the implementation of the MBean interface.
* @param mbeanInterface a Standard MBean interface.
* @param options MBeanOptions that control the operation of the resulting
* MBean.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if the given {@code implementation} does not implement the
* specified interface.
*/
public
<
T
>
StandardEmitterMBean
(
T
implementation
,
Class
<
T
>
mbeanInterface
,
MBeanOptions
options
,
NotificationEmitter
emitter
)
{
super
(
implementation
,
mbeanInterface
,
options
);
if
(
emitter
==
null
)
throw
new
IllegalArgumentException
(
"Null emitter"
);
emitter
=
defaultEmitter
(
);
this
.
emitter
=
emitter
;
this
.
notificationInfo
=
emitter
.
getNotificationInfo
();
injectEmitter
();
}
/**
...
...
@@ -159,9 +210,10 @@ public class StandardEmitterMBean extends StandardMBean
* by forwarding its methods to {@code emitter}.</p>
*
* <p>If {@code emitter} is an instance of {@code
* NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
*
NotificationBroadcasterSupport
#sendNotification sendNotification}.</p>
*
SendNotification
#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
...
...
@@ -175,20 +227,17 @@ public class StandardEmitterMBean extends StandardMBean
* the given {@code mbeanInterface}.</p>
*
* @param mbeanInterface a StandardMBean interface.
* @param emitter the object that will handle notifications.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if {@code this} does not implement the specified interface, or
* if {@code emitter} is null.
* if {@code this} does not implement the specified interface.
*/
protected
StandardEmitterMBean
(
Class
<?>
mbeanInterface
,
NotificationEmitter
emitter
)
{
super
(
mbeanInterface
,
false
);
if
(
emitter
==
null
)
throw
new
IllegalArgumentException
(
"Null emitter"
);
this
.
emitter
=
emitter
;
this
.
notificationInfo
=
emitter
.
getNotificationInfo
();
this
(
mbeanInterface
,
false
,
emitter
);
}
/**
...
...
@@ -200,9 +249,10 @@ public class StandardEmitterMBean extends StandardMBean
* forwarding its methods to {@code emitter}.</p>
*
* <p>If {@code emitter} is an instance of {@code
* NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
*
NotificationBroadcasterSupport
#sendNotification sendNotification}.</p>
*
SendNotification
#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
...
...
@@ -218,20 +268,86 @@ public class StandardEmitterMBean extends StandardMBean
* @param mbeanInterface a StandardMBean interface.
* @param isMXBean If true, the {@code mbeanInterface} parameter
* names an MXBean interface and the resultant MBean is an MXBean.
* @param emitter the object that will handle notifications.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if {@code this} does not implement the specified interface, or
* if {@code emitter} is null.
* if {@code this} does not implement the specified interface.
*/
protected
StandardEmitterMBean
(
Class
<?>
mbeanInterface
,
boolean
isMXBean
,
NotificationEmitter
emitter
)
{
super
(
mbeanInterface
,
isMXBean
);
this
(
mbeanInterface
,
isMXBean
?
MBeanOptions
.
MXBEAN
:
null
,
emitter
);
}
/**
* <p>Make an MBean whose management interface is specified by {@code
* mbeanInterface}, with the given options, and where notifications are
* handled by the given {@code NotificationEmitter}. This constructor can
* be used to make either Standard MBeans or MXBeans. The resultant MBean
* implements the {@code NotificationEmitter} interface by forwarding its
* methods to {@code emitter}.</p>
*
* <p>If {@code emitter} is an instance of {@code
* SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
* then the MBean's {@link #sendNotification
* sendNotification} method will call {@code emitter.}{@link
* SendNotification#sendNotification sendNotification}.</p>
*
* <p>The array returned by {@link #getNotificationInfo()} on the
* new MBean is a copy of the array returned by
* {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
* getNotificationInfo()} at the time of construction. If the array
* returned by {@code emitter.getNotificationInfo()} later changes,
* that will have no effect on this object's
* {@code getNotificationInfo()}.</p>
*
* <p>This constructor must be called from a subclass that implements
* the given {@code mbeanInterface}.</p>
*
* @param mbeanInterface a StandardMBean interface.
* @param options MBeanOptions that control the operation of the resulting
* MBean.
* @param emitter the object that will handle notifications. If null,
* a new {@code NotificationEmitter} will be constructed that also
* implements {@link SendNotification}.
*
* @throws IllegalArgumentException if the {@code mbeanInterface}
* does not follow JMX design patterns for Management Interfaces, or
* if {@code this} does not implement the specified interface.
*/
protected
StandardEmitterMBean
(
Class
<?>
mbeanInterface
,
MBeanOptions
options
,
NotificationEmitter
emitter
)
{
super
(
mbeanInterface
,
options
);
if
(
emitter
==
null
)
throw
new
IllegalArgumentException
(
"Null emitter"
);
emitter
=
defaultEmitter
(
);
this
.
emitter
=
emitter
;
this
.
notificationInfo
=
emitter
.
getNotificationInfo
();
injectEmitter
();
}
private
NotificationEmitter
defaultEmitter
()
{
MBeanNotificationInfo
[]
mbnis
=
getNotificationInfo
();
// Will be null unless getNotificationInfo() is overridden,
// since the notificationInfo field has not been set at this point.
if
(
mbnis
==
null
)
mbnis
=
getMBeanInfo
().
getNotifications
();
return
new
NotificationBroadcasterSupport
(
mbnis
);
}
private
void
injectEmitter
()
{
if
(
emitter
instanceof
SendNotification
)
{
try
{
Object
resource
=
getImplementation
();
SendNotification
send
=
(
SendNotification
)
emitter
;
MBeanInjector
.
injectSendNotification
(
resource
,
send
);
}
catch
(
RuntimeException
e
)
{
throw
e
;
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
e
);
}
}
}
public
void
removeNotificationListener
(
NotificationListener
listener
)
...
...
@@ -259,10 +375,10 @@ public class StandardEmitterMBean extends StandardMBean
/**
* <p>Sends a notification.</p>
*
* <p>If the {@code emitter} parameter to the constructor was
an
*
instance of {@code NotificationBroadcasterSupport} then this
*
method will call {@code emitter.}{@link
*
NotificationBroadcasterSupport
#sendNotification
* <p>If the {@code emitter} parameter to the constructor was
*
an instance of {@link SendNotification}, such as {@link
*
NotificationBroadcasterSupport}, then this method will call {@code
*
emitter.}{@link SendNotification
#sendNotification
* sendNotification}.</p>
*
* @param n the notification to send.
...
...
@@ -271,13 +387,12 @@ public class StandardEmitterMBean extends StandardMBean
* constructor was not a {@code NotificationBroadcasterSupport}.
*/
public
void
sendNotification
(
Notification
n
)
{
if
(
emitter
instanceof
NotificationBroadcasterSupport
)
((
NotificationBroadcasterSupport
)
emitter
).
sendNotification
(
n
);
if
(
emitter
instanceof
SendNotification
)
((
SendNotification
)
emitter
).
sendNotification
(
n
);
else
{
final
String
msg
=
"Cannot sendNotification when emitter is not an "
+
"instance of NotificationBroadcasterSupport: "
+
emitter
.
getClass
().
getName
();
"instance of SendNotification: "
+
emitter
.
getClass
().
getName
();
throw
new
ClassCastException
(
msg
);
}
}
...
...
@@ -292,6 +407,7 @@ public class StandardEmitterMBean extends StandardMBean
* @param info The default MBeanInfo derived by reflection.
* @return the MBeanNotificationInfo[] for the new MBeanInfo.
*/
@Override
MBeanNotificationInfo
[]
getNotifications
(
MBeanInfo
info
)
{
return
getNotificationInfo
();
}
...
...
src/share/classes/javax/management/StandardMBean.java
浏览文件 @
a311994c
...
...
@@ -27,6 +27,7 @@ package javax.management;
import
com.sun.jmx.mbeanserver.DescriptorCache
;
import
com.sun.jmx.mbeanserver.Introspector
;
import
com.sun.jmx.mbeanserver.MBeanInjector
;
import
com.sun.jmx.mbeanserver.MBeanSupport
;
import
com.sun.jmx.mbeanserver.MXBeanSupport
;
import
com.sun.jmx.mbeanserver.StandardMBeanSupport
;
...
...
@@ -125,7 +126,78 @@ import static javax.management.JMX.MBeanOptions;
*
* @since 1.5
*/
public
class
StandardMBean
implements
DynamicMBean
,
MBeanRegistration
{
public
class
StandardMBean
implements
DynamicWrapperMBean
,
MBeanRegistration
{
/**
* <p>Options controlling the behavior of {@code StandardMBean} instances.</p>
*/
public
static
class
Options
extends
JMX
.
MBeanOptions
{
private
static
final
long
serialVersionUID
=
5107355471177517164L
;
private
boolean
wrappedVisible
;
/**
* <p>Construct an {@code Options} object where all options have
* their default values.</p>
*/
public
Options
()
{}
@Override
public
Options
clone
()
{
return
(
Options
)
super
.
clone
();
}
/**
* <p>Defines whether the {@link StandardMBean#getWrappedObject()
* getWrappedObject} method returns the wrapped object.</p>
*
* <p>If this option is true, then {@code getWrappedObject()} will return
* the same object as {@link StandardMBean#getImplementation()
* getImplementation}. Otherwise, it will return the
* StandardMBean instance itself. The setting of this option
* affects the behavior of {@link MBeanServer#getClassLoaderFor
* MBeanServer.getClassLoaderFor} and {@link MBeanServer#isInstanceOf
* MBeanServer.isInstanceOf}. The default value is false for
* compatibility reasons, but true is a better value for most new code.</p>
*
* @return true if this StandardMBean's {@link
* StandardMBean#getWrappedObject getWrappedObject} returns the wrapped
* object.
*/
public
boolean
isWrappedObjectVisible
()
{
return
this
.
wrappedVisible
;
}
/**
* <p>Set the {@link #isWrappedObjectVisible WrappedObjectVisible} option
* to the given value.</p>
* @param visible the new value.
*/
public
void
setWrappedObjectVisible
(
boolean
visible
)
{
this
.
wrappedVisible
=
visible
;
}
// Canonical objects for each of (MXBean,!MXBean) x (WVisible,!WVisible)
private
static
final
Options
[]
CANONICALS
=
{
new
Options
(),
new
Options
(),
new
Options
(),
new
Options
(),
};
static
{
CANONICALS
[
1
].
setMXBeanMappingFactory
(
MXBeanMappingFactory
.
DEFAULT
);
CANONICALS
[
2
].
setWrappedObjectVisible
(
true
);
CANONICALS
[
3
].
setMXBeanMappingFactory
(
MXBeanMappingFactory
.
DEFAULT
);
CANONICALS
[
3
].
setWrappedObjectVisible
(
true
);
}
@Override
MBeanOptions
[]
canonicals
()
{
return
CANONICALS
;
}
@Override
boolean
same
(
MBeanOptions
opts
)
{
return
(
super
.
same
(
opts
)
&&
opts
instanceof
Options
&&
((
Options
)
opts
).
wrappedVisible
==
wrappedVisible
);
}
}
private
final
static
DescriptorCache
descriptors
=
DescriptorCache
.
getInstance
(
JMX
.
proof
);
...
...
@@ -347,7 +419,7 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
* the management interface associated with the given
* implementation.
* @param options MBeanOptions that control the operation of the resulting
* MBean
, as documented in the {@link MBeanOptions} class
.
* MBean.
* @param <T> Allows the compiler to check
* that {@code implementation} does indeed implement the class
* described by {@code mbeanInterface}. The compiler can only
...
...
@@ -381,7 +453,7 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
* @param mbeanInterface The Management Interface exported by this
* MBean.
* @param options MBeanOptions that control the operation of the resulting
* MBean
, as documented in the {@link MBeanOptions} class
.
* MBean.
*
* @exception IllegalArgumentException if the <var>mbeanInterface</var>
* does not follow JMX design patterns for Management Interfaces, or
...
...
@@ -441,7 +513,67 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
* @see #setImplementation
**/
public
Object
getImplementation
()
{
return
mbean
.
getResource
();
return
mbean
.
getWrappedObject
();
}
/**
* <p>Get the wrapped implementation object or return this object.</p>
*
* <p>For compatibility reasons, this method only returns the wrapped
* implementation object if the {@link Options#isWrappedObjectVisible
* WrappedObjectVisible} option was specified when this StandardMBean
* was created. Otherwise it returns {@code this}.</p>
*
* <p>If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor
* getClassLoaderFor} and {@link MBeanServer#isInstanceOf
* isInstanceOf} methods to refer to the wrapped implementation and
* not this StandardMBean object, then you must set the
* {@code WrappedObjectVisible} option, for example using:</p>
*
* <pre>
* StandardMBean.Options opts = new StandardMBean.Options();
* opts.setWrappedObjectVisible(true);
* StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
* </pre>
*
* @return The wrapped implementation object, or this StandardMBean
* instance.
*/
public
Object
getWrappedObject
()
{
if
(
options
instanceof
Options
&&
((
Options
)
options
).
isWrappedObjectVisible
())
return
getImplementation
();
else
return
this
;
}
/**
* <p>Get the ClassLoader of the wrapped implementation object or of this
* object.</p>
*
* <p>For compatibility reasons, this method only returns the ClassLoader
* of the wrapped implementation object if the {@link
* Options#isWrappedObjectVisible WrappedObjectVisible} option was
* specified when this StandardMBean was created. Otherwise it returns
* {@code this.getClass().getClassLoader()}.</p>
*
* <p>If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor
* getClassLoaderFor} and {@link MBeanServer#isInstanceOf
* isInstanceOf} methods to refer to the wrapped implementation and
* not this StandardMBean object, then you must set the
* {@code WrappedObjectVisible} option, for example using:</p>
*
* <pre>
* StandardMBean.Options opts = new StandardMBean.Options();
* opts.setWrappedObjectVisible(true);
* StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
* </pre>
*
* @return The ClassLoader of the wrapped Cimplementation object, or of
* this StandardMBean instance.
*/
public
ClassLoader
getWrappedClassLoader
()
{
return
getWrappedObject
().
getClass
().
getClassLoader
();
}
/**
...
...
@@ -457,7 +589,7 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
* @return The class of the implementation of this Standard MBean (or MXBean).
**/
public
Class
<?>
getImplementationClass
()
{
return
mbean
.
get
Resource
().
getClass
();
return
mbean
.
get
WrappedObject
().
getClass
();
}
/**
...
...
@@ -559,7 +691,7 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
MBeanSupport
msupport
=
mbean
;
final
MBeanInfo
bi
=
msupport
.
getMBeanInfo
();
final
Object
impl
=
msupport
.
get
Resource
();
final
Object
impl
=
msupport
.
get
WrappedObject
();
final
boolean
immutableInfo
=
immutableInfo
(
this
.
getClass
());
...
...
@@ -1184,6 +1316,7 @@ public class StandardMBean implements DynamicMBean, MBeanRegistration {
public
ObjectName
preRegister
(
MBeanServer
server
,
ObjectName
name
)
throws
Exception
{
mbean
.
register
(
server
,
name
);
MBeanInjector
.
inject
(
mbean
.
getWrappedObject
(),
server
,
name
);
return
name
;
}
...
...
src/share/classes/javax/management/modelmbean/RequiredModelMBean.java
浏览文件 @
a311994c
...
...
@@ -23,7 +23,7 @@
* have any questions.
*/
/*
* @author IBM Corp.
* @
(#)
author IBM Corp.
*
* Copyright IBM Corp. 1999-2000. All rights reserved.
*/
...
...
@@ -55,6 +55,7 @@ import javax.management.AttributeChangeNotificationFilter;
import
javax.management.AttributeList
;
import
javax.management.AttributeNotFoundException
;
import
javax.management.Descriptor
;
import
javax.management.DynamicWrapperMBean
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.InvalidAttributeValueException
;
import
javax.management.ListenerNotFoundException
;
...
...
@@ -115,7 +116,7 @@ import sun.reflect.misc.ReflectUtil;
*/
public
class
RequiredModelMBean
implements
ModelMBean
,
MBeanRegistration
,
NotificationEmitter
{
implements
ModelMBean
,
MBeanRegistration
,
NotificationEmitter
,
DynamicWrapperMBean
{
/*************************************/
/* attributes */
...
...
@@ -133,6 +134,9 @@ public class RequiredModelMBean
* and operations will be executed */
private
Object
managedResource
=
null
;
/* true if getWrappedObject returns the wrapped resource */
private
boolean
visible
;
/* records the registering in MBeanServer */
private
boolean
registered
=
false
;
private
transient
MBeanServer
server
=
null
;
...
...
@@ -318,9 +322,13 @@ public class RequiredModelMBean
*
* @param mr Object that is the managed resource
* @param mr_type The type of reference for the managed resource.
* <br>Can be: "ObjectReference", "Handle", "IOR", "EJBHandle",
* or "RMIReference".
* <br>In this implementation only "ObjectReference" is supported.
* <br>Can be: "ObjectReference", "VisibleObjectReference",
* "Handle", "IOR", "EJBHandle", or "RMIReference".
* <br>In this implementation only "ObjectReference" and
* "VisibleObjectReference" are supported. The two
* types are equivalent except for the behavior of the
* {@link #getWrappedObject()} and {@link #getWrappedClassLoader()}
* methods.
*
* @exception MBeanException The initializer of the object has
* thrown an exception.
...
...
@@ -340,10 +348,11 @@ public class RequiredModelMBean
"setManagedResource(Object,String)"
,
"Entry"
);
}
visible
=
"visibleObjectReference"
.
equalsIgnoreCase
(
mr_type
);
// check that the mr_type is supported by this JMXAgent
// only "objectReference" is supported
if
((
mr_type
==
null
)
||
(!
mr_type
.
equalsIgnoreCase
(
"objectReference"
)))
{
if
(!
"objectReference"
.
equalsIgnoreCase
(
mr_type
)
&&
!
visible
)
{
if
(
MODELMBEAN_LOGGER
.
isLoggable
(
Level
.
FINER
))
{
MODELMBEAN_LOGGER
.
logp
(
Level
.
FINER
,
RequiredModelMBean
.
class
.
getName
(),
...
...
@@ -368,6 +377,51 @@ public class RequiredModelMBean
}
}
/**
* <p>Get the managed resource for this Model MBean. For compatibility
* reasons, the managed resource is only returned if the resource type
* specified to {@link #setManagedResource setManagedResource} was {@code
* "visibleObjectReference"}. Otherwise, {@code this} is returned.</p>
*
* @return The value that was specified to {@link #setManagedResource
* setManagedResource}, if the resource type is {@code
* "visibleObjectReference"}. Otherwise, {@code this}.
*/
public
Object
getWrappedObject
()
{
if
(
visible
)
return
managedResource
;
else
return
this
;
}
/**
* <p>Get the ClassLoader of the managed resource for this Model MBean. For
* compatibility reasons, the ClassLoader of the managed resource is only
* returned if the resource type specified to {@link #setManagedResource
* setManagedResource} was {@code "visibleObjectReference"}. Otherwise,
* {@code this.getClass().getClassLoader()} is returned.</p>
*
* @return The ClassLoader of the value that was specified to
* {@link #setManagedResource setManagedResource}, if the resource
* type is {@code "visibleObjectReference"}. Otherwise, {@code
* this.getClass().getClassLoader()}.
*/
public
ClassLoader
getWrappedClassLoader
()
{
return
getWrappedObject
().
getClass
().
getClassLoader
();
}
private
static
boolean
isTrue
(
Descriptor
d
,
String
field
)
{
if
(
d
==
null
)
return
false
;
Object
x
=
d
.
getFieldValue
(
field
);
if
(
x
instanceof
Boolean
)
return
(
Boolean
)
x
;
if
(!(
x
instanceof
String
))
return
false
;
String
s
=
(
String
)
x
;
return
(
"true"
.
equalsIgnoreCase
(
s
)
||
"T"
.
equalsIgnoreCase
(
s
));
}
/**
* <p>Instantiates this MBean instance with the data found for
* the MBean in the persistent store. The data loaded could include
...
...
src/share/classes/javax/management/monitor/package.html
浏览文件 @
a311994c
...
...
@@ -38,14 +38,17 @@ have any questions.
so within the access control context of the
{@link javax.management.monitor.Monitor#start} caller.
</p>
<p>
The value being monitored can be a simple value contained within a
complex type. For example, the {@link java.lang.management.MemoryMXBean
MemoryMXBean} defined in
<tt>
java.lang.management
</tt>
has an attribute
<tt>
HeapMemoryUsage
</tt>
of type {@link java.lang.management.MemoryUsage
MemoryUsage}. To monitor the amount of
<i>
used
</i>
memory, described by
the
<tt>
used
</tt>
property of
<tt>
MemoryUsage
</tt>
, you could monitor
"
<tt>
HeapMemoryUsage.used
</tt>
". That string would be the argument to
{@link javax.management.monitor.MonitorMBean#setObservedAttribute(String)
<p
id=
"complex"
>
The value being monitored can be a simple value
contained within a complex type. For example, the {@link
java.lang.management.MemoryMXBean MemoryMXBean} defined in
<tt>
java.lang.management
</tt>
has an attribute
<tt>
HeapMemoryUsage
</tt>
of type {@link
java.lang.management.MemoryUsage MemoryUsage}. To monitor the
amount of
<i>
used
</i>
memory, described by the
<tt>
used
</tt>
property of
<tt>
MemoryUsage
</tt>
, you could monitor
"
<tt>
HeapMemoryUsage.used
</tt>
". That string would be the
argument to {@link
javax.management.monitor.MonitorMBean#setObservedAttribute(String)
setObservedAttribute}.
</p>
<p>
The rules used to interpret an
<tt>
ObservedAttribute
</tt>
like
...
...
src/share/classes/javax/management/package.html
浏览文件 @
a311994c
...
...
@@ -56,41 +56,41 @@ have any questions.
resource. It has a
<em>
management interface
</em>
consisting
of:
</p>
<ul>
<li>
named and typed attributes that can be read and/or
written
</li>
<li>
named and typed operations that can be invoked
</li>
<ul>
<li>
named and typed attributes that can be read and/or
written
</li>
<li>
typed notifications that can be emitted by the MBean.
</li>
</ul>
<li>
named and typed operations that can be invoked
</li>
<p>
For example, an MBean representing an application's
configuration could have attributes representing the different
configuration items. Reading the
<code>
CacheSize
</code>
attribute would return the current value of that item.
Writing it would update the item, potentially changing the
behavior of the running application. An operation such as
<code>
save
</code>
could store the current configuration
persistently. A notification such as
<code>
ConfigurationChangedNotification
</code>
could be sent
every time the configuration is changed.
</p>
<li>
typed notifications that can be emitted by the MBean.
</li>
</ul>
<p>
In the standard usage of the JMX API, MBeans are implemented
as Java objects. However, as explained below, these objects are
not usually referenced directly.
</p>
<p>
For example, an MBean representing an application's
configuration could have attributes representing the different
configuration items. Reading the
<code>
CacheSize
</code>
attribute would return the current value of that item.
Writing it would update the item, potentially changing the
behavior of the running application. An operation such as
<code>
save
</code>
could store the current configuration
persistently. A notification such as
<code>
ConfigurationChangedNotification
</code>
could be sent
every time the configuration is changed.
</p>
<p>
In the standard usage of the JMX API, MBeans are implemented
as Java objects. However, as explained below, these objects are
not usually referenced directly.
</p>
<h3>
Standard MBeans
</h3>
<p>
To make MBean implementation simple, the JMX API includes the
notion of
<em>
Standard MBeans
</em>
. A Standard MBean is one
whose attributes and operations are deduced from a Java
interface using certain naming patterns, similar to those used
by JavaBeans
<sup><font
size=
"-1"
>
TM
</font></sup>
. For
example, consider an interface like this:
</p>
<h3>
Standard MBeans
</h3>
<pre>
<p>
To make MBean implementation simple, the JMX API includes the
notion of
<em>
Standard MBeans
</em>
. A Standard MBean is one
whose attributes and operations are deduced from a Java
interface using certain naming patterns, similar to those used
by JavaBeans
<sup><font
size=
"-1"
>
TM
</font></sup>
. For
example, consider an interface like this:
</p>
<pre>
public interface ConfigurationMBean {
public int getCacheSize();
public void setCacheSize(int size);
...
...
@@ -128,107 +128,148 @@ have any questions.
class.
</p>
<h3>
MXBeans
</h3>
<p>
An
<em>
MXBean
</em>
is a variant of Standard MBean where complex
types are mapped to a standard set of types defined in the
{@link javax.management.openmbean} package. MXBeans are appropriate
if you would otherwise need to reference application-specific
classes in your MBean interface. They are described in detail
in the specification for {@link javax.management.MXBean MXBean}.
<h3>
Dynamic MBeans
</h3>
<p>
A
<em>
Dynamic MBean
</em>
is an MBean that defines its
management interface at run-time. For example, a configuration
MBean could determine the names and types of the attributes it
exposes by parsing an XML file.
</p>
<p>
Any Java object of a class that implements the {@link
javax.management.DynamicMBean DynamicMBean} interface is a
Dynamic MBean.
</p>
<h3>
Open MBeans
</h3>
<p>
An
<em>
Open MBean
</em>
is a kind of Dynamic MBean where the
types of attributes and of operation parameters and return
values are built using a small set of predefined Java classes.
Open MBeans facilitate operation with remote management programs
that do not necessarily have access to application-specific
types, including non-Java programs. Open MBeans are defined by
the package
<a
href=
"openmbean/package-summary.html"
><code>
javax.management.openmbean
</code></a>
.
</p>
<h3>
Model MBeans
</h3>
<p>
A
<em>
Model MBean
</em>
is a kind of Dynamic MBean that acts
as a bridge between the management interface and the
underlying managed resource. Both the management interface and
the managed resource are specified as Java objects. The same
Model MBean implementation can be reused many times with
different management interfaces and managed resources, and it can
provide common functionality such as persistence and caching.
Model MBeans are defined by the package
<a
href=
"modelmbean/package-summary.html"
><code>
javax.management.modelmbean
</code></a>
.
</p>
<h2>
MBean Server
</h2>
<p>
To be useful, an MBean must be registered in an
<em>
MBean
Server
</em>
. An MBean Server is a repository of MBeans.
Usually the only access to the MBeans is through the MBean
Server. In other words, code no longer accesses the Java
object implementing the MBean directly, but instead accesses
the MBean by name through the MBean Server. Each MBean has a
unique name within the MBean Server, defined by the {@link
javax.management.ObjectName ObjectName} class.
</p>
<p>
An MBean Server is an object implementing the interface
{@link javax.management.MBeanServer MBeanServer}.
The most convenient MBean Server to use is the
<em>
Platform MBean Server
</em>
. This is a
single MBean Server that can be shared by different managed
components running within the same Java Virtual Machine. The
Platform MBean Server is accessed with the method {@link
java.lang.management.ManagementFactory#getPlatformMBeanServer()}.
</p>
<p>
Application code can also create a new MBean Server, or
access already-created MBean Servers, using the {@link
javax.management.MBeanServerFactory MBeanServerFactory} class.
</p>
<h3>
Creating MBeans in the MBean Server
</h3>
<p>
There are two ways to create an MBean. One is to construct a
Java object that will be the MBean, then use the {@link
javax.management.MBeanServer#registerMBean registerMBean}
method to register it in the MBean Server. The other is to
create and register the MBean in a single operation using one
of the {@link javax.management.MBeanServer#createMBean(String,
javax.management.ObjectName) createMBean} methods.
</p>
<p>
The
<code>
registerMBean
</code>
method is simpler for local
use, but cannot be used remotely. The
<code>
createMBean
</code>
method can be used remotely, but
sometimes requires attention to class loading issues.
</p>
<p>
An MBean can perform actions when it is registered in or
unregistered from an MBean Server if it implements the {@link
javax.management.MBeanRegistration MBeanRegistration}
interface.
</p>
<h3>
Accessing MBeans in the MBean Server
</h3>
<p>
Given an
<code>
ObjectName
</code>
<code>
name
</code>
and an
<code>
MBeanServer
</code>
<code>
mbs
</code>
, you can access
attributes and operations as in this example:
</p>
<h3
id=
"stdannot"
>
Defining Standard MBeans with annotations
</h3>
<pre>
<p>
As an alternative to creating an interface such as
<code>
ConfigurationMBean
</code>
and a class that implements it,
you can write just the class, and use annotations to pick out the
public methods that will make up the management interface. For
example, the following class has the same management interface
as a
<code>
Configuration
</code>
class that implements the
<code>
ConfigurationMBean
</code>
interface above.
</p>
<pre>
{@link javax.management.MBean @MBean}
public class Configuration {
{@link javax.management.ManagedAttribute @ManagedAttribute}
public int getCacheSize() {...}
@
ManagedAttribute
public void setCacheSize(int size) {...}
@
ManagedAttribute
public long getLastChangedTime() {...}
{@link javax.management.ManagedOperation @ManagedOperation}
public void save() {...}
...
}
</pre>
<p>
This approach simplifies development, but it does have two
potential drawbacks. First, if you run the Javadoc tool on
this class, the documentation of the management interface may
be mixed in with the documentation of non-management methods
in the class. Second, you cannot make a proxy
as described
<a
href=
"#proxy"
>
below
</a>
if you do not have an
interface like
<code>
ConfigurationMBean
</code>
.
</p>
<h3>
MXBeans
</h3>
<p>
An
<em>
MXBean
</em>
is a variant of Standard MBean where complex
types are mapped to a standard set of types defined in the
{@link javax.management.openmbean} package. MXBeans are appropriate
if you would otherwise need to reference application-specific
classes in your MBean interface. They are described in detail
in the specification for {@link javax.management.MXBean MXBean}.
</p>
<p>
You can define MXBeans using annotations as described
in the
<a
href=
"#stdannot"
>
previous section
</a>
, but
using the
<code>
@
MXBean
</code>
annotation instead of
<code>
@
MBean
</code>
.
</p>
<h3>
Dynamic MBeans
</h3>
<p>
A
<em>
Dynamic MBean
</em>
is an MBean that defines its
management interface at run-time. For example, a configuration
MBean could determine the names and types of the attributes it
exposes by parsing an XML file.
</p>
<p>
Any Java object of a class that implements the {@link
javax.management.DynamicMBean DynamicMBean} interface is a
Dynamic MBean.
</p>
<h3>
Open MBeans
</h3>
<p>
An
<em>
Open MBean
</em>
is a kind of Dynamic MBean where the
types of attributes and of operation parameters and return
values are built using a small set of predefined Java classes.
Open MBeans facilitate operation with remote management programs
that do not necessarily have access to application-specific
types, including non-Java programs. Open MBeans are defined by
the package
<a
href=
"openmbean/package-summary.html"
><code>
javax.management.openmbean
</code></a>
.
</p>
<h3>
Model MBeans
</h3>
<p>
A
<em>
Model MBean
</em>
is a kind of Dynamic MBean that acts
as a bridge between the management interface and the
underlying managed resource. Both the management interface and
the managed resource are specified as Java objects. The same
Model MBean implementation can be reused many times with
different management interfaces and managed resources, and it can
provide common functionality such as persistence and caching.
Model MBeans are defined by the package
<a
href=
"modelmbean/package-summary.html"
><code>
javax.management.modelmbean
</code></a>
.
</p>
<h2>
MBean Server
</h2>
<p>
To be useful, an MBean must be registered in an
<em>
MBean
Server
</em>
. An MBean Server is a repository of MBeans.
Usually the only access to the MBeans is through the MBean
Server. In other words, code no longer accesses the Java
object implementing the MBean directly, but instead accesses
the MBean by name through the MBean Server. Each MBean has a
unique name within the MBean Server, defined by the {@link
javax.management.ObjectName ObjectName} class.
</p>
<p>
An MBean Server is an object implementing the interface
{@link javax.management.MBeanServer MBeanServer}.
The most convenient MBean Server to use is the
<em>
Platform MBean Server
</em>
. This is a
single MBean Server that can be shared by different managed
components running within the same Java Virtual Machine. The
Platform MBean Server is accessed with the method {@link
java.lang.management.ManagementFactory#getPlatformMBeanServer()}.
</p>
<p>
Application code can also create a new MBean Server, or
access already-created MBean Servers, using the {@link
javax.management.MBeanServerFactory MBeanServerFactory} class.
</p>
<h3>
Creating MBeans in the MBean Server
</h3>
<p>
There are two ways to create an MBean. One is to construct a
Java object that will be the MBean, then use the {@link
javax.management.MBeanServer#registerMBean registerMBean}
method to register it in the MBean Server. The other is to
create and register the MBean in a single operation using one
of the {@link javax.management.MBeanServer#createMBean(String,
javax.management.ObjectName) createMBean} methods.
</p>
<p>
The
<code>
registerMBean
</code>
method is simpler for local
use, but cannot be used remotely. The
<code>
createMBean
</code>
method can be used remotely, but
sometimes requires attention to class loading issues.
</p>
<p>
An MBean can perform actions when it is registered in or
unregistered from an MBean Server if it implements the {@link
javax.management.MBeanRegistration MBeanRegistration}
interface.
</p>
<h3>
Accessing MBeans in the MBean Server
</h3>
<p>
Given an
<code>
ObjectName
</code>
<code>
name
</code>
and an
<code>
MBeanServer
</code>
<code>
mbs
</code>
, you can access
attributes and operations as in this example:
</p>
<pre>
int cacheSize = mbs.getAttribute(name, "CacheSize");
{@link javax.management.Attribute Attribute} newCacheSize =
new Attribute("CacheSize", new Integer(2000));
...
...
@@ -236,9 +277,9 @@ have any questions.
mbs.invoke(name, "save", new Object[0], new Class[0]);
</pre>
<p>
Alternatively, if you have a Java interface that corresponds
to the management interface for the MBean, you can use an
<em>
MBean proxy
</em>
like this:
</p>
<p
id=
"proxy"
>
Alternatively, if you have a Java interface that
corresponds
to the management interface for the MBean, you can use an
<em>
MBean proxy
</em>
like this:
</p>
<pre>
ConfigurationMBean conf =
...
...
@@ -264,66 +305,116 @@ have any questions.
perform the query.
</p>
<h2>
Notifications
</h2>
<p>
A
<em>
notification
</em>
is an instance of the {@link
javax.management.Notification Notification} class or a
subclass. In addition to its Java class, it has a
<em>
type
</em>
string that can distinguish it from other
notifications of the same class.
</p>
<p>
An MBean that will emit notifications must implement the
{@link javax.management.NotificationBroadcaster
NotificationBroadcaster} or {@link
javax.management.NotificationEmitter NotificationEmitter}
interface. Usually, it does this by subclassing {@link
javax.management.NotificationBroadcasterSupport
NotificationBroadcasterSupport} or by delegating to an instance
of that class.
</p>
<p>
Notifications can be received by a
<em>
listener
</em>
, which
is an object that implements the {@link
javax.management.NotificationListener NotificationListener}
interface. You can add a listener to an MBean with the method
{@link
javax.management.MBeanServer#addNotificationListener(ObjectName,
NotificationListener, NotificationFilter, Object)}.
You can optionally supply a
<em>
filter
</em>
to this method, to
select only notifications of interest. A filter is an object
that implements the {@link javax.management.NotificationFilter
NotificationFilter} interface.
</p>
<p>
An MBean can be a listener for notifications emitted by other
MBeans in the same MBean Server. In this case, it implements
{@link javax.management.NotificationListener
NotificationListener} and the method {@link
javax.management.MBeanServer#addNotificationListener(ObjectName,
ObjectName, NotificationFilter, Object)} is used to listen.
</p>
<h2>
Remote Access to MBeans
</h2>
<p>
An MBean Server can be accessed remotely through a
<em>
connector
</em>
. A connector allows a remote Java
application to access an MBean Server in essentially the same
way as a local one. The package
<a
href=
"remote/package-summary.html"
><code>
javax.management.remote
</code></a>
defines connectors.
</p>
<p>
The JMX specification also defines the notion of an
<em>
adaptor
</em>
. An adaptor translates between requests in a
protocol such as SNMP or HTML and accesses to an MBean Server.
So for example an SNMP GET operation might result in a
<code>
getAttribute
</code>
on the MBean Server.
</p>
<p
id=
"spec"
>
@see
<a
href=
"{@docRoot}/../technotes/guides/jmx/index.html"
>
Java SE 6 Platform documentation on JMX technology
</a>
in particular the
<a
href=
"{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf"
>
JMX Specification, version 1.4(pdf).
</a>
@since 1.5
<h3>
MBean lifecycle and resource injection
</h3>
<p>
An MBean can implement the {@link javax.management.MBeanRegistration
MBeanRegistration} interface in order to be told when it is registered
and unregistered in the MBean Server. Additionally, the {@link
javax.management.MBeanRegistration#preRegister preRegister} method
allows the MBean to get a reference to the
<code>
MBeanServer
</code>
object and to get its
<code>
ObjectName
</code>
within the MBean
Server.
</p>
<p>
If the only reason to implement
<code>
MBeanRegistration
</code>
is to
discover the
<code>
MBeanServer
</code>
and
<code>
ObjectName
</code>
,
<a
href=
"MBeanRegistration.html#injection"
>
resource injection
</a>
may be
more convenient.
</p>
<h2>
Notifications
</h2>
<p>
A
<em>
notification
</em>
is an instance of the {@link
javax.management.Notification Notification} class or a
subclass. In addition to its Java class, it has a
<em>
type
</em>
string that can distinguish it from other
notifications of the same class.
</p>
<p>
If an MBean is to emit notifications, it must do one of two things.
</p>
<ul>
<li>
It can implement the interface {@link
javax.management.NotificationEmitter NotificationEmitter} (or
its parent {@link javax.management.NotificationBroadcaster
NotificationBroadcaster}), usually by subclassing
{@link javax.management.NotificationBroadcasterSupport
NotificationBroadcasterSupport} or delegating to an instance of
that class.
</li>
<li>
It can use
<a
href=
"MBeanRegistration.html#injection"
>
resource
injection
</a>
to obtain a {@link javax.management.SendNotification
SendNotification} object that it can use to send
notifications.
</li>
</ul>
<p>
The two classes below illustrate these two techniques:
</p>
<pre>
// Implementing NotificationEmitter (via NotificationBroadcasterSupport)
public class Configuration
<b>
extends NotificationBroadcasterSupport
</b>
implements ConfigurationMBean {
...
private void updated() {
Notification n = new Notification(...);
<b>
{@link javax.management.NotificationBroadcasterSupport#sendNotification
sendNotification}(n)
</b>
;
}
}
// Getting a SendNotification through resource injection
public class Configuration implements ConfigurationMBean {
<b>
@
Resource
</b>
private volatile SendNotification sender;
...
private void updated() {
Notification n = new Notification(...);
<b>
sender.sendNotification(n)
</b>
;
}
}
</pre>
<p>
Notifications can be received by a
<em>
listener
</em>
, which
is an object that implements the {@link
javax.management.NotificationListener NotificationListener}
interface. You can add a listener to an MBean with the method
{@link
javax.management.MBeanServer#addNotificationListener(ObjectName,
NotificationListener, NotificationFilter, Object)}.
You can optionally supply a
<em>
filter
</em>
to this method, to
select only notifications of interest. A filter is an object
that implements the {@link javax.management.NotificationFilter
NotificationFilter} interface.
</p>
<p>
An MBean can be a listener for notifications emitted by other
MBeans in the same MBean Server. In this case, it implements
{@link javax.management.NotificationListener
NotificationListener} and the method {@link
javax.management.MBeanServer#addNotificationListener(ObjectName,
ObjectName, NotificationFilter, Object)} is used to listen.
</p>
<h2>
Remote Access to MBeans
</h2>
<p>
An MBean Server can be accessed remotely through a
<em>
connector
</em>
. A connector allows a remote Java
application to access an MBean Server in essentially the same
way as a local one. The package
<a
href=
"remote/package-summary.html"
><code>
javax.management.remote
</code></a>
defines connectors.
</p>
<p>
The JMX specification also defines the notion of an
<em>
adaptor
</em>
. An adaptor translates between requests in a
protocol such as SNMP or HTML and accesses to an MBean Server.
So for example an SNMP GET operation might result in a
<code>
getAttribute
</code>
on the MBean Server.
</p>
<p
id=
"spec"
>
@see
<a
href=
"{@docRoot}/../technotes/guides/jmx/index.html"
>
Java SE 6 Platform documentation on JMX technology
</a>
in particular the
<a
href=
"{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf"
>
JMX Specification, version 1.4(pdf).
</a>
@since 1.5
</body>
</html>
src/share/classes/sun/nio/ch/SelectorImpl.java
浏览文件 @
a311994c
...
...
@@ -142,18 +142,20 @@ abstract class SelectorImpl
// Precondition: Synchronized on this, keys, and selectedKeys
Set
cks
=
cancelledKeys
();
synchronized
(
cks
)
{
Iterator
i
=
cks
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
try
{
implDereg
(
ski
);
}
catch
(
SocketException
se
)
{
IOException
ioe
=
new
IOException
(
"Error deregistering key"
);
ioe
.
initCause
(
se
);
throw
ioe
;
}
finally
{
i
.
remove
();
if
(!
cks
.
isEmpty
())
{
Iterator
i
=
cks
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
try
{
implDereg
(
ski
);
}
catch
(
SocketException
se
)
{
IOException
ioe
=
new
IOException
(
"Error deregistering key"
);
ioe
.
initCause
(
se
);
throw
ioe
;
}
finally
{
i
.
remove
();
}
}
}
}
...
...
test/com/sun/jdi/MonitorFrameInfo.java
浏览文件 @
a311994c
...
...
@@ -25,7 +25,8 @@
* @test
* @bug 6230699
* @summary Test ThreadReference.ownedMonitorsAndFrames()
*
* @bug 6701700
* @summary MonitorInfo objects aren't invalidated when the owning thread is resumed
* @author Swamy Venkataramanappa
*
* @run build TestScaffold VMConnection TargetListener TargetAdapter
...
...
@@ -100,15 +101,15 @@ public class MonitorFrameInfo extends TestScaffold {
if
(!
mainThread
.
frame
(
0
).
location
().
method
().
name
()
.
equals
(
"foo3"
))
{
failure
(
"frame failed"
);
failure
(
"
FAILED:
frame failed"
);
}
if
(
mainThread
.
frames
().
size
()
!=
(
initialSize
+
3
))
{
failure
(
"frames size failed"
);
failure
(
"
FAILED:
frames size failed"
);
}
if
(
mainThread
.
frames
().
size
()
!=
mainThread
.
frameCount
())
{
failure
(
"frames size not equal to frameCount"
);
failure
(
"
FAILED:
frames size not equal to frameCount"
);
}
/* Test monitor frame info.
...
...
@@ -119,13 +120,32 @@ public class MonitorFrameInfo extends TestScaffold {
if
(
monitors
.
size
()
!=
expectedCount
)
{
failure
(
"monitors count is not equal to expected count"
);
}
MonitorInfo
mon
=
null
;
for
(
int
j
=
0
;
j
<
monitors
.
size
();
j
++)
{
MonitorInfo
mon
=
(
MonitorInfo
)
monitors
.
get
(
j
);
mon
=
(
MonitorInfo
)
monitors
.
get
(
j
);
System
.
out
.
println
(
"Monitor obj "
+
mon
.
monitor
()
+
"depth ="
+
mon
.
stackDepth
());
if
(
mon
.
stackDepth
()
!=
expectedDepth
[
j
])
{
failure
(
"monitor stack depth is not equal to expected depth"
);
failure
(
"
FAILED:
monitor stack depth is not equal to expected depth"
);
}
}
// The last gotten monInfo is in mon. When we resume the thread,
// it should become invalid. We will step out of the top frame
// so that the frame depth in this mon object will no longer be correct.
// That is why the monInfo's have to become invalid when the thread is
// resumed.
stepOut
(
mainThread
);
boolean
ok
=
false
;
try
{
System
.
out
.
println
(
"*** Saved Monitor obj "
+
mon
.
monitor
()
+
"depth ="
+
mon
.
stackDepth
());
}
catch
(
InvalidStackFrameException
ee
)
{
// ok
ok
=
true
;
System
.
out
.
println
(
"Got expected InvalidStackFrameException after a resume"
);
}
if
(!
ok
)
{
failure
(
"FAILED: MonitorInfo object was not invalidated by a resume"
);
}
}
else
{
System
.
out
.
println
(
"can not get monitors frame info"
);
}
...
...
test/com/sun/jdi/ResumeOneThreadTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6700889
* @summary Thread resume invalidates all stack frames, even from other threads
*
* @author jjh
*
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run compile -g ResumeOneThreadTest.java
* @run main ResumeOneThreadTest
*/
import
com.sun.jdi.*
;
import
com.sun.jdi.event.*
;
import
com.sun.jdi.request.*
;
import
java.util.*
;
class
ResumeOneThreadTarg
extends
Thread
{
static
String
name1
=
"Thread 1"
;
static
String
name2
=
"Thread 2"
;
public
ResumeOneThreadTarg
(
String
name
)
{
super
(
name
);
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
" Debuggee: Howdy!"
);
ResumeOneThreadTarg
t1
=
new
ResumeOneThreadTarg
(
name1
);
ResumeOneThreadTarg
t2
=
new
ResumeOneThreadTarg
(
name2
);
t1
.
start
();
t2
.
start
();
}
// This just starts two threads. Each runs to a bkpt.
public
void
run
()
{
if
(
getName
().
equals
(
name1
))
{
run1
();
}
else
{
run2
();
}
}
public
void
bkpt1
(
String
p1
)
{
System
.
out
.
println
(
" Debuggee: bkpt 1"
);
}
public
void
run1
()
{
bkpt1
(
"Hello Alviso!"
);
}
public
void
bkpt2
()
{
System
.
out
.
println
(
" Debuggee: bkpt 2"
);
}
public
void
run2
()
{
bkpt2
();
}
}
/********** test program **********/
public
class
ResumeOneThreadTest
extends
TestScaffold
{
ReferenceType
targetClass
;
ThreadReference
mainThread
;
BreakpointRequest
request1
;
BreakpointRequest
request2
;
ThreadReference
thread1
=
null
;
ThreadReference
thread2
=
null
;;
boolean
theVMisDead
=
false
;
ResumeOneThreadTest
(
String
args
[])
{
super
(
args
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
ResumeOneThreadTest
(
args
).
startTests
();
}
synchronized
public
void
breakpointReached
(
BreakpointEvent
event
)
{
println
(
"-- Got bkpt at: "
+
event
.
location
());
ThreadReference
eventThread
=
event
.
thread
();
if
(
eventThread
.
name
().
equals
(
ResumeOneThreadTarg
.
name1
))
{
thread1
=
eventThread
;
}
if
(
eventThread
.
name
().
equals
(
ResumeOneThreadTarg
.
name2
))
{
thread2
=
eventThread
;
}
}
public
void
vmDied
(
VMDeathEvent
event
)
{
theVMisDead
=
true
;
}
synchronized
public
void
eventSetComplete
(
EventSet
set
)
{
if
(
theVMisDead
)
{
return
;
}
if
(
thread1
==
null
||
thread2
==
null
)
{
// Don't do a set.resume(), just let the other thread
// keep running until it hits its bkpt.
return
;
}
// Both threads are stopped at their bkpts. Get a StackFrame from
// Thread 1 then resume Thread 2 and verify that the saved StackFrame is
// still valid.
// suspend everything.
println
(
"-- All threads suspended"
);
vm
().
suspend
();
StackFrame
t1sf0
=
null
;
try
{
t1sf0
=
thread1
.
frame
(
0
);
}
catch
(
IncompatibleThreadStateException
ee
)
{
failure
(
"FAILED: Exception: "
+
ee
);
}
println
(
"-- t1sf0 args: "
+
t1sf0
.
getArgumentValues
());
// Ok, we have a StackFrame for thread 1. Resume just thread 2
// Note that thread 2 has been suspended twice - by the SUSPEND_ALL
// bkpt, and by the above vm().suspend(), so we have to resume
// it twice.
request2
.
disable
();
thread2
.
resume
();
thread2
.
resume
();
println
(
"-- Did Resume on thread 2"
);
// Can we get frames for thread1?
try
{
StackFrame
t1sf0_1
=
thread1
.
frame
(
0
);
if
(!
t1sf0
.
equals
(
t1sf0_1
))
{
failure
(
"FAILED: Got a different frame 0 for thread 1 after resuming thread 2"
);
}
}
catch
(
IncompatibleThreadStateException
ee
)
{
failure
(
"FAILED: Could not get frames for thread 1: Exception: "
+
ee
);
}
catch
(
Exception
ee
)
{
failure
(
"FAILED: Could not get frames for thread 1: Exception: "
+
ee
);
}
try
{
println
(
"-- t1sf0 args: "
+
t1sf0
.
getArgumentValues
());
}
catch
(
InvalidStackFrameException
ee
)
{
// This is the failure.
failure
(
"FAILED Got InvalidStackFrameException"
);
vm
().
dispose
();
throw
(
ee
);
}
// Let the debuggee finish
request1
.
disable
();
thread1
.
resume
();
vm
().
resume
();
println
(
"--------------"
);
}
/********** test core **********/
protected
void
runTests
()
throws
Exception
{
/*
* Get to the top of main()
* to determine targetClass and mainThread
*/
BreakpointEvent
bpe
=
startToMain
(
"ResumeOneThreadTarg"
);
targetClass
=
bpe
.
location
().
declaringType
();
mainThread
=
bpe
.
thread
();
EventRequestManager
erm
=
vm
().
eventRequestManager
();
final
Thread
mainThread
=
Thread
.
currentThread
();
/*
* Set event requests
*/
Location
loc1
=
findMethod
(
targetClass
,
"bkpt1"
,
"(Ljava/lang/String;)V"
).
location
();
request1
=
erm
.
createBreakpointRequest
(
loc1
);
request1
.
setSuspendPolicy
(
EventRequest
.
SUSPEND_EVENT_THREAD
);
request1
.
enable
();
Location
loc2
=
findMethod
(
targetClass
,
"bkpt2"
,
"()V"
).
location
();
request2
=
erm
.
createBreakpointRequest
(
loc2
);
request2
.
setSuspendPolicy
(
EventRequest
.
SUSPEND_EVENT_THREAD
);
request2
.
enable
();
/*
* resume the target, listening for events
*/
listenUntilVMDisconnect
();
/*
* deal with results of test
* if anything has called failure("foo") testFailed will be true
*/
if
(!
testFailed
)
{
println
(
"ResumeOneThreadTest: passed"
);
}
else
{
throw
new
Exception
(
"ResumeOneThreadTest: failed"
);
}
}
}
test/com/sun/jdi/SourceNameFilterTest.java
浏览文件 @
a311994c
...
...
@@ -23,7 +23,7 @@
/**
* @test
* @bug 4836939
* @bug 4836939
6646613
* @summary JDI add addSourceNameFilter to ClassPrepareRequest
*
* @author jjh
...
...
@@ -31,7 +31,11 @@
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run compile -g SourceNameFilterTest.java
* @run main SourceNameFilterTest
* @run compile -g:none SourceNameFilterTest.java
* @run main SourceNameFilterTest
*/
// The compile -g:none suppresses the lineNumber table to trigger bug 6646613.
import
com.sun.jdi.*
;
import
com.sun.jdi.event.*
;
import
com.sun.jdi.request.*
;
...
...
@@ -84,7 +88,6 @@ public class SourceNameFilterTest extends TestScaffold {
boolean
gotEvent1
=
false
;
boolean
gotEvent2
=
false
;
boolean
gotEvent3
=
false
;
ClassPrepareRequest
cpReq
;
boolean
shouldResume
=
false
;
SourceNameFilterTest
(
String
args
[])
{
...
...
@@ -151,6 +154,18 @@ public class SourceNameFilterTest extends TestScaffold {
*/
BreakpointEvent
bpe
=
startToMain
(
"SourceNameFilterTarg"
);
targetClass
=
bpe
.
location
().
declaringType
();
boolean
noSourceName
=
false
;
try
{
targetClass
.
sourceName
();
}
catch
(
AbsentInformationException
ee
)
{
noSourceName
=
true
;
}
if
(
noSourceName
)
{
println
(
"-- Running with no source names"
);
}
else
{
println
(
"-- Running with source names"
);
}
mainThread
=
bpe
.
thread
();
EventRequestManager
erm
=
vm
().
eventRequestManager
();
addListener
(
this
);
...
...
@@ -175,7 +190,9 @@ public class SourceNameFilterTest extends TestScaffold {
/*
* This should cause us to get a class prepare event for
* LoadedLater3
* LoadedLater3 except in the case where -g:none
* was used to compile so that there is no LineNumberTable
* and therefore, no source name for the class.
*/
cpReq
=
erm
.
createClassPrepareRequest
();
cpReq
.
addSourceNameFilter
(
"SourceNameFilterTest.java"
);
...
...
@@ -186,17 +203,21 @@ public class SourceNameFilterTest extends TestScaffold {
if
(!
gotEvent1
)
{
failure
(
"failure: Did not get a class prepare request "
+
"for Loaded
l
ater1"
);
"for Loaded
L
ater1"
);
}
if
(
gotEvent2
)
{
failure
(
"failure: Did get a class prepare request "
+
"for Loaded
l
ater2"
);
"for Loaded
L
ater2"
);
}
if
(!
gotEvent3
)
{
if
(
gotEvent3
&&
noSourceName
)
{
failure
(
"failure: Did get a class prepare request "
+
"for LoadedLater3"
);
}
else
if
(!
gotEvent3
&&
!
noSourceName
)
{
failure
(
"failure: Did not get a class prepare request "
+
"for Loaded
l
ater3"
);
"for Loaded
L
ater3"
);
}
/*
...
...
test/com/sun/jdi/VMConnection.java
浏览文件 @
a311994c
...
...
@@ -115,7 +115,7 @@ class VMConnection {
return
cmdLine
;
}
// Insert the options at position 1. Blanks in args are not allowed!
String
[]
v1
=
opts
.
split
(
" "
);
String
[]
v1
=
opts
.
split
(
"
+
"
);
String
[]
retVal
=
new
String
[
cmdLine
.
length
+
v1
.
length
];
retVal
[
0
]
=
cmdLine
[
0
];
System
.
arraycopy
(
v1
,
0
,
retVal
,
1
,
v1
.
length
);
...
...
test/java/nio/channels/FileChannel/ExpandingMap.java
浏览文件 @
a311994c
...
...
@@ -22,7 +22,7 @@
*/
/* @test
* @bug 4938372
* @bug 4938372
6541641
* @summary Flushing dirty pages prior to unmap can cause Cleaner thread to
* abort VM if memory system has pages locked
*/
...
...
@@ -39,7 +39,7 @@ import java.util.ArrayList;
public
class
ExpandingMap
{
public
static
void
main
(
String
[]
args
)
throws
IO
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
initialSize
=
20480
*
1024
;
int
maximumMapSize
=
16
*
1024
*
1024
;
...
...
@@ -103,6 +103,13 @@ public class ExpandingMap {
}
}
fc
.
close
();
// cleanup the ref to mapped buffers so they can be GCed
for
(
int
i
=
0
;
i
<
buffers
.
length
;
i
++)
buffers
[
i
]
=
null
;
System
.
gc
();
// Take a nap to wait for the Cleaner to cleanup those unrefed maps
Thread
.
sleep
(
1000
);
System
.
out
.
println
(
"TEST PASSED"
);
}
...
...
test/java/nio/channels/Selector/Wakeup.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2001-2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* @test
* @bug 6405995
* @summary Unit test for selector wakeup and interruption
* @library ..
*/
import
java.io.*
;
import
java.net.*
;
import
java.nio.*
;
import
java.nio.channels.*
;
import
java.util.Random
;
public
class
Wakeup
{
static
void
sleep
(
int
millis
)
{
try
{
Thread
.
sleep
(
millis
);
}
catch
(
InterruptedException
x
)
{
x
.
printStackTrace
();
}
}
static
class
Sleeper
extends
TestThread
{
volatile
boolean
started
=
false
;
volatile
int
entries
=
0
;
volatile
int
wakeups
=
0
;
volatile
boolean
wantInterrupt
=
false
;
volatile
boolean
gotInterrupt
=
false
;
volatile
Exception
exception
=
null
;
volatile
boolean
closed
=
false
;
Object
gate
=
new
Object
();
Selector
sel
;
Sleeper
(
Selector
sel
)
{
super
(
"Sleeper"
,
System
.
err
);
this
.
sel
=
sel
;
}
public
void
go
()
throws
Exception
{
started
=
true
;
for
(;;)
{
synchronized
(
gate
)
{
}
entries
++;
try
{
sel
.
select
();
}
catch
(
ClosedSelectorException
x
)
{
closed
=
true
;
}
boolean
intr
=
Thread
.
currentThread
().
isInterrupted
();
wakeups
++;
System
.
err
.
println
(
"Wakeup "
+
wakeups
+
(
closed
?
" (closed)"
:
""
)
+
(
intr
?
" (intr)"
:
""
));
if
(
wakeups
>
1000
)
throw
new
Exception
(
"Too many wakeups"
);
if
(
closed
)
return
;
if
(
wantInterrupt
)
{
while
(!
Thread
.
interrupted
())
Thread
.
yield
();
gotInterrupt
=
true
;
wantInterrupt
=
false
;
}
}
}
}
private
static
int
checkedWakeups
=
0
;
private
static
void
check
(
Sleeper
sleeper
,
boolean
intr
)
throws
Exception
{
checkedWakeups
++;
if
(
sleeper
.
wakeups
>
checkedWakeups
)
{
sleeper
.
finish
(
100
);
throw
new
Exception
(
"Sleeper has run ahead"
);
}
int
n
=
0
;
while
(
sleeper
.
wakeups
<
checkedWakeups
)
{
sleep
(
50
);
if
((
n
+=
50
)
>
1000
)
{
sleeper
.
finish
(
100
);
throw
new
Exception
(
"Sleeper appears to be dead ("
+
checkedWakeups
+
")"
);
}
}
if
(
sleeper
.
wakeups
>
checkedWakeups
)
{
sleeper
.
finish
(
100
);
throw
new
Exception
(
"Too many wakeups: Expected "
+
checkedWakeups
+
", got "
+
sleeper
.
wakeups
);
}
if
(
intr
)
{
n
=
0
;
// Interrupts can sometimes be delayed, so wait
while
(!
sleeper
.
gotInterrupt
)
{
sleep
(
50
);
if
((
n
+=
50
)
>
1000
)
{
sleeper
.
finish
(
100
);
throw
new
Exception
(
"Interrupt never delivered"
);
}
}
sleeper
.
gotInterrupt
=
false
;
}
System
.
err
.
println
(
"Check "
+
checkedWakeups
+
(
intr
?
" (intr "
+
n
+
")"
:
""
));
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Selector
sel
=
Selector
.
open
();
// Wakeup before select
sel
.
wakeup
();
Sleeper
sleeper
=
new
Sleeper
(
sel
);
sleeper
.
start
();
while
(!
sleeper
.
started
)
sleep
(
50
);
check
(
sleeper
,
false
);
// 1
for
(
int
i
=
2
;
i
<
5
;
i
++)
{
// Wakeup during select
sel
.
wakeup
();
check
(
sleeper
,
false
);
// 2 .. 4
}
// Double wakeup
synchronized
(
sleeper
.
gate
)
{
sel
.
wakeup
();
check
(
sleeper
,
false
);
// 5
sel
.
wakeup
();
sel
.
wakeup
();
}
check
(
sleeper
,
false
);
// 6
// Interrupt
synchronized
(
sleeper
.
gate
)
{
sleeper
.
wantInterrupt
=
true
;
sleeper
.
interrupt
();
check
(
sleeper
,
true
);
// 7
}
// Interrupt before select
while
(
sleeper
.
entries
<
8
)
Thread
.
yield
();
synchronized
(
sleeper
.
gate
)
{
sel
.
wakeup
();
check
(
sleeper
,
false
);
// 8
sleeper
.
wantInterrupt
=
true
;
sleeper
.
interrupt
();
sleep
(
50
);
}
check
(
sleeper
,
true
);
// 9
// Close during select
while
(
sleeper
.
entries
<
10
)
Thread
.
yield
();
synchronized
(
sleeper
.
gate
)
{
sel
.
close
();
check
(
sleeper
,
false
);
// 10
}
if
(
sleeper
.
finish
(
200
)
==
0
)
throw
new
Exception
(
"Test failed"
);
if
(!
sleeper
.
closed
)
throw
new
Exception
(
"Selector not closed"
);
}
}
test/javax/management/Introspector/AnnotatedMBeanTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test %M% %I%
* @bug 6323980
* @summary Test MBeans defined with @MBean
* @author Eamonn McManus
* @run main/othervm -ea AnnotatedMBeanTest
*/
import
java.io.File
;
import
java.io.PrintWriter
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.Set
;
import
javax.management.Attribute
;
import
javax.management.Descriptor
;
import
javax.management.DescriptorKey
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MBeanParameterInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.MXBean
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.ManagedAttribute
;
import
javax.management.ManagedOperation
;
import
javax.management.MBean
;
import
javax.management.ObjectName
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeType
;
public
class
AnnotatedMBeanTest
{
private
static
MBeanServer
mbs
;
private
static
final
ObjectName
objectName
;
static
{
try
{
objectName
=
new
ObjectName
(
"test:type=Test"
);
}
catch
(
MalformedObjectNameException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
AnnotatedMBeanTest
.
class
.
desiredAssertionStatus
())
throw
new
Exception
(
"Test must be run with -ea"
);
File
policyFile
=
File
.
createTempFile
(
"jmxperms"
,
".policy"
);
policyFile
.
deleteOnExit
();
PrintWriter
pw
=
new
PrintWriter
(
policyFile
);
pw
.
println
(
"grant {"
);
pw
.
println
(
" permission javax.management.MBeanPermission \"*\", \"*\";"
);
pw
.
println
(
" permission javax.management.MBeanServerPermission \"*\";"
);
pw
.
println
(
" permission javax.management.MBeanTrustPermission \"*\";"
);
pw
.
println
(
"};"
);
pw
.
close
();
System
.
setProperty
(
"java.security.policy"
,
policyFile
.
getAbsolutePath
());
System
.
setSecurityManager
(
new
SecurityManager
());
String
failure
=
null
;
for
(
Method
m
:
AnnotatedMBeanTest
.
class
.
getDeclaredMethods
())
{
if
(
Modifier
.
isStatic
(
m
.
getModifiers
())
&&
m
.
getName
().
startsWith
(
"test"
)
&&
m
.
getParameterTypes
().
length
==
0
)
{
mbs
=
MBeanServerFactory
.
newMBeanServer
();
try
{
m
.
invoke
(
null
);
System
.
out
.
println
(
m
.
getName
()
+
" OK"
);
}
catch
(
InvocationTargetException
ite
)
{
System
.
out
.
println
(
m
.
getName
()
+
" got exception:"
);
Throwable
t
=
ite
.
getCause
();
t
.
printStackTrace
(
System
.
out
);
failure
=
m
.
getName
()
+
": "
+
t
.
toString
();
}
}
}
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
public
static
class
Stats
{
private
final
int
used
;
private
final
int
size
;
private
final
boolean
interesting
;
public
Stats
(
int
used
,
int
size
,
boolean
interesting
)
{
this
.
used
=
used
;
this
.
size
=
size
;
this
.
interesting
=
interesting
;
}
public
int
getUsed
()
{
return
used
;
}
public
int
getSize
()
{
return
size
;
}
public
boolean
isInteresting
()
{
return
interesting
;
}
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
static
@interface
Units
{
@DescriptorKey
(
"units"
)
String
value
();
}
@MBean
public
static
class
Cache
{
private
int
used
=
23
;
private
int
size
=
99
;
@ManagedAttribute
@Units
(
"bytes"
)
public
int
getUsed
()
{
return
used
;
}
@ManagedAttribute
public
int
getSize
()
{
return
size
;
}
@ManagedAttribute
public
void
setSize
(
int
x
)
{
this
.
size
=
x
;
}
@ManagedAttribute
public
boolean
isInteresting
()
{
return
false
;
}
@ManagedAttribute
public
Stats
getStats
()
{
return
new
Stats
(
used
,
size
,
false
);
}
@ManagedOperation
public
int
dropOldest
(
int
n
)
{
return
55
;
}
private
void
irrelevantMethod
()
{}
private
int
getIrrelevant
()
{
return
0
;}
public
int
getIrrelevant2
()
{
return
0
;}
public
int
otherIrrelevantMethod
()
{
return
5
;}
}
public
static
class
SubCache
extends
Cache
{
// SubCache does not have the @MBean annotation
// but its parent does. It doesn't add any @ManagedAttribute or
// @ManagedOperation methods, so its management interface
// should be the same.
private
void
irrelevantMethod2
()
{}
public
int
otherIrrelevantMethod3
()
{
return
0
;}
public
int
getX
()
{
return
0
;}
public
void
setX
(
int
x
)
{}
}
@MXBean
public
static
class
CacheMX
{
private
int
used
=
23
;
private
int
size
=
99
;
@ManagedAttribute
@Units
(
"bytes"
)
public
int
getUsed
()
{
return
used
;
}
@ManagedAttribute
public
int
getSize
()
{
return
size
;
}
@ManagedAttribute
public
void
setSize
(
int
x
)
{
this
.
size
=
x
;
}
@ManagedAttribute
public
boolean
isInteresting
()
{
return
false
;
}
@ManagedAttribute
public
Stats
getStats
()
{
return
new
Stats
(
used
,
size
,
false
);
}
@ManagedOperation
public
int
dropOldest
(
int
n
)
{
return
55
;
}
private
void
irrelevantMethod
()
{}
private
int
getIrrelevant
()
{
return
0
;}
public
int
getIrrelevant2
()
{
return
0
;}
public
int
otherIrrelevantMethod
()
{
return
5
;}
}
public
static
class
SubCacheMX
extends
CacheMX
{
private
void
irrelevantMethod2
()
{}
public
int
otherIrrelevantMethod3
()
{
return
0
;}
public
int
getX
()
{
return
0
;}
public
void
setX
(
int
x
)
{}
}
private
static
void
testSimpleManagedResource
()
throws
Exception
{
testResource
(
new
Cache
(),
false
);
}
private
static
void
testSubclassManagedResource
()
throws
Exception
{
testResource
(
new
SubCache
(),
false
);
}
private
static
void
testMXBeanResource
()
throws
Exception
{
testResource
(
new
CacheMX
(),
true
);
}
private
static
void
testSubclassMXBeanResource
()
throws
Exception
{
testResource
(
new
SubCacheMX
(),
true
);
}
private
static
void
testResource
(
Object
resource
,
boolean
mx
)
throws
Exception
{
mbs
.
registerMBean
(
resource
,
objectName
);
MBeanInfo
mbi
=
mbs
.
getMBeanInfo
(
objectName
);
assert
mbi
.
getDescriptor
().
getFieldValue
(
"mxbean"
).
equals
(
Boolean
.
toString
(
mx
));
MBeanAttributeInfo
[]
mbais
=
mbi
.
getAttributes
();
assert
mbais
.
length
==
4
:
mbais
.
length
;
for
(
MBeanAttributeInfo
mbai
:
mbais
)
{
String
name
=
mbai
.
getName
();
if
(
name
.
equals
(
"Used"
))
{
assert
mbai
.
isReadable
();
assert
!
mbai
.
isWritable
();
assert
!
mbai
.
isIs
();
assert
mbai
.
getType
().
equals
(
"int"
);
assert
"bytes"
.
equals
(
mbai
.
getDescriptor
().
getFieldValue
(
"units"
));
}
else
if
(
name
.
equals
(
"Size"
))
{
assert
mbai
.
isReadable
();
assert
mbai
.
isWritable
();
assert
!
mbai
.
isIs
();
assert
mbai
.
getType
().
equals
(
"int"
);
}
else
if
(
name
.
equals
(
"Interesting"
))
{
assert
mbai
.
isReadable
();
assert
!
mbai
.
isWritable
();
assert
mbai
.
isIs
();
assert
mbai
.
getType
().
equals
(
"boolean"
);
}
else
if
(
name
.
equals
(
"Stats"
))
{
assert
mbai
.
isReadable
();
assert
!
mbai
.
isWritable
();
assert
!
mbai
.
isIs
();
Descriptor
d
=
mbai
.
getDescriptor
();
if
(
mx
)
{
assert
mbai
.
getType
().
equals
(
CompositeData
.
class
.
getName
());
assert
d
.
getFieldValue
(
"originalType"
).
equals
(
Stats
.
class
.
getName
());
CompositeType
ct
=
(
CompositeType
)
d
.
getFieldValue
(
"openType"
);
Set
<
String
>
names
=
new
HashSet
<
String
>(
Arrays
.
asList
(
"used"
,
"size"
,
"interesting"
));
assert
ct
.
keySet
().
equals
(
names
)
:
ct
.
keySet
();
}
else
{
assert
mbai
.
getType
().
equals
(
Stats
.
class
.
getName
());
}
}
else
assert
false
:
name
;
}
MBeanOperationInfo
[]
mbois
=
mbi
.
getOperations
();
assert
mbois
.
length
==
1
:
mbois
.
length
;
MBeanOperationInfo
mboi
=
mbois
[
0
];
assert
mboi
.
getName
().
equals
(
"dropOldest"
);
assert
mboi
.
getReturnType
().
equals
(
"int"
);
MBeanParameterInfo
[]
mbpis
=
mboi
.
getSignature
();
assert
mbpis
.
length
==
1
:
mbpis
.
length
;
assert
mbpis
[
0
].
getType
().
equals
(
"int"
);
assert
mbs
.
getAttribute
(
objectName
,
"Used"
).
equals
(
23
);
assert
mbs
.
getAttribute
(
objectName
,
"Size"
).
equals
(
99
);
mbs
.
setAttribute
(
objectName
,
new
Attribute
(
"Size"
,
55
));
assert
mbs
.
getAttribute
(
objectName
,
"Size"
).
equals
(
55
);
assert
mbs
.
getAttribute
(
objectName
,
"Interesting"
).
equals
(
false
);
Object
stats
=
mbs
.
getAttribute
(
objectName
,
"Stats"
);
assert
(
mx
?
CompositeData
.
class
:
Stats
.
class
).
isInstance
(
stats
)
:
stats
.
getClass
();
int
ret
=
(
Integer
)
mbs
.
invoke
(
objectName
,
"dropOldest"
,
new
Object
[]
{
66
},
new
String
[]
{
"int"
});
assert
ret
==
55
;
}
}
test/javax/management/Introspector/AnnotatedNotificationInfoTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test %M% %I%
* @bug 6323980
* @summary Test @NotificationInfo annotation
* @author Eamonn McManus
* @run main/othervm -ea AnnotatedNotificationInfoTest
*/
import
java.io.Serializable
;
import
java.lang.management.ManagementFactory
;
import
java.lang.reflect.Field
;
import
javax.annotation.Resource
;
import
javax.management.AttributeChangeNotification
;
import
javax.management.Description
;
import
javax.management.Descriptor
;
import
javax.management.ImmutableDescriptor
;
import
javax.management.MBean
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MXBean
;
import
javax.management.NotificationBroadcasterSupport
;
import
javax.management.NotificationInfo
;
import
javax.management.NotificationInfos
;
import
javax.management.ObjectName
;
import
javax.management.SendNotification
;
public
class
AnnotatedNotificationInfoTest
{
// Data for the first test. This tests that MBeanNotificationInfo
// is correctly derived from @NotificationInfo.
// Every static field called mbean* is expected to be an MBean
// with a single MBeanNotificationInfo that has the same value
// in each case.
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
interface
Intf1MBean
{}
public
static
class
Intf1
extends
NotificationBroadcasterSupport
implements
Intf1MBean
{}
private
static
Object
mbeanIntf1
=
new
Intf1
();
@NotificationInfos
(
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
}))
public
static
interface
Intf2MBean
{}
public
static
class
Intf2
extends
NotificationBroadcasterSupport
implements
Intf2MBean
{}
private
static
Object
mbeanIntf2
=
new
Intf2
();
@NotificationInfos
({})
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
interface
Intf3MBean
{}
public
static
class
Intf3
extends
NotificationBroadcasterSupport
implements
Intf3MBean
{}
private
static
Object
mbeanIntf3
=
new
Intf3
();
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
interface
ParentIntf
{}
public
static
interface
Intf4MBean
extends
Serializable
,
ParentIntf
,
Cloneable
{}
public
static
class
Intf4
extends
NotificationBroadcasterSupport
implements
Intf4MBean
{}
private
static
Object
mbeanIntf4
=
new
Intf4
();
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
interface
Intf5MXBean
{}
public
static
class
Intf5Impl
extends
NotificationBroadcasterSupport
implements
Intf5MXBean
{}
private
static
Object
mbeanIntf5
=
new
Intf5Impl
();
public
static
interface
Impl1MBean
{}
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
class
Impl1
extends
NotificationBroadcasterSupport
implements
Impl1MBean
{}
private
static
Object
mbeanImpl1
=
new
Impl1
();
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
class
ParentImpl
extends
NotificationBroadcasterSupport
{}
public
static
interface
Impl2MBean
{}
public
static
class
Impl2
extends
ParentImpl
implements
Impl2MBean
{}
private
static
Object
mbeanImpl2
=
new
Impl2
();
public
static
interface
Impl3MXBean
{}
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
class
Impl3
extends
NotificationBroadcasterSupport
implements
Impl3MXBean
{}
private
static
Object
mbeanImpl3
=
new
Impl3
();
public
static
class
Impl4
extends
ParentImpl
implements
Impl3MXBean
{}
private
static
Object
mbeanImpl4
=
new
Impl4
();
@MBean
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
class
MBean1
extends
NotificationBroadcasterSupport
{}
private
static
Object
mbeanMBean1
=
new
MBean1
();
@MBean
public
static
class
MBean2
extends
ParentImpl
{}
private
static
Object
mbeanMBean2
=
new
MBean2
();
// Following disabled until we support it
// @MBean
// @NotificationInfo(
// types = {"foo", "bar"},
// notificationClass = AttributeChangeNotification.class,
// description = @Description(
// value = "description",
// bundleBaseName = "bundle",
// key = "key"),
// descriptorFields = {"foo=bar"})
// public static class MBean3 {
// @Resource
// private volatile SendNotification send;
// }
//
// private static Object mbeanMBean3 = new MBean3();
@MXBean
@NotificationInfo
(
types
=
{
"foo"
,
"bar"
},
notificationClass
=
AttributeChangeNotification
.
class
,
description
=
@Description
(
value
=
"description"
,
bundleBaseName
=
"bundle"
,
key
=
"key"
),
descriptorFields
=
{
"foo=bar"
})
public
static
class
MXBean1
extends
NotificationBroadcasterSupport
{}
private
static
Object
mbeanMXBean1
=
new
MXBean1
();
@MXBean
public
static
class
MXBean2
extends
ParentImpl
{}
private
static
Object
mbeanMXBean2
=
new
MXBean2
();
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
AnnotatedNotificationInfoTest
.
class
.
desiredAssertionStatus
())
throw
new
Exception
(
"Test must be run with -ea"
);
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
ObjectName
on
=
new
ObjectName
(
"a:b=c"
);
Descriptor
expectedDescriptor
=
new
ImmutableDescriptor
(
"foo=bar"
,
"descriptionResourceBundleBaseName=bundle"
,
"descriptionResourceKey=key"
);
MBeanNotificationInfo
expected
=
new
MBeanNotificationInfo
(
new
String
[]
{
"foo"
,
"bar"
},
AttributeChangeNotification
.
class
.
getName
(),
"description"
,
expectedDescriptor
);
System
.
out
.
println
(
"Testing MBeans..."
);
for
(
Field
mbeanField
:
AnnotatedNotificationInfoTest
.
class
.
getDeclaredFields
())
{
if
(!
mbeanField
.
getName
().
startsWith
(
"mbean"
))
continue
;
System
.
out
.
println
(
"..."
+
mbeanField
.
getName
());
Object
mbean
=
mbeanField
.
get
(
null
);
mbs
.
registerMBean
(
mbean
,
on
);
MBeanInfo
mbi
=
mbs
.
getMBeanInfo
(
on
);
MBeanNotificationInfo
[]
mbnis
=
mbi
.
getNotifications
();
assert
mbnis
.
length
==
1
:
mbnis
.
length
;
assert
mbnis
[
0
].
equals
(
expected
)
:
mbnis
[
0
];
mbs
.
unregisterMBean
(
on
);
}
}
}
test/javax/management/Introspector/MBeanDescriptionTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test %M% %I%
* @bug 6323980
* @summary Test @Description
* @author Eamonn McManus
*/
import
java.lang.management.ManagementFactory
;
import
javax.management.Description
;
import
javax.management.IntrospectionException
;
import
javax.management.MBean
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanConstructorInfo
;
import
javax.management.MBeanFeatureInfo
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MBeanParameterInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MXBean
;
import
javax.management.ManagedAttribute
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.ObjectName
;
import
javax.management.StandardMBean
;
public
class
MBeanDescriptionTest
{
private
static
String
failure
;
private
static
final
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
private
static
final
ObjectName
name
;
static
{
try
{
name
=
new
ObjectName
(
"a:b=c"
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
public
static
interface
Interface
{
@Description
(
"A description"
)
public
String
getA
();
@Description
(
"B description"
)
public
int
getB
();
public
void
setB
(
int
x
);
public
boolean
isC
();
@Description
(
"C description"
)
public
void
setC
(
boolean
x
);
@Description
(
"D description"
)
public
void
setD
(
float
x
);
@Description
(
"H description"
)
public
int
getH
();
@Description
(
"H description"
)
public
void
setH
(
int
x
);
public
String
getE
();
public
int
getF
();
public
void
setF
(
int
x
);
public
void
setG
(
boolean
x
);
@Description
(
"opA description"
)
public
int
opA
(
@Description
(
"p1 description"
)
int
p1
,
@Description
(
"p2 description"
)
int
p2
);
public
void
opB
(
float
x
);
}
@Description
(
"MBean description"
)
public
static
interface
TestMBean
extends
Interface
{}
public
static
class
Test
implements
TestMBean
{
@Description
(
"0-arg constructor description"
)
public
Test
()
{}
public
Test
(
String
why
)
{}
@Description
(
"2-arg constructor description"
)
public
Test
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{
}
public
String
getA
()
{
return
null
;
}
public
int
getB
()
{
return
0
;
}
public
void
setB
(
int
x
)
{
}
public
boolean
isC
()
{
return
false
;
}
public
void
setC
(
boolean
x
)
{
}
public
void
setD
(
float
x
)
{
}
public
String
getE
()
{
return
null
;
}
public
int
getF
()
{
return
0
;
}
public
void
setF
(
int
x
)
{
}
public
void
setG
(
boolean
x
)
{
}
public
int
getH
()
{
return
0
;
}
public
void
setH
(
int
x
)
{
}
public
int
opA
(
int
p1
,
int
p2
)
{
return
0
;
}
public
void
opB
(
float
x
)
{
}
}
public
static
class
TestSub
extends
Test
{
@Description
(
"0-arg constructor description"
)
public
TestSub
()
{}
public
TestSub
(
String
why
)
{}
@Description
(
"2-arg constructor description"
)
public
TestSub
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{
}
}
public
static
class
StandardSub
extends
StandardMBean
implements
TestMBean
{
@Description
(
"0-arg constructor description"
)
public
StandardSub
()
{
super
(
TestMBean
.
class
,
false
);
}
public
StandardSub
(
String
why
)
{
super
(
TestMBean
.
class
,
false
);
}
@Description
(
"2-arg constructor description"
)
public
StandardSub
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{
super
(
TestMBean
.
class
,
false
);
}
public
String
getA
()
{
return
null
;
}
public
int
getB
()
{
return
0
;
}
public
void
setB
(
int
x
)
{
}
public
boolean
isC
()
{
return
false
;
}
public
void
setC
(
boolean
x
)
{
}
public
void
setD
(
float
x
)
{
}
public
String
getE
()
{
return
null
;
}
public
int
getF
()
{
return
0
;
}
public
void
setF
(
int
x
)
{
}
public
void
setG
(
boolean
x
)
{
}
public
int
opA
(
int
p1
,
int
p2
)
{
return
0
;
}
public
void
opB
(
float
x
)
{
}
public
int
getH
()
{
return
0
;
}
public
void
setH
(
int
x
)
{
}
}
@Description
(
"MBean description"
)
public
static
interface
TestMXBean
extends
Interface
{}
public
static
class
TestMXBeanImpl
implements
TestMXBean
{
@Description
(
"0-arg constructor description"
)
public
TestMXBeanImpl
()
{}
public
TestMXBeanImpl
(
String
why
)
{}
@Description
(
"2-arg constructor description"
)
public
TestMXBeanImpl
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{
}
public
String
getA
()
{
return
null
;
}
public
int
getB
()
{
return
0
;
}
public
void
setB
(
int
x
)
{
}
public
boolean
isC
()
{
return
false
;
}
public
void
setC
(
boolean
x
)
{
}
public
void
setD
(
float
x
)
{
}
public
String
getE
()
{
return
null
;
}
public
int
getF
()
{
return
0
;
}
public
void
setF
(
int
x
)
{
}
public
void
setG
(
boolean
x
)
{
}
public
int
opA
(
int
p1
,
int
p2
)
{
return
0
;
}
public
void
opB
(
float
x
)
{
}
public
int
getH
()
{
return
0
;
}
public
void
setH
(
int
x
)
{
}
}
public
static
class
StandardMXSub
extends
StandardMBean
implements
TestMXBean
{
@Description
(
"0-arg constructor description"
)
public
StandardMXSub
()
{
super
(
TestMXBean
.
class
,
true
);
}
public
StandardMXSub
(
String
why
)
{
super
(
TestMXBean
.
class
,
true
);
}
@Description
(
"2-arg constructor description"
)
public
StandardMXSub
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{
super
(
TestMXBean
.
class
,
true
);
}
public
String
getA
()
{
return
null
;
}
public
int
getB
()
{
return
0
;
}
public
void
setB
(
int
x
)
{
}
public
boolean
isC
()
{
return
false
;
}
public
void
setC
(
boolean
x
)
{
}
public
void
setD
(
float
x
)
{
}
public
String
getE
()
{
return
null
;
}
public
int
getF
()
{
return
0
;
}
public
void
setF
(
int
x
)
{
}
public
void
setG
(
boolean
x
)
{
}
public
int
opA
(
int
p1
,
int
p2
)
{
return
0
;
}
public
void
opB
(
float
x
)
{
}
public
int
getH
()
{
return
0
;
}
public
void
setH
(
int
x
)
{
}
}
@MBean
@Description
(
"MBean description"
)
public
static
class
AnnotatedMBean
{
@Description
(
"0-arg constructor description"
)
public
AnnotatedMBean
()
{}
public
AnnotatedMBean
(
String
why
)
{}
@Description
(
"2-arg constructor description"
)
public
AnnotatedMBean
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{}
@ManagedAttribute
@Description
(
"A description"
)
public
String
getA
()
{
return
null
;
}
@ManagedAttribute
@Description
(
"B description"
)
public
int
getB
()
{
return
0
;
}
@ManagedAttribute
public
void
setB
(
int
x
)
{
}
@ManagedAttribute
public
boolean
isC
()
{
return
false
;
}
@ManagedAttribute
@Description
(
"C description"
)
public
void
setC
(
boolean
x
)
{
}
@ManagedAttribute
@Description
(
"D description"
)
public
void
setD
(
float
x
)
{
}
@ManagedAttribute
public
String
getE
()
{
return
null
;
}
@ManagedAttribute
public
int
getF
()
{
return
0
;
}
@ManagedAttribute
public
void
setF
(
int
x
)
{
}
@ManagedAttribute
public
void
setG
(
boolean
x
)
{
}
@ManagedAttribute
@Description
(
"H description"
)
public
int
getH
()
{
return
0
;
}
@ManagedAttribute
@Description
(
"H description"
)
public
void
setH
(
int
x
)
{
}
@ManagedOperation
@Description
(
"opA description"
)
public
int
opA
(
@Description
(
"p1 description"
)
int
p1
,
@Description
(
"p2 description"
)
int
p2
)
{
return
0
;
}
@ManagedOperation
public
void
opB
(
float
x
)
{
}
}
@MXBean
@Description
(
"MBean description"
)
public
static
class
AnnotatedMXBean
{
@Description
(
"0-arg constructor description"
)
public
AnnotatedMXBean
()
{}
public
AnnotatedMXBean
(
String
why
)
{}
@Description
(
"2-arg constructor description"
)
public
AnnotatedMXBean
(
@Description
(
"p1 description"
)
int
x
,
@Description
(
"p2 description"
)
String
y
)
{}
@ManagedAttribute
@Description
(
"A description"
)
public
String
getA
()
{
return
null
;
}
@ManagedAttribute
@Description
(
"B description"
)
public
int
getB
()
{
return
0
;
}
@ManagedAttribute
public
void
setB
(
int
x
)
{
}
@ManagedAttribute
public
boolean
isC
()
{
return
false
;
}
@ManagedAttribute
@Description
(
"C description"
)
public
void
setC
(
boolean
x
)
{
}
@ManagedAttribute
@Description
(
"D description"
)
public
void
setD
(
float
x
)
{
}
@ManagedAttribute
public
String
getE
()
{
return
null
;
}
@ManagedAttribute
public
int
getF
()
{
return
0
;
}
@ManagedAttribute
public
void
setF
(
int
x
)
{
}
@ManagedAttribute
public
void
setG
(
boolean
x
)
{
}
@ManagedAttribute
@Description
(
"H description"
)
public
int
getH
()
{
return
0
;
}
@ManagedAttribute
@Description
(
"H description"
)
public
void
setH
(
int
x
)
{
}
@ManagedOperation
@Description
(
"opA description"
)
public
int
opA
(
@Description
(
"p1 description"
)
int
p1
,
@Description
(
"p2 description"
)
int
p2
)
{
return
0
;
}
@ManagedOperation
public
void
opB
(
float
x
)
{
}
}
// Negative tests follow.
// Inconsistent descriptions
public
static
interface
BadInterface
{
@Description
(
"foo"
)
public
String
getFoo
();
@Description
(
"bar"
)
public
void
setFoo
(
String
x
);
}
public
static
interface
BadMBean
extends
BadInterface
{}
public
static
class
Bad
implements
BadMBean
{
public
String
getFoo
()
{
return
null
;
}
public
void
setFoo
(
String
x
)
{
}
}
public
static
interface
BadMXBean
extends
BadInterface
{}
public
static
class
BadMXBeanImpl
implements
BadMXBean
{
public
String
getFoo
()
{
return
null
;
}
public
void
setFoo
(
String
x
)
{
}
}
private
static
interface
Defaults
{
public
String
defaultAttributeDescription
(
String
name
);
public
String
defaultOperationDescription
(
String
name
);
public
String
defaultParameterDescription
(
int
index
);
}
private
static
class
StandardDefaults
implements
Defaults
{
public
String
defaultAttributeDescription
(
String
name
)
{
return
"Attribute exposed for management"
;
}
public
String
defaultOperationDescription
(
String
name
)
{
return
"Operation exposed for management"
;
}
public
String
defaultParameterDescription
(
int
index
)
{
return
""
;
}
}
private
static
final
Defaults
standardDefaults
=
new
StandardDefaults
();
private
static
class
MXBeanDefaults
implements
Defaults
{
public
String
defaultAttributeDescription
(
String
name
)
{
return
name
;
}
public
String
defaultOperationDescription
(
String
name
)
{
return
name
;
}
public
String
defaultParameterDescription
(
int
index
)
{
return
"p"
+
index
;
}
}
private
static
final
Defaults
mxbeanDefaults
=
new
MXBeanDefaults
();
private
static
class
TestCase
{
final
String
name
;
final
Object
mbean
;
final
Defaults
defaults
;
TestCase
(
String
name
,
Object
mbean
,
Defaults
defaults
)
{
this
.
name
=
name
;
this
.
mbean
=
mbean
;
this
.
defaults
=
defaults
;
}
}
private
static
class
ExceptionTest
{
final
String
name
;
final
Object
mbean
;
ExceptionTest
(
String
name
,
Object
mbean
)
{
this
.
name
=
name
;
this
.
mbean
=
mbean
;
}
}
private
static
final
TestCase
[]
tests
=
{
new
TestCase
(
"Standard MBean"
,
new
Test
(),
standardDefaults
),
new
TestCase
(
"Standard MBean subclass"
,
new
TestSub
(),
standardDefaults
),
new
TestCase
(
"StandardMBean delegating"
,
new
StandardMBean
(
new
Test
(),
TestMBean
.
class
,
false
),
standardDefaults
),
new
TestCase
(
"StandardMBean delegating to subclass"
,
new
StandardMBean
(
new
TestSub
(),
TestMBean
.
class
,
false
),
standardDefaults
),
new
TestCase
(
"StandardMBean subclass"
,
new
StandardSub
(),
standardDefaults
),
new
TestCase
(
"MXBean"
,
new
TestMXBeanImpl
(),
mxbeanDefaults
),
new
TestCase
(
"StandardMBean MXBean delegating"
,
new
StandardMBean
(
new
TestMXBeanImpl
(),
TestMXBean
.
class
,
true
),
mxbeanDefaults
),
new
TestCase
(
"StandardMBean MXBean subclass"
,
new
StandardMXSub
(),
mxbeanDefaults
),
new
TestCase
(
"@MBean"
,
new
AnnotatedMBean
(),
standardDefaults
),
new
TestCase
(
"@MXBean"
,
new
AnnotatedMXBean
(),
mxbeanDefaults
),
new
TestCase
(
"StandardMBean @MBean delegating"
,
new
StandardMBean
(
new
AnnotatedMBean
(),
null
,
false
),
standardDefaults
),
new
TestCase
(
"StandardMBean @MXBean delegating"
,
new
StandardMBean
(
new
AnnotatedMXBean
(),
null
,
true
),
mxbeanDefaults
),
};
private
static
final
ExceptionTest
[]
exceptionTests
=
{
new
ExceptionTest
(
"Standard MBean with inconsistent get/set"
,
new
Bad
()),
new
ExceptionTest
(
"MXBean with inconsistent get/set"
,
new
BadMXBeanImpl
()),
};
public
static
void
main
(
String
[]
args
)
throws
Exception
{
System
.
out
.
println
(
"=== Testing correct MBeans ==="
);
for
(
TestCase
test
:
tests
)
{
System
.
out
.
println
(
"Testing "
+
test
.
name
+
"..."
);
mbs
.
registerMBean
(
test
.
mbean
,
name
);
boolean
expectConstructors
=
(
test
.
mbean
.
getClass
()
!=
StandardMBean
.
class
);
check
(
mbs
.
getMBeanInfo
(
name
),
test
.
defaults
,
expectConstructors
);
mbs
.
unregisterMBean
(
name
);
}
System
.
out
.
println
();
System
.
out
.
println
(
"=== Testing incorrect MBeans ==="
);
for
(
ExceptionTest
test
:
exceptionTests
)
{
System
.
out
.
println
(
"Testing "
+
test
.
name
);
try
{
mbs
.
registerMBean
(
test
.
mbean
,
name
);
fail
(
"Registration succeeded but should not have"
);
mbs
.
unregisterMBean
(
name
);
}
catch
(
NotCompliantMBeanException
e
)
{
// OK
}
catch
(
Exception
e
)
{
fail
(
"Registration failed with wrong exception: "
+
"expected NotCompliantMBeanException, got "
+
e
.
getClass
().
getName
());
}
}
System
.
out
.
println
();
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
private
static
void
check
(
MBeanInfo
mbi
,
Defaults
defaults
,
boolean
expectConstructors
)
throws
Exception
{
assertEquals
(
"MBean description"
,
mbi
.
getDescription
());
// These attributes have descriptions
for
(
String
attr
:
new
String
[]
{
"A"
,
"B"
,
"C"
,
"D"
,
"H"
})
{
MBeanAttributeInfo
mbai
=
getAttributeInfo
(
mbi
,
attr
);
assertEquals
(
attr
+
" description"
,
mbai
.
getDescription
());
}
// These attributes don't have descriptions
for
(
String
attr
:
new
String
[]
{
"E"
,
"F"
,
"G"
})
{
// If we ever change the default description, we'll need to change
// this test accordingly.
MBeanAttributeInfo
mbai
=
getAttributeInfo
(
mbi
,
attr
);
assertEquals
(
defaults
.
defaultAttributeDescription
(
attr
),
mbai
.
getDescription
());
}
// This operation has a description, as do its parameters
MBeanOperationInfo
opA
=
getOperationInfo
(
mbi
,
"opA"
);
assertEquals
(
"opA description"
,
opA
.
getDescription
());
checkSignature
(
opA
.
getSignature
());
// This operation has the default description, as does its parameter
MBeanOperationInfo
opB
=
getOperationInfo
(
mbi
,
"opB"
);
assertEquals
(
defaults
.
defaultOperationDescription
(
"opB"
),
opB
.
getDescription
());
MBeanParameterInfo
opB0
=
opB
.
getSignature
()[
0
];
assertEquals
(
defaults
.
defaultParameterDescription
(
0
),
opB0
.
getDescription
());
if
(
expectConstructors
)
{
// The 0-arg and 2-arg constructors have descriptions
MBeanConstructorInfo
con0
=
getConstructorInfo
(
mbi
,
0
);
assertEquals
(
"0-arg constructor description"
,
con0
.
getDescription
());
MBeanConstructorInfo
con2
=
getConstructorInfo
(
mbi
,
2
);
assertEquals
(
"2-arg constructor description"
,
con2
.
getDescription
());
checkSignature
(
con2
.
getSignature
());
// The 1-arg constructor does not have a description.
// The default description for constructors and their
// parameters is the same for all types of MBean.
MBeanConstructorInfo
con1
=
getConstructorInfo
(
mbi
,
1
);
assertEquals
(
"Public constructor of the MBean"
,
con1
.
getDescription
());
assertEquals
(
""
,
con1
.
getSignature
()[
0
].
getDescription
());
}
}
private
static
void
checkSignature
(
MBeanParameterInfo
[]
params
)
{
for
(
int
i
=
0
;
i
<
params
.
length
;
i
++)
{
MBeanParameterInfo
mbpi
=
params
[
i
];
assertEquals
(
"p"
+
(
i
+
1
)
+
" description"
,
mbpi
.
getDescription
());
}
}
private
static
MBeanAttributeInfo
getAttributeInfo
(
MBeanInfo
mbi
,
String
attr
)
throws
Exception
{
return
getFeatureInfo
(
mbi
.
getAttributes
(),
attr
);
}
private
static
MBeanOperationInfo
getOperationInfo
(
MBeanInfo
mbi
,
String
op
)
throws
Exception
{
return
getFeatureInfo
(
mbi
.
getOperations
(),
op
);
}
private
static
MBeanConstructorInfo
getConstructorInfo
(
MBeanInfo
mbi
,
int
nparams
)
throws
Exception
{
for
(
MBeanConstructorInfo
mbci
:
mbi
.
getConstructors
())
{
if
(
mbci
.
getSignature
().
length
==
nparams
)
return
mbci
;
}
throw
new
Exception
(
"Constructor not found: "
+
nparams
);
}
private
static
<
T
extends
MBeanFeatureInfo
>
T
getFeatureInfo
(
T
[]
features
,
String
name
)
throws
Exception
{
for
(
T
feature
:
features
)
{
if
(
feature
.
getName
().
equals
(
name
))
return
feature
;
}
throw
new
Exception
(
"Feature not found: "
+
name
);
}
private
static
void
assertEquals
(
Object
expected
,
Object
actual
)
{
if
(!
expected
.
equals
(
actual
))
fail
(
"Expected "
+
string
(
expected
)
+
", got "
+
string
(
actual
));
}
private
static
String
string
(
Object
x
)
{
if
(
x
instanceof
String
)
return
quote
((
String
)
x
);
else
return
String
.
valueOf
(
x
);
}
private
static
String
quote
(
String
s
)
{
return
'"'
+
s
.
replace
(
"\\"
,
"\\\\"
).
replace
(
"\""
,
"\\\""
)
+
'"'
;
}
private
static
void
fail
(
String
why
)
{
StackTraceElement
[]
stack
=
new
Throwable
().
getStackTrace
();
int
n
=
0
;
for
(
StackTraceElement
elmt
:
stack
)
{
String
method
=
elmt
.
getMethodName
();
if
(
method
.
equals
(
"fail"
)
||
method
.
equals
(
"assertEquals"
)
||
method
.
equals
(
"checkSignature"
))
continue
;
n
=
elmt
.
getLineNumber
();
break
;
}
System
.
out
.
println
(
"FAILED: "
+
why
+
" (line "
+
n
+
")"
);
failure
=
why
;
}
}
test/javax/management/Introspector/ParameterNameTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test %M% %I%
* @bug 6323980
* @summary Test that parameter names can be specified with @Name.
* @author Eamonn McManus
*/
import
javax.management.MBean
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MBeanParameterInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.MXBean
;
import
javax.management.ObjectName
;
import
annot.Name
;
import
javax.management.ManagedOperation
;
public
class
ParameterNameTest
{
public
static
interface
NoddyMBean
{
public
int
add
(
int
x
,
@Name
(
"y"
)
int
y
);
}
public
static
class
Noddy
implements
NoddyMBean
{
public
int
add
(
int
x
,
int
y
)
{
return
x
+
y
;
}
}
public
static
interface
NoddyMXBean
{
public
int
add
(
int
x
,
@Name
(
"y"
)
int
y
);
}
public
static
class
NoddyImpl
implements
NoddyMXBean
{
public
int
add
(
int
x
,
int
y
)
{
return
x
+
y
;
}
}
@MBean
public
static
class
NoddyAnnot
{
@ManagedOperation
public
int
add
(
int
x
,
@Name
(
"y"
)
int
y
)
{
return
x
+
y
;
}
}
@MXBean
public
static
class
NoddyAnnotMX
{
@ManagedOperation
public
int
add
(
int
x
,
@Name
(
"y"
)
int
y
)
{
return
x
+
y
;
}
}
private
static
final
Object
[]
mbeans
=
{
new
Noddy
(),
new
NoddyImpl
(),
new
NoddyAnnot
(),
new
NoddyAnnotMX
(),
};
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
ObjectName
name
=
new
ObjectName
(
"a:b=c"
);
for
(
Object
mbean
:
mbeans
)
{
System
.
out
.
println
(
"Testing "
+
mbean
.
getClass
().
getName
());
mbs
.
registerMBean
(
mbean
,
name
);
MBeanInfo
mbi
=
mbs
.
getMBeanInfo
(
name
);
MBeanOperationInfo
[]
mbois
=
mbi
.
getOperations
();
assertEquals
(
1
,
mbois
.
length
);
MBeanParameterInfo
[]
mbpis
=
mbois
[
0
].
getSignature
();
assertEquals
(
2
,
mbpis
.
length
);
boolean
mx
=
Boolean
.
parseBoolean
(
(
String
)
mbi
.
getDescriptor
().
getFieldValue
(
"mxbean"
));
assertEquals
(
mx
?
"p0"
:
"p1"
,
mbpis
[
0
].
getName
());
assertEquals
(
"y"
,
mbpis
[
1
].
getName
());
mbs
.
unregisterMBean
(
name
);
}
System
.
out
.
println
(
"TEST PASSED"
);
}
private
static
void
assertEquals
(
Object
expect
,
Object
actual
)
throws
Exception
{
boolean
eq
;
if
(
expect
==
null
)
eq
=
(
actual
==
null
);
else
eq
=
expect
.
equals
(
actual
);
if
(!
eq
)
{
throw
new
Exception
(
"TEST FAILED: expected "
+
expect
+
", found "
+
actual
);
}
}
}
test/javax/management/Introspector/ResourceInjectionTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test %M% %I%
* @bug 6323980
* @summary Test resource injection via @Resource
* @author Eamonn McManus
* @run main/othervm -ea ResourceInjectionTest
*/
import
java.io.File
;
import
java.io.PrintWriter
;
import
java.io.Serializable
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.Arrays
;
import
javax.annotation.Resource
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
import
javax.management.AttributeNotFoundException
;
import
javax.management.DynamicMBean
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.MBean
;
import
javax.management.MBeanException
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanRegistrationException
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.MXBean
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.ManagedAttribute
;
import
javax.management.ManagedOperation
;
import
javax.management.NotCompliantMBeanException
;
import
javax.management.Notification
;
import
javax.management.NotificationEmitter
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectName
;
import
javax.management.ReflectionException
;
import
javax.management.SendNotification
;
import
javax.management.StandardEmitterMBean
;
import
javax.management.StandardMBean
;
import
javax.management.openmbean.MXBeanMappingFactory
;
public
class
ResourceInjectionTest
{
private
static
MBeanServer
mbs
;
private
static
final
ObjectName
objectName
;
static
{
try
{
objectName
=
new
ObjectName
(
"test:type=Test"
);
}
catch
(
MalformedObjectNameException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
/* This is somewhat nasty. In the current state of affairs, a
* StandardEmitterMBean can only get the
* MBeanServer to rewrite the source of a Notification from
* the originating object's reference to its ObjectName IF
* StandardEmitterMBean.getResource() returns a reference to the
* wrapped object. By default it doesn't, and you need to specify
* the option below to make it do so. We may hope that this is
* obscure enough for users to run into it rarely if ever.
*/
private
static
final
StandardMBean
.
Options
withWrappedVisible
;
private
static
final
StandardMBean
.
Options
withWrappedVisibleMX
;
static
{
withWrappedVisible
=
new
StandardMBean
.
Options
();
withWrappedVisible
.
setWrappedObjectVisible
(
true
);
withWrappedVisibleMX
=
withWrappedVisible
.
clone
();
withWrappedVisibleMX
.
setMXBeanMappingFactory
(
MXBeanMappingFactory
.
DEFAULT
);
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
private
static
@interface
ExpectException
{
Class
<?
extends
Exception
>
value
();
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
ResourceInjectionTest
.
class
.
desiredAssertionStatus
())
throw
new
Exception
(
"Test must be run with -ea"
);
File
policyFile
=
File
.
createTempFile
(
"jmxperms"
,
".policy"
);
policyFile
.
deleteOnExit
();
PrintWriter
pw
=
new
PrintWriter
(
policyFile
);
pw
.
println
(
"grant {"
);
pw
.
println
(
" permission javax.management.MBeanPermission \"*\", \"*\";"
);
pw
.
println
(
" permission javax.management.MBeanServerPermission \"*\";"
);
pw
.
println
(
" permission javax.management.MBeanTrustPermission \"*\";"
);
pw
.
println
(
"};"
);
pw
.
close
();
System
.
setProperty
(
"java.security.policy"
,
policyFile
.
getAbsolutePath
());
System
.
setSecurityManager
(
new
SecurityManager
());
String
failure
=
null
;
for
(
Method
m
:
ResourceInjectionTest
.
class
.
getDeclaredMethods
())
{
if
(
Modifier
.
isStatic
(
m
.
getModifiers
())
&&
m
.
getName
().
startsWith
(
"test"
)
&&
m
.
getParameterTypes
().
length
==
0
)
{
ExpectException
expexc
=
m
.
getAnnotation
(
ExpectException
.
class
);
mbs
=
MBeanServerFactory
.
newMBeanServer
();
try
{
m
.
invoke
(
null
);
if
(
expexc
!=
null
)
{
failure
=
m
.
getName
()
+
" did not got expected exception "
+
expexc
.
value
().
getName
();
System
.
out
.
println
(
failure
);
}
else
System
.
out
.
println
(
m
.
getName
()
+
" OK"
);
}
catch
(
InvocationTargetException
ite
)
{
Throwable
t
=
ite
.
getCause
();
String
prob
=
null
;
if
(
expexc
!=
null
)
{
if
(
expexc
.
value
().
isInstance
(
t
))
{
System
.
out
.
println
(
m
.
getName
()
+
" OK (got expected "
+
expexc
.
value
().
getName
()
+
")"
);
}
else
prob
=
"got wrong exception"
;
}
else
prob
=
"got exception"
;
if
(
prob
!=
null
)
{
failure
=
m
.
getName
()
+
": "
+
prob
+
" "
+
t
.
getClass
().
getName
();
System
.
out
.
println
(
failure
);
t
.
printStackTrace
(
System
.
out
);
}
}
}
}
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
private
static
interface
Send
{
public
void
send
();
}
// Test @Resource in MBean defined by annotations
@MBean
public
static
class
Annotated
{
@Resource
private
volatile
MBeanServer
mbeanServer
;
@Resource
private
volatile
ObjectName
myName
;
@ManagedAttribute
public
ObjectName
getMyName
()
{
return
myName
;
}
@ManagedOperation
public
void
unregisterSelf
()
throws
InstanceNotFoundException
,
MBeanRegistrationException
{
mbeanServer
.
unregisterMBean
(
myName
);
}
}
private
static
void
testAnnotated
()
throws
Exception
{
testMBean
(
new
Annotated
());
}
private
static
void
testAnnotatedWrapped
()
throws
Exception
{
testMBean
(
new
StandardMBean
(
new
Annotated
(),
null
));
}
@MBean
public
static
class
AnnotatedSend
extends
Annotated
implements
Send
{
@Resource
private
volatile
SendNotification
sender
;
@ManagedOperation
public
void
send
()
{
sender
.
sendNotification
(
new
Notification
(
"type"
,
this
,
0L
));
}
}
private
static
void
testAnnotatedSend
()
throws
Exception
{
testMBean
(
new
AnnotatedSend
());
}
private
static
void
testAnnotatedSendWrapped
()
throws
Exception
{
testMBean
(
new
StandardEmitterMBean
(
new
AnnotatedSend
(),
null
,
withWrappedVisible
,
null
));
}
// Test @Resource in MXBean defined by annotations
@MXBean
public
static
class
AnnotatedMX
{
@Resource
private
volatile
MBeanServer
mbeanServer
;
@Resource
private
volatile
ObjectName
myName
;
@ManagedAttribute
public
ObjectName
getMyName
()
{
return
myName
;
}
@ManagedOperation
public
void
unregisterSelf
()
throws
InstanceNotFoundException
,
MBeanRegistrationException
{
mbeanServer
.
unregisterMBean
(
myName
);
}
}
private
static
void
testAnnotatedMX
()
throws
Exception
{
testMBean
(
new
AnnotatedMX
());
}
private
static
void
testAnnotatedMXWrapped
()
throws
Exception
{
testMBean
(
new
StandardMBean
(
new
AnnotatedMX
(),
null
,
true
));
}
public
static
class
AnnotatedMXSend
extends
AnnotatedMX
implements
Send
{
@Resource
private
volatile
SendNotification
sender
;
@ManagedOperation
public
void
send
()
{
sender
.
sendNotification
(
new
Notification
(
"type"
,
this
,
0L
));
}
}
private
static
void
testAnnotatedMXSend
()
throws
Exception
{
testMBean
(
new
AnnotatedMXSend
());
}
private
static
void
testAnnotatedMXSendWrapped
()
throws
Exception
{
testMBean
(
new
StandardEmitterMBean
(
new
AnnotatedMXSend
(),
null
,
withWrappedVisibleMX
,
null
));
}
// Test @Resource in Standard MBean
public
static
interface
SimpleStandardMBean
{
public
ObjectName
getMyName
();
public
void
unregisterSelf
()
throws
Exception
;
}
public
static
class
SimpleStandard
implements
SimpleStandardMBean
{
@Resource
(
type
=
MBeanServer
.
class
)
private
volatile
Object
mbeanServer
;
@Resource
(
type
=
ObjectName
.
class
)
private
volatile
Object
myName
;
public
ObjectName
getMyName
()
{
return
(
ObjectName
)
myName
;
}
public
void
unregisterSelf
()
throws
Exception
{
((
MBeanServer
)
mbeanServer
).
unregisterMBean
(
getMyName
());
}
}
private
static
void
testStandard
()
throws
Exception
{
testMBean
(
new
SimpleStandard
());
}
private
static
void
testStandardWrapped
()
throws
Exception
{
testMBean
(
new
StandardMBean
(
new
SimpleStandard
(),
SimpleStandardMBean
.
class
));
}
public
static
interface
SimpleStandardSendMBean
extends
SimpleStandardMBean
{
public
void
send
();
}
public
static
class
SimpleStandardSend
extends
SimpleStandard
implements
SimpleStandardSendMBean
{
@Resource
(
type
=
SendNotification
.
class
)
private
volatile
Object
sender
;
public
void
send
()
{
((
SendNotification
)
sender
).
sendNotification
(
new
Notification
(
"type"
,
this
,
0L
));
}
}
private
static
void
testStandardSend
()
throws
Exception
{
testMBean
(
new
SimpleStandardSend
());
}
private
static
void
testStandardSendWrapped
()
throws
Exception
{
testMBean
(
new
StandardEmitterMBean
(
new
SimpleStandardSend
(),
SimpleStandardSendMBean
.
class
,
withWrappedVisible
,
null
));
}
// Test @Resource in MXBean
public
static
interface
SimpleMXBean
{
public
ObjectName
getMyName
();
public
void
unregisterSelf
()
throws
Exception
;
}
public
static
class
SimpleMX
implements
SimpleMXBean
{
@Resource
(
type
=
MBeanServer
.
class
)
private
volatile
Object
mbeanServer
;
@Resource
(
type
=
ObjectName
.
class
)
private
volatile
Object
myName
;
public
ObjectName
getMyName
()
{
return
(
ObjectName
)
myName
;
}
public
void
unregisterSelf
()
throws
Exception
{
((
MBeanServer
)
mbeanServer
).
unregisterMBean
(
getMyName
());
}
}
private
static
void
testMX
()
throws
Exception
{
testMBean
(
new
SimpleMX
());
}
private
static
void
testMXWrapped
()
throws
Exception
{
testMBean
(
new
StandardMBean
(
new
SimpleMX
(),
SimpleMXBean
.
class
,
true
));
}
public
static
interface
SimpleMXBeanSend
extends
SimpleMXBean
{
public
void
send
();
}
public
MBeanServer
getMbs
()
{
return
mbs
;
}
public
static
class
SimpleMXSend
extends
SimpleMX
implements
SimpleMXBeanSend
{
@Resource
(
type
=
SendNotification
.
class
)
private
volatile
Object
sender
;
public
void
send
()
{
((
SendNotification
)
sender
).
sendNotification
(
new
Notification
(
"type"
,
this
,
0L
));
}
}
private
static
void
testMXSend
()
throws
Exception
{
testMBean
(
new
SimpleMXSend
());
}
private
static
void
testMXSendWrapped
()
throws
Exception
{
testMBean
(
new
StandardEmitterMBean
(
new
SimpleMXSend
(),
SimpleMXBeanSend
.
class
,
withWrappedVisibleMX
,
null
));
}
// Test @Resource in Dynamic MBean
private
static
class
SimpleDynamic
implements
DynamicMBean
{
private
MBeanServer
mbeanServer
;
private
ObjectName
myName
;
@Resource
private
synchronized
void
setMBeanServer
(
MBeanServer
mbs
)
{
mbeanServer
=
mbs
;
}
@Resource
(
type
=
ObjectName
.
class
)
private
synchronized
void
setObjectName
(
Serializable
name
)
{
myName
=
(
ObjectName
)
name
;
}
public
synchronized
Object
getAttribute
(
String
attribute
)
throws
AttributeNotFoundException
{
if
(
attribute
.
equals
(
"MyName"
))
return
myName
;
throw
new
AttributeNotFoundException
(
attribute
);
}
public
void
setAttribute
(
Attribute
attribute
)
throws
AttributeNotFoundException
{
throw
new
AttributeNotFoundException
(
attribute
.
getName
());
}
public
synchronized
AttributeList
getAttributes
(
String
[]
attributes
)
{
AttributeList
list
=
new
AttributeList
();
for
(
String
name
:
attributes
)
{
if
(
name
.
equals
(
"MyName"
))
list
.
add
(
new
Attribute
(
"MyName"
,
myName
));
}
return
list
;
}
public
AttributeList
setAttributes
(
AttributeList
attributes
)
{
return
new
AttributeList
();
}
public
synchronized
Object
invoke
(
String
actionName
,
Object
[]
params
,
String
[]
signature
)
throws
MBeanException
,
ReflectionException
{
if
(
actionName
.
equals
(
"unregisterSelf"
)
&&
(
params
==
null
||
params
.
length
==
0
)
&&
(
signature
==
null
||
signature
.
length
==
0
))
{
try
{
mbeanServer
.
unregisterMBean
(
myName
);
return
null
;
}
catch
(
Exception
x
)
{
throw
new
MBeanException
(
x
);
}
}
else
{
Exception
x
=
new
NoSuchMethodException
(
actionName
+
Arrays
.
toString
(
signature
));
throw
new
MBeanException
(
x
);
}
}
public
MBeanInfo
getMBeanInfo
()
{
DynamicMBean
mbean
=
new
StandardMBean
(
new
SimpleStandard
(),
SimpleStandardMBean
.
class
,
false
);
return
mbean
.
getMBeanInfo
();
}
}
private
static
void
testDynamic
()
throws
Exception
{
testMBean
(
new
SimpleDynamic
());
}
private
static
class
SimpleDynamicSend
extends
SimpleDynamic
{
private
SendNotification
sender
;
@Resource
private
synchronized
void
setSender
(
SendNotification
sender
)
{
this
.
sender
=
sender
;
}
@Override
public
synchronized
Object
invoke
(
String
actionName
,
Object
[]
params
,
String
[]
signature
)
throws
MBeanException
,
ReflectionException
{
if
(
actionName
.
equals
(
"send"
))
{
sender
.
sendNotification
(
new
Notification
(
"type"
,
this
,
0L
));
return
null
;
}
else
return
super
.
invoke
(
actionName
,
params
,
signature
);
}
}
private
static
void
testDynamicSend
()
throws
Exception
{
testMBean
(
new
SimpleDynamicSend
());
}
// Test that @Resource classes don't have to be public
// They can even be defined within methods!
// But you can't have any @ManagedAttributes or @ManagedOperations
// in such MBeans so their utility is limited.
private
static
void
testNonPublic
()
throws
Exception
{
@MBean
class
NonPublic
{
@Resource
ObjectName
myName
;
}
assert
!
Modifier
.
isPublic
(
NonPublic
.
class
.
getModifiers
());
NonPublic
mbean
=
new
NonPublic
();
mbs
.
registerMBean
(
mbean
,
objectName
);
assert
objectName
.
equals
(
mbean
.
myName
);
}
// Test inheritance and multiple injections of the same value
private
static
class
ManyResources
extends
AnnotatedSend
{
@Resource
private
volatile
ObjectName
myName
;
// same name as in parent!
@Resource
(
type
=
ObjectName
.
class
)
private
volatile
Object
myOtherName
;
private
volatile
ObjectName
myThirdName
;
private
volatile
ObjectName
myFourthName
;
private
volatile
int
methodCalls
;
@Resource
private
volatile
SendNotification
send1
;
@Resource
(
type
=
SendNotification
.
class
)
private
volatile
Object
send2
;
@Resource
void
setMyName
(
ObjectName
name
)
{
myThirdName
=
name
;
methodCalls
++;
}
@Resource
(
type
=
ObjectName
.
class
)
private
void
setMyNameAgain
(
ObjectName
name
)
{
myFourthName
=
name
;
methodCalls
++;
}
void
check
()
{
assert
objectName
.
equals
(
myName
)
:
myName
;
for
(
ObjectName
name
:
new
ObjectName
[]
{
(
ObjectName
)
myOtherName
,
myThirdName
,
myFourthName
})
{
assert
myName
==
name
:
name
;
}
assert
methodCalls
==
2
:
methodCalls
;
assert
send1
!=
null
&&
send2
==
send1
;
}
}
private
static
void
testManyResources
()
throws
Exception
{
ManyResources
mr
=
new
ManyResources
();
testMBean
(
mr
);
mr
.
check
();
}
// Test that method override doesn't lead to multiple calls of the same method
private
static
class
ManyResourcesSub
extends
ManyResources
{
private
boolean
called
;
@Override
@Resource
void
setMyName
(
ObjectName
name
)
{
super
.
setMyName
(
name
);
called
=
true
;
}
void
check2
()
{
assert
called
;
}
}
private
static
void
testOverride
()
throws
Exception
{
ManyResourcesSub
mrs
=
new
ManyResourcesSub
();
testMBean
(
mrs
);
mrs
.
check
();
mrs
.
check2
();
}
// Test that @Resource is illegal on static fields
@MBean
public
static
class
StaticResource
{
@Resource
private
static
ObjectName
name
;
}
@ExpectException
(
NotCompliantMBeanException
.
class
)
private
static
void
testStaticResource
()
throws
Exception
{
testMBean
(
new
StaticResource
());
}
// Test that @Resource is illegal on static methods
@MBean
public
static
class
StaticResourceMethod
{
@Resource
private
static
void
setObjectName
(
ObjectName
name
)
{}
}
@ExpectException
(
NotCompliantMBeanException
.
class
)
private
static
void
testStaticResourceMethod
()
throws
Exception
{
testMBean
(
new
StaticResourceMethod
());
}
// Test that @Resource is illegal on methods that don't return void
@MBean
public
static
class
NonVoidMethod
{
@Resource
private
String
setObjectName
(
ObjectName
name
)
{
return
"oops"
;
}
}
@ExpectException
(
NotCompliantMBeanException
.
class
)
private
static
void
testNonVoidMethod
()
throws
Exception
{
testMBean
(
new
NonVoidMethod
());
}
// Test that @Resource is illegal on methods with no arguments
@MBean
public
static
class
NoArgMethod
{
@Resource
(
type
=
ObjectName
.
class
)
private
void
setObjectName
()
{}
}
@ExpectException
(
NotCompliantMBeanException
.
class
)
private
static
void
testNoArgMethod
()
throws
Exception
{
testMBean
(
new
NoArgMethod
());
}
// Test that @Resource is illegal on methods with more than one argument
@MBean
public
static
class
MultiArgMethod
{
@Resource
private
void
setObjectName
(
ObjectName
name
,
String
what
)
{}
}
@ExpectException
(
NotCompliantMBeanException
.
class
)
private
static
void
testMultiArgMethod
()
throws
Exception
{
testMBean
(
new
MultiArgMethod
());
}
private
static
class
CountListener
implements
NotificationListener
{
volatile
int
count
;
public
void
handleNotification
(
Notification
notification
,
Object
handback
)
{
count
++;
}
}
private
static
void
testMBean
(
Object
mbean
)
throws
Exception
{
mbs
.
registerMBean
(
mbean
,
objectName
);
final
ObjectName
name
=
(
ObjectName
)
mbs
.
getAttribute
(
objectName
,
"MyName"
);
assert
objectName
.
equals
(
name
)
:
name
;
if
(
mbean
instanceof
Send
||
mbean
instanceof
NotificationEmitter
)
{
assert
mbs
.
isInstanceOf
(
name
,
NotificationEmitter
.
class
.
getName
());
CountListener
countL
=
new
CountListener
();
mbs
.
addNotificationListener
(
name
,
countL
,
null
,
null
);
NotificationListener
checkSource
=
new
NotificationListener
()
{
public
void
handleNotification
(
Notification
n
,
Object
h
)
{
assert
n
.
getSource
().
equals
(
name
)
:
n
.
getSource
();
}
};
mbs
.
addNotificationListener
(
name
,
checkSource
,
null
,
null
);
mbs
.
invoke
(
objectName
,
"send"
,
null
,
null
);
assert
countL
.
count
==
1
;
mbs
.
removeNotificationListener
(
name
,
checkSource
);
mbs
.
removeNotificationListener
(
name
,
countL
,
null
,
null
);
}
mbs
.
invoke
(
objectName
,
"unregisterSelf"
,
null
,
null
);
assert
!
mbs
.
isRegistered
(
objectName
);
}
}
test/javax/management/Introspector/annot/Name.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
annot
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Name
{
String
value
();
}
test/javax/management/mxbean/ComparatorExceptionTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6601652
* @summary Test exception when SortedMap or SortedSet has non-null Comparator
* @author Eamonn McManus
*/
import
java.util.SortedMap
;
import
java.util.SortedSet
;
import
java.util.TreeMap
;
import
java.util.TreeSet
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.ObjectName
;
public
class
ComparatorExceptionTest
{
public
static
interface
TestMXBean
{
public
SortedSet
<
String
>
getSortedSet
();
public
SortedMap
<
String
,
String
>
getSortedMap
();
}
public
static
class
TestImpl
implements
TestMXBean
{
public
SortedSet
<
String
>
getSortedSet
()
{
return
new
TreeSet
<
String
>(
String
.
CASE_INSENSITIVE_ORDER
);
}
public
SortedMap
<
String
,
String
>
getSortedMap
()
{
return
new
TreeMap
<
String
,
String
>(
String
.
CASE_INSENSITIVE_ORDER
);
}
}
private
static
String
failure
;
private
static
void
fail
(
String
why
)
{
failure
=
"FAILED: "
+
why
;
System
.
out
.
println
(
failure
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
ObjectName
name
=
new
ObjectName
(
"a:b=c"
);
mbs
.
registerMBean
(
new
TestImpl
(),
name
);
for
(
String
attr
:
new
String
[]
{
"SortedSet"
,
"SortedMap"
})
{
try
{
Object
value
=
mbs
.
getAttribute
(
name
,
attr
);
fail
(
"get "
+
attr
+
" did not throw exception"
);
}
catch
(
Exception
e
)
{
Throwable
t
=
e
;
while
(!(
t
instanceof
IllegalArgumentException
))
{
if
(
t
==
null
)
break
;
t
=
t
.
getCause
();
}
if
(
t
!=
null
)
System
.
out
.
println
(
"Correct exception for "
+
attr
);
else
{
fail
(
"get "
+
attr
+
" got wrong exception"
);
e
.
printStackTrace
(
System
.
out
);
}
}
}
if
(
failure
!=
null
)
throw
new
Exception
(
failure
);
}
}
test/javax/management/mxbean/MXBeanTest.java
浏览文件 @
a311994c
...
...
@@ -23,7 +23,7 @@
/*
* @test
* @bug 6175517 6278707 6318827 6305746 6392303
* @bug 6175517 6278707 6318827 6305746 6392303
6600709
* @summary General MXBean test.
* @author Eamonn McManus
* @run clean MXBeanTest MerlinMXBean TigerMXBean
...
...
@@ -40,7 +40,8 @@ import java.util.Arrays;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
javax.management.Attribute
;
import
java.util.Map
;
import
java.util.SortedMap
;
import
javax.management.JMX
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanInfo
;
...
...
@@ -55,10 +56,6 @@ import javax.management.StandardMBean;
import
javax.management.openmbean.ArrayType
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeDataInvocationHandler
;
import
javax.management.openmbean.OpenMBeanAttributeInfo
;
import
javax.management.openmbean.OpenMBeanInfo
;
import
javax.management.openmbean.OpenMBeanOperationInfo
;
import
javax.management.openmbean.OpenMBeanParameterInfo
;
import
javax.management.openmbean.OpenType
;
import
javax.management.openmbean.SimpleType
;
import
javax.management.openmbean.TabularData
;
...
...
@@ -81,10 +78,8 @@ public class MXBeanTest {
if
(
failures
==
0
)
System
.
out
.
println
(
"Test passed"
);
else
{
System
.
out
.
println
(
"TEST FAILURES: "
+
failures
);
System
.
exit
(
1
);
}
else
throw
new
Exception
(
"TEST FAILURES: "
+
failures
);
}
private
static
int
failures
=
0
;
...
...
@@ -561,6 +556,11 @@ public class MXBeanTest {
return
false
;
return
deepEqual
(
o1
,
o2
,
namedMXBeans
);
}
if
(
o1
instanceof
Map
)
{
if
(!(
o2
instanceof
Map
))
return
false
;
return
equalMap
((
Map
)
o1
,
(
Map
)
o2
,
namedMXBeans
);
}
if
(
o1
instanceof
CompositeData
&&
o2
instanceof
CompositeData
)
{
return
compositeDataEqual
((
CompositeData
)
o1
,
(
CompositeData
)
o2
,
namedMXBeans
);
...
...
@@ -600,6 +600,21 @@ public class MXBeanTest {
return
true
;
}
private
static
boolean
equalMap
(
Map
<?,?>
m1
,
Map
<?,?>
m2
,
NamedMXBeans
namedMXBeans
)
{
if
(
m1
.
size
()
!=
m2
.
size
())
return
false
;
if
((
m1
instanceof
SortedMap
)
!=
(
m2
instanceof
SortedMap
))
return
false
;
for
(
Object
k1
:
m1
.
keySet
())
{
if
(!
m2
.
containsKey
(
k1
))
return
false
;
if
(!
equal
(
m1
.
get
(
k1
),
m2
.
get
(
k1
),
namedMXBeans
))
return
false
;
}
return
true
;
}
// This is needed to work around a bug (5095277)
// in CompositeDataSupport.equals
private
static
boolean
compositeDataEqual
(
CompositeData
cd1
,
...
...
@@ -655,7 +670,7 @@ public class MXBeanTest {
/* I wanted to call this method toString(Object), but oddly enough
this meant that I couldn't call it from the inner class
MXBeanImplInvocationHandler, because the inherited Object.toString()
prevented that.
Surprising behaviour.
*/
prevented that. */
static
String
string
(
Object
o
)
{
if
(
o
==
null
)
return
"null"
;
...
...
test/javax/management/mxbean/SameObjectTwoNamesTest.java
0 → 100644
浏览文件 @
a311994c
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test SameObjectTwoNamesTest.java
* @bug 6283873
* @summary Check that registering the same MXBean under two different
* names produces an exception
* @author Alexander Shusherov
* @author Eamonn McManus
* @run main SameObjectTwoNamesTest
* @run main/othervm -Djmx.mxbean.multiname=true SameObjectTwoNamesTest
*/
import
javax.management.InstanceAlreadyExistsException
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.ObjectName
;
public
class
SameObjectTwoNamesTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
boolean
expectException
=
(
System
.
getProperty
(
"jmx.mxbean.multiname"
)
==
null
);
try
{
ObjectName
objectName1
=
new
ObjectName
(
"test:index=1"
);
ObjectName
objectName2
=
new
ObjectName
(
"test:index=2"
);
MBeanServer
mbs
=
MBeanServerFactory
.
createMBeanServer
();
MXBC_SimpleClass01
mxBeanObject
=
new
MXBC_SimpleClass01
();
mbs
.
registerMBean
(
mxBeanObject
,
objectName1
);
mbs
.
registerMBean
(
mxBeanObject
,
objectName2
);
if
(
expectException
)
{
throw
new
Exception
(
"TEST FAILED: "
+
"InstanceAlreadyExistsException was not thrown"
);
}
else
System
.
out
.
println
(
"Correctly got no exception with compat property"
);
}
catch
(
InstanceAlreadyExistsException
e
)
{
if
(
expectException
)
{
System
.
out
.
println
(
"Got expected InstanceAlreadyExistsException:"
);
e
.
printStackTrace
(
System
.
out
);
}
else
{
throw
new
Exception
(
"TEST FAILED: Got exception even though compat property set"
,
e
);
}
}
System
.
out
.
println
(
"TEST PASSED"
);
}
public
interface
MXBC_Simple01MXBean
{}
public
static
class
MXBC_SimpleClass01
implements
MXBC_Simple01MXBean
{}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录