Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
4a5cc836
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看板
提交
4a5cc836
编写于
10月 17, 2008
作者:
T
tbell
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
b6936d7c
4c231751
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
526 addition
and
161 deletion
+526
-161
src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
...e/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
+26
-1
src/share/classes/java/nio/channels/SelectableChannel.java
src/share/classes/java/nio/channels/SelectableChannel.java
+6
-0
src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java
...sses/java/nio/channels/spi/AbstractSelectableChannel.java
+10
-0
src/share/classes/javax/management/event/EventClient.java
src/share/classes/javax/management/event/EventClient.java
+16
-8
src/share/classes/javax/management/event/FetchingEventRelay.java
...re/classes/javax/management/event/FetchingEventRelay.java
+20
-20
src/share/classes/javax/management/monitor/Monitor.java
src/share/classes/javax/management/monitor/Monitor.java
+2
-2
src/share/classes/javax/management/remote/rmi/RMIConnector.java
...are/classes/javax/management/remote/rmi/RMIConnector.java
+6
-7
src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
.../classes/sun/management/jmxremote/ConnectorBootstrap.java
+20
-5
src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java
...sun/management/jmxremote/LocalRMIServerSocketFactory.java
+114
-0
src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java
src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java
+32
-18
src/share/lib/management/management.properties
src/share/lib/management/management.properties
+21
-1
src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
+30
-36
src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java
src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java
+33
-31
src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
+45
-32
test/java/nio/channels/Selector/CloseThenRegister.java
test/java/nio/channels/Selector/CloseThenRegister.java
+48
-0
test/javax/management/mxbean/TypeNameTest.java
test/javax/management/mxbean/TypeNameTest.java
+97
-0
未找到文件。
src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
浏览文件 @
4a5cc836
...
...
@@ -32,6 +32,7 @@ import java.lang.ref.WeakReference;
import
java.lang.reflect.GenericArrayType
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.ParameterizedType
;
import
java.lang.reflect.Type
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
...
...
@@ -390,7 +391,31 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
if
(
type
instanceof
Class
)
return
((
Class
)
type
).
getName
();
else
return
type
.
toString
();
return
genericTypeString
(
type
);
}
private
static
String
genericTypeString
(
Type
type
)
{
if
(
type
instanceof
Class
<?>)
{
Class
<?>
c
=
(
Class
<?>)
type
;
if
(
c
.
isArray
())
return
genericTypeString
(
c
.
getComponentType
())
+
"[]"
;
else
return
c
.
getName
();
}
else
if
(
type
instanceof
GenericArrayType
)
{
GenericArrayType
gat
=
(
GenericArrayType
)
type
;
return
genericTypeString
(
gat
.
getGenericComponentType
())
+
"[]"
;
}
else
if
(
type
instanceof
ParameterizedType
)
{
ParameterizedType
pt
=
(
ParameterizedType
)
type
;
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
genericTypeString
(
pt
.
getRawType
())).
append
(
"<"
);
String
sep
=
""
;
for
(
Type
t
:
pt
.
getActualTypeArguments
())
{
sb
.
append
(
sep
).
append
(
genericTypeString
(
t
));
sep
=
", "
;
}
return
sb
.
append
(
">"
).
toString
();
}
else
return
"???"
;
}
private
final
PerInterfaceMap
<
ConvertingMethod
>
...
...
src/share/classes/java/nio/channels/SelectableChannel.java
浏览文件 @
4a5cc836
...
...
@@ -191,6 +191,9 @@ public abstract class SelectableChannel
* @throws ClosedChannelException
* If this channel is closed
*
* @throws ClosedSelectorException
* If the selector is closed
*
* @throws IllegalBlockingModeException
* If this channel is in blocking mode
*
...
...
@@ -246,6 +249,9 @@ public abstract class SelectableChannel
* @throws ClosedChannelException
* If this channel is closed
*
* @throws ClosedSelectorException
* If the selector is closed
*
* @throws IllegalBlockingModeException
* If this channel is in blocking mode
*
...
...
src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java
浏览文件 @
4a5cc836
...
...
@@ -175,6 +175,16 @@ public abstract class AbstractSelectableChannel
* the selector is invoked while holding the appropriate locks. The
* resulting key is added to this channel's key set before being returned.
* </p>
*
* @throws ClosedSelectorException {@inheritDoc}
*
* @throws IllegalBlockingModeException {@inheritDoc}
*
* @throws IllegalSelectorException {@inheritDoc}
*
* @throws CancelledKeyException {@inheritDoc}
*
* @throws IllegalArgumentException {@inheritDoc}
*/
public
final
SelectionKey
register
(
Selector
sel
,
int
ops
,
Object
att
)
...
...
src/share/classes/javax/management/event/EventClient.java
浏览文件 @
4a5cc836
...
...
@@ -265,12 +265,20 @@ public class EventClient implements EventConsumer, NotificationManager {
public
ScheduledThreadPoolExecutor
createThreadPool
(
ThreadGroup
group
)
{
ThreadFactory
daemonThreadFactory
=
new
DaemonThreadFactory
(
"JMX EventClient lease renewer %d"
);
ScheduledThreadPoolExecutor
exec
=
new
ScheduledThreadPoolExecutor
(
20
,
daemonThreadFactory
);
exec
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
exec
.
allowCoreThreadTimeOut
(
true
);
exec
.
setRemoveOnCancelPolicy
(
true
);
return
exec
;
ScheduledThreadPoolExecutor
executor
=
new
ScheduledThreadPoolExecutor
(
20
,
daemonThreadFactory
);
executor
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
executor
.
allowCoreThreadTimeOut
(
true
);
executor
.
setRemoveOnCancelPolicy
(
true
);
// By default, a ScheduledThreadPoolExecutor will keep jobs
// in its queue even after they have been cancelled. They
// will only be removed when their scheduled time arrives.
// Since the job references the LeaseRenewer which references
// this EventClient, this can lead to a moderately large number
// of objects remaining referenced until the renewal time
// arrives. Hence the above call, which removes the job from
// the queue as soon as it is cancelled.
return
executor
;
}
};
return
leaseRenewerThreadPool
.
getThreadPoolExecutor
(
create
);
...
...
@@ -381,7 +389,7 @@ public class EventClient implements EventConsumer, NotificationManager {
listenerId
=
eventClientDelegate
.
addListener
(
clientId
,
name
,
filter
);
}
catch
(
EventClientNotFoundException
ecnfe
)
{
final
IOException
ioe
=
new
IOException
();
final
IOException
ioe
=
new
IOException
(
ecnfe
.
getMessage
()
);
ioe
.
initCause
(
ecnfe
);
throw
ioe
;
}
...
...
@@ -488,7 +496,7 @@ public class EventClient implements EventConsumer, NotificationManager {
listenerId
=
eventClientDelegate
.
addSubscriber
(
clientId
,
name
,
filter
);
}
catch
(
EventClientNotFoundException
ecnfe
)
{
final
IOException
ioe
=
new
IOException
();
final
IOException
ioe
=
new
IOException
(
ecnfe
.
getMessage
()
);
ioe
.
initCause
(
ecnfe
);
throw
ioe
;
}
...
...
src/share/classes/javax/management/event/FetchingEventRelay.java
浏览文件 @
4a5cc836
...
...
@@ -91,7 +91,7 @@ public class FetchingEventRelay implements EventRelay {
* the fetching.
*
* @param delegate The {@code EventClientDelegateMBean} to work with.
* @param
e
xecutor Used to do the fetching. A new thread is created if
* @param
fetchE
xecutor Used to do the fetching. A new thread is created if
* {@code null}.
* @throws IOException If failed to work with the {@code delegate}.
* @throws MBeanException if unable to add a client to the remote
...
...
@@ -101,12 +101,12 @@ public class FetchingEventRelay implements EventRelay {
* @throws IllegalArgumentException If {@code delegate} is {@code null}.
*/
public
FetchingEventRelay
(
EventClientDelegateMBean
delegate
,
Executor
e
xecutor
)
throws
IOException
,
MBeanException
{
Executor
fetchE
xecutor
)
throws
IOException
,
MBeanException
{
this
(
delegate
,
DEFAULT_BUFFER_SIZE
,
DEFAULT_WAITING_TIMEOUT
,
DEFAULT_MAX_NOTIFICATIONS
,
e
xecutor
);
fetchE
xecutor
);
}
/**
...
...
@@ -120,7 +120,7 @@ public class FetchingEventRelay implements EventRelay {
* @param timeout The waiting time in millseconds when fetching
* notifications from an {@code EventClientDelegateMBean}.
* @param maxNotifs The maximum notifications to fetch every time.
* @param
e
xecutor Used to do the fetching. A new thread is created if
* @param
fetchE
xecutor Used to do the fetching. A new thread is created if
* {@code null}.
* @throws IOException if failed to communicate with the {@code delegate}.
* @throws MBeanException if unable to add a client to the remote
...
...
@@ -133,12 +133,12 @@ public class FetchingEventRelay implements EventRelay {
int
bufferSize
,
long
timeout
,
int
maxNotifs
,
Executor
e
xecutor
)
throws
IOException
,
MBeanException
{
Executor
fetchE
xecutor
)
throws
IOException
,
MBeanException
{
this
(
delegate
,
bufferSize
,
timeout
,
maxNotifs
,
e
xecutor
,
fetchE
xecutor
,
FetchingEventForwarder
.
class
.
getName
(),
new
Object
[]
{
bufferSize
},
new
String
[]
{
int
.
class
.
getName
()});
...
...
@@ -155,7 +155,7 @@ public class FetchingEventRelay implements EventRelay {
* @param timeout The waiting time in millseconds when fetching
* notifications from an {@code EventClientDelegateMBean}.
* @param maxNotifs The maximum notifications to fetch every time.
* @param
e
xecutor Used to do the fetching.
* @param
fetchE
xecutor Used to do the fetching.
* @param forwarderName the class name of a user specific EventForwarder
* to create in server to forward notifications to this object. The class
* should be a subclass of the class {@link FetchingEventForwarder}.
...
...
@@ -174,7 +174,7 @@ public class FetchingEventRelay implements EventRelay {
int
bufferSize
,
long
timeout
,
int
maxNotifs
,
Executor
e
xecutor
,
Executor
fetchE
xecutor
,
String
forwarderName
,
Object
[]
params
,
String
[]
sig
)
throws
IOException
,
MBeanException
{
...
...
@@ -184,11 +184,11 @@ public class FetchingEventRelay implements EventRelay {
bufferSize
+
" "
+
timeout
+
" "
+
maxNotifs
+
" "
+
e
xecutor
+
" "
+
fetchE
xecutor
+
" "
+
forwarderName
+
" "
);
}
if
(
delegate
==
null
)
{
if
(
delegate
==
null
)
{
throw
new
NullPointerException
(
"Null EventClientDelegateMBean!"
);
}
...
...
@@ -212,16 +212,16 @@ public class FetchingEventRelay implements EventRelay {
this
.
timeout
=
timeout
;
this
.
maxNotifs
=
maxNotifs
;
if
(
e
xecutor
==
null
)
{
ScheduledThreadPoolExecutor
stpe
=
new
ScheduledThreadPoolExecutor
(
1
,
daemonThreadFactory
);
stpe
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
stpe
.
allowCoreThreadTimeOut
(
true
);
executor
=
stpe
;
this
.
defaultExecutor
=
stpe
;
if
(
fetchE
xecutor
==
null
)
{
ScheduledThreadPoolExecutor
executor
=
new
ScheduledThreadPoolExecutor
(
1
,
daemonThreadFactory
);
executor
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
executor
.
allowCoreThreadTimeOut
(
true
);
fetchExecutor
=
executor
;
this
.
defaultExecutor
=
executor
;
}
else
this
.
defaultExecutor
=
null
;
this
.
executor
=
e
xecutor
;
this
.
fetchExecutor
=
fetchE
xecutor
;
startSequenceNumber
=
0
;
fetchingJob
=
new
MyJob
();
...
...
@@ -258,7 +258,7 @@ public class FetchingEventRelay implements EventRelay {
private
class
MyJob
extends
RepeatedSingletonJob
{
public
MyJob
()
{
super
(
e
xecutor
);
super
(
fetchE
xecutor
);
}
public
boolean
isSuspended
()
{
...
...
@@ -368,7 +368,7 @@ public class FetchingEventRelay implements EventRelay {
private
String
clientId
;
private
boolean
stopped
=
false
;
private
final
Executor
e
xecutor
;
private
final
Executor
fetchE
xecutor
;
private
final
ExecutorService
defaultExecutor
;
private
final
MyJob
fetchingJob
;
...
...
src/share/classes/javax/management/monitor/Monitor.java
浏览文件 @
4a5cc836
...
...
@@ -181,7 +181,7 @@ public abstract class Monitor
/**
* Executor Service.
*/
private
static
final
ExecutorService
executor
;
private
static
final
ThreadPoolExecutor
executor
;
static
{
final
String
maximumPoolSizeSysProp
=
"jmx.x.monitor.maximum.pool.size"
;
final
String
maximumPoolSizeStr
=
AccessController
.
doPrivileged
(
...
...
@@ -218,7 +218,7 @@ public abstract class Monitor
TimeUnit
.
SECONDS
,
new
LinkedBlockingQueue
<
Runnable
>(),
new
DaemonThreadFactory
(
"Executor"
));
((
ThreadPoolExecutor
)
executor
)
.
allowCoreThreadTimeOut
(
true
);
executor
.
allowCoreThreadTimeOut
(
true
);
}
/**
...
...
src/share/classes/javax/management/remote/rmi/RMIConnector.java
浏览文件 @
4a5cc836
...
...
@@ -71,9 +71,8 @@ import java.util.Map;
import
java.util.Properties
;
import
java.util.Set
;
import
java.util.WeakHashMap
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.LinkedBlocking
Deq
ue
;
import
java.util.concurrent.LinkedBlocking
Que
ue
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.ThreadPoolExecutor
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -421,12 +420,12 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable
public
ThreadPoolExecutor
createThreadPool
(
ThreadGroup
group
)
{
ThreadFactory
daemonThreadFactory
=
new
DaemonThreadFactory
(
"JMX RMIConnector listener dispatch %d"
);
ThreadPoolExecutor
exec
=
new
ThreadPoolExecutor
(
ThreadPoolExecutor
exec
utor
=
new
ThreadPoolExecutor
(
1
,
10
,
1
,
TimeUnit
.
SECONDS
,
new
LinkedBlocking
Deq
ue
<
Runnable
>(),
new
LinkedBlocking
Que
ue
<
Runnable
>(),
daemonThreadFactory
);
exec
.
allowCoreThreadTimeOut
(
true
);
return
exec
;
exec
utor
.
allowCoreThreadTimeOut
(
true
);
return
exec
utor
;
}
};
return
listenerDispatchThreadPool
.
getThreadPoolExecutor
(
create
);
...
...
@@ -1503,7 +1502,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable
super
(
period
);
}
public
void
gotIOException
(
IOException
ioe
)
throws
IOException
{
public
void
gotIOException
(
IOException
ioe
)
throws
IOException
{
if
(
ioe
instanceof
NoSuchObjectException
)
{
// need to restart
super
.
gotIOException
(
ioe
);
...
...
src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
浏览文件 @
4a5cc836
...
...
@@ -80,7 +80,7 @@ import sun.management.AgentConfigurationError;
import
static
sun
.
management
.
AgentConfigurationError
.*;
import
sun.management.ConnectorAddressLink
;
import
sun.management.FileSystem
;
import
sun.management.snmp.util.Mib
Logger
;
import
com.sun.jmx.remote.util.Class
Logger
;
import
com.sun.jmx.remote.internal.RMIExporter
;
import
com.sun.jmx.remote.security.JMXPluggableAuthenticator
;
...
...
@@ -99,6 +99,7 @@ public final class ConnectorBootstrap {
public
static
final
String
PORT
=
"0"
;
public
static
final
String
CONFIG_FILE_NAME
=
"management.properties"
;
public
static
final
String
USE_SSL
=
"true"
;
public
static
final
String
USE_LOCAL_ONLY
=
"true"
;
public
static
final
String
USE_REGISTRY_SSL
=
"false"
;
public
static
final
String
USE_AUTHENTICATION
=
"true"
;
public
static
final
String
PASSWORD_FILE_NAME
=
"jmxremote.password"
;
...
...
@@ -115,6 +116,8 @@ public final class ConnectorBootstrap {
"com.sun.management.jmxremote.port"
;
public
static
final
String
CONFIG_FILE_NAME
=
"com.sun.management.config.file"
;
public
static
final
String
USE_LOCAL_ONLY
=
"com.sun.management.jmxremote.local.only"
;
public
static
final
String
USE_SSL
=
"com.sun.management.jmxremote.ssl"
;
public
static
final
String
USE_REGISTRY_SSL
=
...
...
@@ -384,7 +387,7 @@ public final class ConnectorBootstrap {
checkAccessFile
(
accessFileName
);
}
if
(
log
.
isD
ebugOn
())
{
if
(
log
.
d
ebugOn
())
{
log
.
debug
(
"initialize"
,
Agent
.
getText
(
"jmxremote.ConnectorBootstrap.initialize"
)
+
"\n\t"
+
PropertyNames
.
PORT
+
"="
+
port
+
...
...
@@ -477,6 +480,18 @@ public final class ConnectorBootstrap {
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
try
{
JMXServiceURL
url
=
new
JMXServiceURL
(
"rmi"
,
localhost
,
0
);
// Do we accept connections from local interfaces only?
Properties
props
=
Agent
.
getManagementProperties
();
if
(
props
==
null
)
{
props
=
new
Properties
();
}
String
useLocalOnlyStr
=
props
.
getProperty
(
PropertyNames
.
USE_LOCAL_ONLY
,
DefaultValues
.
USE_LOCAL_ONLY
);
boolean
useLocalOnly
=
Boolean
.
valueOf
(
useLocalOnlyStr
).
booleanValue
();
if
(
useLocalOnly
)
{
env
.
put
(
RMIConnectorServer
.
RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE
,
new
LocalRMIServerSocketFactory
());
}
JMXConnectorServer
server
=
JMXConnectorServerFactory
.
newJMXConnectorServer
(
url
,
env
,
mbs
);
server
.
start
();
...
...
@@ -764,7 +779,7 @@ public final class ConnectorBootstrap {
private
ConnectorBootstrap
()
{
}
// XXX Revisit: should probably clone this MibLogger....
private
static
final
MibLogger
log
=
new
MibLogger
(
ConnectorBootstrap
.
class
);
private
static
final
ClassLogger
log
=
new
ClassLogger
(
ConnectorBootstrap
.
class
.
getPackage
().
getName
(),
"ConnectorBootstrap"
);
}
src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java
0 → 100644
浏览文件 @
4a5cc836
/*
* 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
sun.management.jmxremote
;
import
java.io.IOException
;
import
java.net.InetAddress
;
import
java.net.NetworkInterface
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.net.SocketException
;
import
java.rmi.server.RMIServerSocketFactory
;
import
java.util.Enumeration
;
/**
* This RMI server socket factory creates server sockets that
* will only accept connection requests from clients running
* on the host where the RMI remote objects have been exported.
*/
public
final
class
LocalRMIServerSocketFactory
implements
RMIServerSocketFactory
{
/**
* Creates a server socket that only accepts connection requests from
* clients running on the host where the RMI remote objects have been
* exported.
*/
public
ServerSocket
createServerSocket
(
int
port
)
throws
IOException
{
return
new
ServerSocket
(
port
)
{
@Override
public
Socket
accept
()
throws
IOException
{
Socket
socket
=
super
.
accept
();
InetAddress
remoteAddr
=
socket
.
getInetAddress
();
final
String
msg
=
"The server sockets created using the "
+
"LocalRMIServerSocketFactory only accept connections "
+
"from clients running on the host where the RMI "
+
"remote objects have been exported."
;
if
(
remoteAddr
.
isAnyLocalAddress
())
{
// local address: accept the connection.
return
socket
;
}
// Retrieve all the network interfaces on this host.
Enumeration
<
NetworkInterface
>
nis
;
try
{
nis
=
NetworkInterface
.
getNetworkInterfaces
();
}
catch
(
SocketException
e
)
{
try
{
socket
.
close
();
}
catch
(
IOException
ioe
)
{
// Ignore...
}
throw
new
IOException
(
msg
,
e
);
}
// Walk through the network interfaces to see
// if any of them matches the client's address.
// If true, then the client's address is local.
while
(
nis
.
hasMoreElements
())
{
NetworkInterface
ni
=
nis
.
nextElement
();
Enumeration
<
InetAddress
>
addrs
=
ni
.
getInetAddresses
();
while
(
addrs
.
hasMoreElements
())
{
InetAddress
localAddr
=
addrs
.
nextElement
();
if
(
localAddr
.
equals
(
remoteAddr
))
{
return
socket
;
}
}
}
// The client's address is remote so refuse the connection.
try
{
socket
.
close
();
}
catch
(
IOException
ioe
)
{
// Ignore...
}
throw
new
IOException
(
msg
);
}
};
}
/**
* Two LocalRMIServerSocketFactory objects
* are equal if they are of the same type.
*/
@Override
public
boolean
equals
(
Object
obj
)
{
return
(
obj
instanceof
LocalRMIServerSocketFactory
);
}
/**
* Returns a hash code value for this LocalRMIServerSocketFactory.
*/
@Override
public
int
hashCode
()
{
return
getClass
().
hashCode
();
}
}
src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java
浏览文件 @
4a5cc836
...
...
@@ -58,6 +58,9 @@ abstract class AbstractPollSelectorImpl
// True if this Selector has been closed
private
boolean
closed
=
false
;
// Lock for close and cleanup
private
Object
closeLock
=
new
Object
();
AbstractPollSelectorImpl
(
SelectorProvider
sp
,
int
channels
,
int
offset
)
{
super
(
sp
);
this
.
totalChannels
=
channels
;
...
...
@@ -65,7 +68,11 @@ abstract class AbstractPollSelectorImpl
}
void
putEventOps
(
SelectionKeyImpl
sk
,
int
ops
)
{
pollWrapper
.
putEventOps
(
sk
.
getIndex
(),
ops
);
synchronized
(
closeLock
)
{
if
(
closed
)
throw
new
ClosedSelectorException
();
pollWrapper
.
putEventOps
(
sk
.
getIndex
(),
ops
);
}
}
public
Selector
wakeup
()
{
...
...
@@ -76,7 +83,9 @@ abstract class AbstractPollSelectorImpl
protected
abstract
int
doSelect
(
long
timeout
)
throws
IOException
;
protected
void
implClose
()
throws
IOException
{
if
(!
closed
)
{
synchronized
(
closeLock
)
{
if
(
closed
)
return
;
closed
=
true
;
// Deregister channels
for
(
int
i
=
channelOffset
;
i
<
totalChannels
;
i
++)
{
...
...
@@ -129,23 +138,28 @@ abstract class AbstractPollSelectorImpl
}
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
// Check to see if the array is large enough
if
(
channelArray
.
length
==
totalChannels
)
{
// Make a larger array
int
newSize
=
pollWrapper
.
totalChannels
*
2
;
SelectionKeyImpl
temp
[]
=
new
SelectionKeyImpl
[
newSize
];
// Copy over
for
(
int
i
=
channelOffset
;
i
<
totalChannels
;
i
++)
temp
[
i
]
=
channelArray
[
i
];
channelArray
=
temp
;
// Grow the NativeObject poll array
pollWrapper
.
grow
(
newSize
);
synchronized
(
closeLock
)
{
if
(
closed
)
throw
new
ClosedSelectorException
();
// Check to see if the array is large enough
if
(
channelArray
.
length
==
totalChannels
)
{
// Make a larger array
int
newSize
=
pollWrapper
.
totalChannels
*
2
;
SelectionKeyImpl
temp
[]
=
new
SelectionKeyImpl
[
newSize
];
// Copy over
for
(
int
i
=
channelOffset
;
i
<
totalChannels
;
i
++)
temp
[
i
]
=
channelArray
[
i
];
channelArray
=
temp
;
// Grow the NativeObject poll array
pollWrapper
.
grow
(
newSize
);
}
channelArray
[
totalChannels
]
=
ski
;
ski
.
setIndex
(
totalChannels
);
pollWrapper
.
addEntry
(
ski
.
channel
);
totalChannels
++;
keys
.
add
(
ski
);
}
channelArray
[
totalChannels
]
=
ski
;
ski
.
setIndex
(
totalChannels
);
pollWrapper
.
addEntry
(
ski
.
channel
);
totalChannels
++;
keys
.
add
(
ski
);
}
protected
void
implDereg
(
SelectionKeyImpl
ski
)
throws
IOException
{
...
...
src/share/lib/management/management.properties
浏览文件 @
4a5cc836
...
...
@@ -82,7 +82,7 @@
#
# com.sun.management.snmp.interface=<InetAddress>
# Specifies the local interface on which the SNMP agent will bind.
# This is useful
l
when running on machines which have several
# This is useful when running on machines which have several
# interfaces defined. It makes it possible to listen to a specific
# subnet accessible through that interface.
# Default for this property is "localhost".
...
...
@@ -143,6 +143,26 @@
# running MBean server, the connector, or the registry.
#
#
# ########## RMI connector settings for local management ##########
#
# com.sun.management.jmxremote.local.only=true|false
# Default for this property is true. (Case for true/false ignored)
# If this property is specified as true then the local JMX RMI connector
# server will only accept connection requests from clients running on
# the host where the out-of-the-box JMX management agent is running.
# In order to ensure backwards compatibility this property could be
# set to false. However, deploying the local management agent in this
# way is discouraged because the local JMX RMI connector server will
# accept connection requests from any client either local or remote.
# For remote management the remote JMX RMI connector server should
# be used instead with authentication and SSL/TLS encryption enabled.
#
# For allowing the local management agent accept local
# and remote connection requests use the following line
# com.sun.management.jmxremote.local.only=false
#
# ###################### RMI SSL #############################
#
...
...
src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
浏览文件 @
4a5cc836
...
...
@@ -46,15 +46,15 @@ class DevPollSelectorImpl
// The poll object
DevPollArrayWrapper
pollWrapper
;
// The number of valid channels in this Selector's poll array
private
int
totalChannels
;
// Maps from file descriptors to keys
private
Map
<
Integer
,
SelectionKeyImpl
>
fdToKey
;
// True if this Selector has been closed
private
boolean
closed
=
false
;
// Lock for close/cleanup
private
Object
closeLock
=
new
Object
();
// Lock for interrupt triggering and clearing
private
Object
interruptLock
=
new
Object
();
private
boolean
interruptTriggered
=
false
;
...
...
@@ -72,7 +72,6 @@ class DevPollSelectorImpl
pollWrapper
=
new
DevPollArrayWrapper
();
pollWrapper
.
initInterrupt
(
fd0
,
fd1
);
fdToKey
=
new
HashMap
<
Integer
,
SelectionKeyImpl
>();
totalChannels
=
1
;
}
protected
int
doSelect
(
long
timeout
)
...
...
@@ -131,45 +130,39 @@ class DevPollSelectorImpl
}
protected
void
implClose
()
throws
IOException
{
if
(!
closed
)
{
closed
=
true
;
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
if
(
closed
)
return
;
closed
=
true
;
FileDispatcher
.
closeIntFD
(
fd0
);
FileDispatcher
.
closeIntFD
(
fd1
);
if
(
pollWrapper
!=
null
)
{
pollWrapper
.
release
(
fd0
);
pollWrapper
.
closeDevPollFD
();
pollWrapper
=
null
;
selectedKeys
=
null
;
// Deregister channels
Iterator
i
=
keys
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
i
.
remove
();
}
totalChannels
=
0
;
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
}
fd0
=
-
1
;
fd1
=
-
1
;
FileDispatcher
.
closeIntFD
(
fd0
);
FileDispatcher
.
closeIntFD
(
fd1
);
pollWrapper
.
release
(
fd0
);
pollWrapper
.
closeDevPollFD
();
selectedKeys
=
null
;
// Deregister channels
Iterator
i
=
keys
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
i
.
remove
();
}
fd0
=
-
1
;
fd1
=
-
1
;
}
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
int
fd
=
IOUtil
.
fdVal
(
ski
.
channel
.
getFD
());
fdToKey
.
put
(
Integer
.
valueOf
(
fd
),
ski
);
totalChannels
++;
keys
.
add
(
ski
);
}
...
...
@@ -179,7 +172,6 @@ class DevPollSelectorImpl
int
fd
=
ski
.
channel
.
getFDVal
();
fdToKey
.
remove
(
Integer
.
valueOf
(
fd
));
pollWrapper
.
release
(
fd
);
totalChannels
--;
ski
.
setIndex
(-
1
);
keys
.
remove
(
ski
);
selectedKeys
.
remove
(
ski
);
...
...
@@ -190,6 +182,8 @@ class DevPollSelectorImpl
}
void
putEventOps
(
SelectionKeyImpl
sk
,
int
ops
)
{
if
(
closed
)
throw
new
ClosedSelectorException
();
int
fd
=
IOUtil
.
fdVal
(
sk
.
channel
.
getFD
());
pollWrapper
.
setInterest
(
fd
,
ops
);
}
...
...
src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java
浏览文件 @
4a5cc836
/*
* Copyright 2005-200
8
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-200
7
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
...
...
@@ -31,7 +31,6 @@ import java.nio.channels.spi.*;
import
java.util.*
;
import
sun.misc.*
;
/**
* An implementation of Selector for Linux 2.6+ kernels that uses
* the epoll event notification facility.
...
...
@@ -51,7 +50,7 @@ class EPollSelectorImpl
private
Map
<
Integer
,
SelectionKeyImpl
>
fdToKey
;
// True if this Selector has been closed
private
boolean
closed
=
false
;
private
volatile
boolean
closed
=
false
;
// Lock for interrupt triggering and clearing
private
Object
interruptLock
=
new
Object
();
...
...
@@ -128,40 +127,41 @@ class EPollSelectorImpl
}
protected
void
implClose
()
throws
IOException
{
if
(!
closed
)
{
closed
=
true
;
if
(
closed
)
return
;
closed
=
true
;
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
FileDispatcher
.
closeIntFD
(
fd0
);
FileDispatcher
.
closeIntFD
(
fd1
);
if
(
pollWrapper
!=
null
)
{
pollWrapper
.
release
(
fd0
);
pollWrapper
.
closeEPollFD
();
pollWrapper
=
null
;
selectedKeys
=
null
;
// Deregister channels
Iterator
i
=
keys
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
i
.
remove
();
}
}
fd0
=
-
1
;
fd1
=
-
1
;
FileDispatcher
.
closeIntFD
(
fd0
);
FileDispatcher
.
closeIntFD
(
fd1
);
pollWrapper
.
release
(
fd0
);
pollWrapper
.
closeEPollFD
();
// it is possible
selectedKeys
=
null
;
// Deregister channels
Iterator
i
=
keys
.
iterator
();
while
(
i
.
hasNext
())
{
SelectionKeyImpl
ski
=
(
SelectionKeyImpl
)
i
.
next
();
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
i
.
remove
();
}
fd0
=
-
1
;
fd1
=
-
1
;
}
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
if
(
closed
)
throw
new
ClosedSelectorException
();
int
fd
=
IOUtil
.
fdVal
(
ski
.
channel
.
getFD
());
fdToKey
.
put
(
Integer
.
valueOf
(
fd
),
ski
);
pollWrapper
.
add
(
fd
);
...
...
@@ -183,6 +183,8 @@ class EPollSelectorImpl
}
void
putEventOps
(
SelectionKeyImpl
sk
,
int
ops
)
{
if
(
closed
)
throw
new
ClosedSelectorException
();
int
fd
=
IOUtil
.
fdVal
(
sk
.
channel
.
getFD
());
pollWrapper
.
setInterest
(
fd
,
ops
);
}
...
...
src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
浏览文件 @
4a5cc836
/*
* Copyright 2002-200
8
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-200
7
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
...
...
@@ -80,6 +80,9 @@ final class WindowsSelectorImpl extends SelectorImpl {
// File descriptors corresponding to source and sink
private
final
int
wakeupSourceFd
,
wakeupSinkFd
;
// Lock for close cleanup
private
Object
closeLock
=
new
Object
();
// Maps file descriptors to their indices in pollArray
private
final
static
class
FdMap
extends
HashMap
<
Integer
,
MapEntry
>
{
static
final
long
serialVersionUID
=
0L
;
...
...
@@ -473,42 +476,48 @@ final class WindowsSelectorImpl extends SelectorImpl {
}
protected
void
implClose
()
throws
IOException
{
if
(
channelArray
!=
null
)
{
if
(
pollWrapper
!=
null
)
{
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
wakeupPipe
.
sink
().
close
();
wakeupPipe
.
source
().
close
();
for
(
int
i
=
1
;
i
<
totalChannels
;
i
++)
{
// Deregister channels
if
(
i
%
MAX_SELECTABLE_FDS
!=
0
)
{
// skip wakeupEvent
deregister
(
channelArray
[
i
]);
SelectableChannel
selch
=
channelArray
[
i
].
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
synchronized
(
closeLock
)
{
if
(
channelArray
!=
null
)
{
if
(
pollWrapper
!=
null
)
{
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
}
pollWrapper
.
free
();
pollWrapper
=
null
;
selectedKeys
=
null
;
channelArray
=
null
;
threads
.
clear
();
// Call startThreads. All remaining helper threads now exit,
// since threads.size() = 0;
startLock
.
startThreads
();
wakeupPipe
.
sink
().
close
();
wakeupPipe
.
source
().
close
();
for
(
int
i
=
1
;
i
<
totalChannels
;
i
++)
{
// Deregister channels
if
(
i
%
MAX_SELECTABLE_FDS
!=
0
)
{
// skip wakeupEvent
deregister
(
channelArray
[
i
]);
SelectableChannel
selch
=
channelArray
[
i
].
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
}
}
pollWrapper
.
free
();
pollWrapper
=
null
;
selectedKeys
=
null
;
channelArray
=
null
;
threads
.
clear
();
// Call startThreads. All remaining helper threads now exit,
// since threads.size() = 0;
startLock
.
startThreads
();
}
}
}
}
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
growIfNeeded
();
channelArray
[
totalChannels
]
=
ski
;
ski
.
setIndex
(
totalChannels
);
fdMap
.
put
(
ski
);
keys
.
add
(
ski
);
pollWrapper
.
addEntry
(
totalChannels
,
ski
);
totalChannels
++;
synchronized
(
closeLock
)
{
if
(
pollWrapper
==
null
)
throw
new
ClosedSelectorException
();
growIfNeeded
();
channelArray
[
totalChannels
]
=
ski
;
ski
.
setIndex
(
totalChannels
);
fdMap
.
put
(
ski
);
keys
.
add
(
ski
);
pollWrapper
.
addEntry
(
totalChannels
,
ski
);
totalChannels
++;
}
}
private
void
growIfNeeded
()
{
...
...
@@ -554,7 +563,11 @@ final class WindowsSelectorImpl extends SelectorImpl {
}
void
putEventOps
(
SelectionKeyImpl
sk
,
int
ops
)
{
pollWrapper
.
putEventOps
(
sk
.
getIndex
(),
ops
);
synchronized
(
closeLock
)
{
if
(
pollWrapper
==
null
)
throw
new
ClosedSelectorException
();
pollWrapper
.
putEventOps
(
sk
.
getIndex
(),
ops
);
}
}
public
Selector
wakeup
()
{
...
...
test/java/nio/channels/Selector/CloseThenRegister.java
0 → 100644
浏览文件 @
4a5cc836
/*
* 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 5025260
* @summary ClosedSelectorException is expected when register after close
*/
import
java.net.*
;
import
java.nio.channels.*
;
public
class
CloseThenRegister
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
try
{
Selector
s
=
Selector
.
open
();
s
.
close
();
ServerSocketChannel
c
=
ServerSocketChannel
.
open
();
c
.
socket
().
bind
(
new
InetSocketAddress
(
40000
));
c
.
configureBlocking
(
false
);
c
.
register
(
s
,
SelectionKey
.
OP_ACCEPT
);
}
catch
(
ClosedSelectorException
cse
)
{
return
;
}
throw
new
RuntimeException
(
"register after close does not cause CSE!"
);
}
}
test/javax/management/mxbean/TypeNameTest.java
0 → 100644
浏览文件 @
4a5cc836
/*
* 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 6757225
* @summary Test that type names in MXBeans match their spec.
* @author Eamonn McManus
*/
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.util.List
;
import
java.util.Map
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerFactory
;
import
javax.management.ObjectName
;
import
javax.management.StandardMBean
;
public
class
TypeNameTest
{
public
static
interface
TestMXBean
{
public
int
getInt
();
public
String
IntName
=
"int"
;
public
Map
<
String
,
Integer
>
getMapSI
();
public
String
MapSIName
=
"java.util.Map<java.lang.String, java.lang.Integer>"
;
public
Map
<
String
,
int
[]>
getMapSInts
();
public
String
MapSIntsName
=
"java.util.Map<java.lang.String, int[]>"
;
public
List
<
List
<
int
[]>>
getListListInts
();
public
String
ListListIntsName
=
"java.util.List<java.util.List<int[]>>"
;
}
private
static
InvocationHandler
nullIH
=
new
InvocationHandler
()
{
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
return
null
;
}
};
static
String
failure
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
TestMXBean
testImpl
=
(
TestMXBean
)
Proxy
.
newProxyInstance
(
TestMXBean
.
class
.
getClassLoader
(),
new
Class
<?>[]
{
TestMXBean
.
class
},
nullIH
);
Object
mxbean
=
new
StandardMBean
(
testImpl
,
TestMXBean
.
class
,
true
);
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
ObjectName
name
=
new
ObjectName
(
"a:b=c"
);
mbs
.
registerMBean
(
mxbean
,
name
);
MBeanInfo
mbi
=
mbs
.
getMBeanInfo
(
name
);
MBeanAttributeInfo
[]
mbais
=
mbi
.
getAttributes
();
for
(
MBeanAttributeInfo
mbai
:
mbais
)
{
String
attrName
=
mbai
.
getName
();
String
attrTypeName
=
(
String
)
mbai
.
getDescriptor
().
getFieldValue
(
"originalType"
);
String
fieldName
=
attrName
+
"Name"
;
Field
nameField
=
TestMXBean
.
class
.
getField
(
fieldName
);
String
expectedTypeName
=
(
String
)
nameField
.
get
(
null
);
if
(
expectedTypeName
.
equals
(
attrTypeName
))
{
System
.
out
.
println
(
"OK: "
+
attrName
+
": "
+
attrTypeName
);
}
else
{
failure
=
"For attribute "
+
attrName
+
" expected type name \""
+
expectedTypeName
+
"\", found type name \""
+
attrTypeName
+
"\""
;
System
.
out
.
println
(
"FAIL: "
+
failure
);
}
}
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录