Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
8f834f5c
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8f834f5c
编写于
5月 27, 2013
作者:
C
chegar
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
23cdb220
89b85933
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
210 addition
and
66 deletion
+210
-66
src/share/classes/java/lang/ref/Reference.java
src/share/classes/java/lang/ref/Reference.java
+17
-2
src/windows/classes/sun/nio/fs/WindowsConstants.java
src/windows/classes/sun/nio/fs/WindowsConstants.java
+1
-0
src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
+7
-7
src/windows/classes/sun/nio/fs/WindowsWatchService.java
src/windows/classes/sun/nio/fs/WindowsWatchService.java
+55
-47
src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
+18
-10
test/java/lang/ref/OOMEInReferenceHandler.java
test/java/lang/ref/OOMEInReferenceHandler.java
+112
-0
未找到文件。
src/share/classes/java/lang/ref/Reference.java
浏览文件 @
8f834f5c
/*
* Copyright (c) 1997, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -138,8 +138,23 @@ public abstract class Reference<T> {
pending
=
r
.
discovered
;
r
.
discovered
=
null
;
}
else
{
// The waiting on the lock may cause an OOME because it may try to allocate
// exception objects, so also catch OOME here to avoid silent exit of the
// reference handler thread.
//
// Explicitly define the order of the two exceptions we catch here
// when waiting for the lock.
//
// We do not want to try to potentially load the InterruptedException class
// (which would be done if this was its first use, and InterruptedException
// were checked first) in this situation.
//
// This may lead to the VM not ever trying to load the InterruptedException
// class again.
try
{
lock
.
wait
();
try
{
lock
.
wait
();
}
catch
(
OutOfMemoryError
x
)
{
}
}
catch
(
InterruptedException
x
)
{
}
continue
;
}
...
...
src/windows/classes/sun/nio/fs/WindowsConstants.java
浏览文件 @
8f834f5c
...
...
@@ -100,6 +100,7 @@ class WindowsConstants {
public
static
final
int
ERROR_INVALID_LEVEL
=
124
;
public
static
final
int
ERROR_DIR_NOT_EMPTY
=
145
;
public
static
final
int
ERROR_ALREADY_EXISTS
=
183
;
public
static
final
int
ERROR_MORE_DATA
=
234
;
public
static
final
int
ERROR_DIRECTORY
=
267
;
public
static
final
int
ERROR_NOTIFY_ENUM_DIR
=
1022
;
public
static
final
int
ERROR_NONE_MAPPED
=
1332
;
...
...
src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java
浏览文件 @
8f834f5c
...
...
@@ -973,19 +973,19 @@ class WindowsNativeDispatcher {
* HANDLE CreateIoCompletionPort (
* HANDLE FileHandle,
* HANDLE ExistingCompletionPort,
*
DWORD
CompletionKey,
*
ULONG_PTR
CompletionKey,
* DWORD NumberOfConcurrentThreads
* )
*/
static
native
long
CreateIoCompletionPort
(
long
fileHandle
,
long
existingPort
,
int
completionKey
)
throws
WindowsException
;
long
completionKey
)
throws
WindowsException
;
/**
* GetQueuedCompletionStatus(
* HANDLE CompletionPort,
* LPDWORD lpNumberOfBytesTransferred,
*
LPDWORD
lpCompletionKey,
*
PULONG_PTR
lpCompletionKey,
* LPOVERLAPPED *lpOverlapped,
* DWORD dwMilliseconds
*/
...
...
@@ -999,12 +999,12 @@ class WindowsNativeDispatcher {
static
class
CompletionStatus
{
private
int
error
;
private
int
bytesTransferred
;
private
int
completionKey
;
private
long
completionKey
;
private
CompletionStatus
()
{
}
int
error
()
{
return
error
;
}
int
bytesTransferred
()
{
return
bytesTransferred
;
}
int
completionKey
()
{
return
completionKey
;
}
long
completionKey
()
{
return
completionKey
;
}
}
private
static
native
void
GetQueuedCompletionStatus0
(
long
completionPort
,
CompletionStatus
status
)
throws
WindowsException
;
...
...
@@ -1013,12 +1013,12 @@ class WindowsNativeDispatcher {
* PostQueuedCompletionStatus(
* HANDLE CompletionPort,
* DWORD dwNumberOfBytesTransferred,
*
DWORD
dwCompletionKey,
*
ULONG_PTR
dwCompletionKey,
* LPOVERLAPPED lpOverlapped
* )
*/
static
native
void
PostQueuedCompletionStatus
(
long
completionPort
,
int
completionKey
)
throws
WindowsException
;
long
completionKey
)
throws
WindowsException
;
/**
* ReadDirectoryChangesW(
...
...
src/windows/classes/sun/nio/fs/WindowsWatchService.java
浏览文件 @
8f834f5c
...
...
@@ -41,6 +41,7 @@ import static sun.nio.fs.WindowsConstants.*;
class
WindowsWatchService
extends
AbstractWatchService
{
private
final
static
int
WAKEUP_COMPLETION_KEY
=
0
;
private
final
Unsafe
unsafe
=
Unsafe
.
getUnsafe
();
// background thread to service I/O completion port
...
...
@@ -83,7 +84,7 @@ class WindowsWatchService
*/
private
class
WindowsWatchKey
extends
AbstractWatchKey
{
// file key (used to detect existing registrations)
private
FileKey
fileKey
;
private
final
FileKey
fileKey
;
// handle to directory
private
volatile
long
handle
=
INVALID_HANDLE_VALUE
;
...
...
@@ -223,8 +224,7 @@ class WindowsWatchService
FileKey
other
=
(
FileKey
)
obj
;
if
(
this
.
volSerialNumber
!=
other
.
volSerialNumber
)
return
false
;
if
(
this
.
fileIndexHigh
!=
other
.
fileIndexHigh
)
return
false
;
if
(
this
.
fileIndexLow
!=
other
.
fileIndexLow
)
return
false
;
return
true
;
return
this
.
fileIndexLow
==
other
.
fileIndexLow
;
}
}
...
...
@@ -268,6 +268,7 @@ class WindowsWatchService
private
static
final
short
OFFSETOF_FILENAME
=
12
;
// size of per-directory buffer for events (FIXME - make this configurable)
// Need to be less than 4*16384 = 65536. DWORD align.
private
static
final
int
CHANGES_BUFFER_SIZE
=
16
*
1024
;
private
final
WindowsFileSystem
fs
;
...
...
@@ -275,27 +276,28 @@ class WindowsWatchService
private
final
long
port
;
// maps completion key to WatchKey
private
final
Map
<
Integer
,
WindowsWatchKey
>
int
2key
;
private
final
Map
<
Integer
,
WindowsWatchKey
>
ck
2key
;
// maps file key to WatchKey
private
final
Map
<
FileKey
,
WindowsWatchKey
>
fk2key
;
// unique completion key for each directory
// native completion key capacity is 64 bits on Win64.
private
int
lastCompletionKey
;
Poller
(
WindowsFileSystem
fs
,
WindowsWatchService
watcher
,
long
port
)
{
this
.
fs
=
fs
;
this
.
watcher
=
watcher
;
this
.
port
=
port
;
this
.
int2key
=
new
HashMap
<
Integer
,
WindowsWatchKey
>();
this
.
fk2key
=
new
HashMap
<
FileKey
,
WindowsWatchKey
>();
this
.
ck2key
=
new
HashMap
<
>();
this
.
fk2key
=
new
HashMap
<>();
this
.
lastCompletionKey
=
0
;
}
@Override
void
wakeup
()
throws
IOException
{
try
{
PostQueuedCompletionStatus
(
port
,
0
);
PostQueuedCompletionStatus
(
port
,
WAKEUP_COMPLETION_KEY
);
}
catch
(
WindowsException
x
)
{
throw
new
IOException
(
x
.
getMessage
());
}
...
...
@@ -322,7 +324,6 @@ class WindowsWatchService
for
(
WatchEvent
.
Modifier
modifier:
modifiers
)
{
if
(
modifier
==
ExtendedWatchEventModifier
.
FILE_TREE
)
{
watchSubtree
=
true
;
continue
;
}
else
{
if
(
modifier
==
null
)
return
new
NullPointerException
();
...
...
@@ -333,7 +334,7 @@ class WindowsWatchService
}
// open directory
long
handle
=
-
1L
;
long
handle
;
try
{
handle
=
CreateFile
(
dir
.
getPathForWin32Calls
(),
FILE_LIST_DIRECTORY
,
...
...
@@ -347,7 +348,7 @@ class WindowsWatchService
boolean
registered
=
false
;
try
{
// read attributes and check file is a directory
WindowsFileAttributes
attrs
=
null
;
WindowsFileAttributes
attrs
;
try
{
attrs
=
WindowsFileAttributes
.
readAttributes
(
handle
);
}
catch
(
WindowsException
x
)
{
...
...
@@ -370,9 +371,10 @@ class WindowsWatchService
return
existing
;
}
// unique completion key (skip 0)
// Can overflow the int type capacity.
// Skip WAKEUP_COMPLETION_KEY value.
int
completionKey
=
++
lastCompletionKey
;
if
(
completionKey
==
0
)
if
(
completionKey
==
WAKEUP_COMPLETION_KEY
)
completionKey
=
++
lastCompletionKey
;
// associate handle with completion port
...
...
@@ -418,13 +420,13 @@ class WindowsWatchService
// 1. remove mapping from old completion key to existing watch key
// 2. release existing key's resources (handle/buffer)
// 3. re-initialize key with new handle/buffer
int
2key
.
remove
(
existing
.
completionKey
());
ck
2key
.
remove
(
existing
.
completionKey
());
existing
.
releaseResources
();
watchKey
=
existing
.
init
(
handle
,
events
,
watchSubtree
,
buffer
,
countAddress
,
overlappedAddress
,
completionKey
);
}
// map completion map to watch key
int
2key
.
put
(
completionKey
,
watchKey
);
ck
2key
.
put
(
completionKey
,
watchKey
);
registered
=
true
;
return
watchKey
;
...
...
@@ -440,7 +442,7 @@ class WindowsWatchService
WindowsWatchKey
key
=
(
WindowsWatchKey
)
obj
;
if
(
key
.
isValid
())
{
fk2key
.
remove
(
key
.
fileKey
());
int
2key
.
remove
(
key
.
completionKey
());
ck
2key
.
remove
(
key
.
completionKey
());
key
.
invalidate
();
}
}
...
...
@@ -449,11 +451,11 @@ class WindowsWatchService
@Override
void
implCloseAll
()
{
// cancel all keys
for
(
Map
.
Entry
<
Integer
,
WindowsWatchKey
>
entry:
int
2key
.
entrySet
())
{
for
(
Map
.
Entry
<
Integer
,
WindowsWatchKey
>
entry:
ck
2key
.
entrySet
())
{
entry
.
getValue
().
invalidate
();
}
fk2key
.
clear
();
int
2key
.
clear
();
ck
2key
.
clear
();
// close I/O completion port
CloseHandle
(
port
);
...
...
@@ -517,7 +519,7 @@ class WindowsWatchService
@Override
public
void
run
()
{
for
(;;)
{
CompletionStatus
info
=
null
;
CompletionStatus
info
;
try
{
info
=
GetQueuedCompletionStatus
(
port
);
}
catch
(
WindowsException
x
)
{
...
...
@@ -527,7 +529,7 @@ class WindowsWatchService
}
// wakeup
if
(
info
.
completionKey
()
==
0
)
{
if
(
info
.
completionKey
()
==
WAKEUP_COMPLETION_KEY
)
{
boolean
shutdown
=
processRequests
();
if
(
shutdown
)
{
return
;
...
...
@@ -536,7 +538,7 @@ class WindowsWatchService
}
// map completionKey to get WatchKey
WindowsWatchKey
key
=
int2key
.
get
(
info
.
completionKey
());
WindowsWatchKey
key
=
ck2key
.
get
((
int
)
info
.
completionKey
());
if
(
key
==
null
)
{
// We get here when a registration is changed. In that case
// the directory is closed which causes an event with the
...
...
@@ -544,38 +546,44 @@ class WindowsWatchService
continue
;
}
// ReadDirectoryChangesW failed
if
(
info
.
error
()
!=
0
)
{
boolean
criticalError
=
false
;
int
errorCode
=
info
.
error
();
int
messageSize
=
info
.
bytesTransferred
();
if
(
errorCode
==
ERROR_NOTIFY_ENUM_DIR
)
{
// buffer overflow
if
(
info
.
error
()
==
ERROR_NOTIFY_ENUM_DIR
)
{
key
.
signalEvent
(
StandardWatchEventKinds
.
OVERFLOW
,
null
);
}
else
if
(
errorCode
!=
0
&&
errorCode
!=
ERROR_MORE_DATA
)
{
// ReadDirectoryChangesW failed
criticalError
=
true
;
}
else
{
// ERROR_MORE_DATA is a warning about incomplite
// data transfer over TCP/UDP stack. For the case
// [messageSize] is zero in the most of cases.
if
(
messageSize
>
0
)
{
// process non-empty events.
processEvents
(
key
,
messageSize
);
}
else
if
(
errorCode
==
0
)
{
// insufficient buffer size
// not described, but can happen.
key
.
signalEvent
(
StandardWatchEventKinds
.
OVERFLOW
,
null
);
}
else
{
// other error so cancel key
implCancelKey
(
key
);
key
.
signal
();
}
continue
;
}
// process the events
if
(
info
.
bytesTransferred
()
>
0
)
{
processEvents
(
key
,
info
.
bytesTransferred
());
}
else
{
// insufficient buffer size
key
.
signalEvent
(
StandardWatchEventKinds
.
OVERFLOW
,
null
);
// start read for next batch of changes
try
{
ReadDirectoryChangesW
(
key
.
handle
(),
key
.
buffer
().
address
(),
CHANGES_BUFFER_SIZE
,
key
.
watchSubtree
(),
ALL_FILE_NOTIFY_EVENTS
,
key
.
countAddress
(),
key
.
overlappedAddress
());
}
catch
(
WindowsException
x
)
{
// no choice but to cancel key
criticalError
=
true
;
}
}
// start read for next batch of changes
try
{
ReadDirectoryChangesW
(
key
.
handle
(),
key
.
buffer
().
address
(),
CHANGES_BUFFER_SIZE
,
key
.
watchSubtree
(),
ALL_FILE_NOTIFY_EVENTS
,
key
.
countAddress
(),
key
.
overlappedAddress
());
}
catch
(
WindowsException
x
)
{
// no choice but to cancel key
if
(
criticalError
)
{
implCancelKey
(
key
);
key
.
signal
();
}
...
...
src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c
浏览文件 @
8f834f5c
...
...
@@ -162,7 +162,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
}
completionStatus_error
=
(
*
env
)
->
GetFieldID
(
env
,
clazz
,
"error"
,
"I"
);
completionStatus_bytesTransferred
=
(
*
env
)
->
GetFieldID
(
env
,
clazz
,
"bytesTransferred"
,
"I"
);
completionStatus_completionKey
=
(
*
env
)
->
GetFieldID
(
env
,
clazz
,
"completionKey"
,
"
I
"
);
completionStatus_completionKey
=
(
*
env
)
->
GetFieldID
(
env
,
clazz
,
"completionKey"
,
"
J
"
);
clazz
=
(
*
env
)
->
FindClass
(
env
,
"sun/nio/fs/WindowsNativeDispatcher$BackupResult"
);
if
(
clazz
==
NULL
)
{
...
...
@@ -1169,12 +1169,11 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
JNIEXPORT
jlong
JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort
(
JNIEnv
*
env
,
jclass
this
,
jlong
fileHandle
,
jlong
existingPort
,
j
int
completionKey
)
jlong
fileHandle
,
jlong
existingPort
,
j
long
completionKey
)
{
ULONG_PTR
ck
=
completionKey
;
HANDLE
port
=
CreateIoCompletionPort
((
HANDLE
)
jlong_to_ptr
(
fileHandle
),
(
HANDLE
)
jlong_to_ptr
(
existingPort
),
ck
,
(
ULONG_PTR
)
completionKey
,
0
);
if
(
port
==
NULL
)
{
throwWindowsException
(
env
,
GetLastError
());
...
...
@@ -1203,21 +1202,20 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env,
(
*
env
)
->
SetIntField
(
env
,
obj
,
completionStatus_error
,
ioResult
);
(
*
env
)
->
SetIntField
(
env
,
obj
,
completionStatus_bytesTransferred
,
(
jint
)
bytesTransferred
);
(
*
env
)
->
SetIntField
(
env
,
obj
,
completionStatus_completionKey
,
(
jint
)
completionKey
);
(
*
env
)
->
SetLongField
(
env
,
obj
,
completionStatus_completionKey
,
(
jlong
)
completionKey
);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus
(
JNIEnv
*
env
,
jclass
this
,
jlong
completionPort
,
j
int
completionKey
)
jlong
completionPort
,
j
long
completionKey
)
{
BOOL
res
;
res
=
PostQueuedCompletionStatus
((
HANDLE
)
jlong_to_ptr
(
completionPort
),
(
DWORD
)
0
,
/* dwNumberOfBytesTransferred */
(
DWORD
)
completionKey
,
(
ULONG_PTR
)
completionKey
,
NULL
);
/* lpOverlapped */
if
(
res
==
0
)
{
throwWindowsException
(
env
,
GetLastError
());
...
...
@@ -1232,7 +1230,17 @@ Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclas
BOOL
res
;
BOOL
subtree
=
(
watchSubTree
==
JNI_TRUE
)
?
TRUE
:
FALSE
;
((
LPOVERLAPPED
)
jlong_to_ptr
(
pOverlapped
))
->
hEvent
=
NULL
;
/* Any unused members of [OVERLAPPED] structure should always be initialized to zero
before the structure is used in a function call.
Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx
The [Offset] and [OffsetHigh] members of this structure are not used.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
[hEvent] should be zero, other fields are the return values. */
ZeroMemory
((
LPOVERLAPPED
)
jlong_to_ptr
(
pOverlapped
),
sizeof
(
OVERLAPPED
));
res
=
ReadDirectoryChangesW
((
HANDLE
)
jlong_to_ptr
(
hDirectory
),
(
LPVOID
)
jlong_to_ptr
(
bufferAddress
),
(
DWORD
)
bufferLength
,
...
...
test/java/lang/ref/OOMEInReferenceHandler.java
0 → 100644
浏览文件 @
8f834f5c
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 7038914
* @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
* @run main/othervm -Xmx16M -XX:-UseTLAB OOMEInReferenceHandler
* @author peter.levart@gmail.com
*/
import
java.lang.ref.*
;
public
class
OOMEInReferenceHandler
{
static
Object
[]
fillHeap
()
{
Object
[]
first
=
null
,
last
=
null
;
int
size
=
1
<<
20
;
while
(
size
>
0
)
{
try
{
Object
[]
array
=
new
Object
[
size
];
if
(
first
==
null
)
{
first
=
array
;
}
else
{
last
[
0
]
=
array
;
}
last
=
array
;
}
catch
(
OutOfMemoryError
oome
)
{
size
=
size
>>>
1
;
}
}
return
first
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// preinitialize the InterruptedException class so that the reference handler
// does not die due to OOME when loading the class if it is the first use
InterruptedException
ie
=
new
InterruptedException
(
"dummy"
);
ThreadGroup
tg
=
Thread
.
currentThread
().
getThreadGroup
();
for
(
ThreadGroup
tgn
=
tg
;
tgn
!=
null
;
tg
=
tgn
,
tgn
=
tg
.
getParent
()
)
;
Thread
[]
threads
=
new
Thread
[
tg
.
activeCount
()];
Thread
referenceHandlerThread
=
null
;
int
n
=
tg
.
enumerate
(
threads
);
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
if
(
"Reference Handler"
.
equals
(
threads
[
i
].
getName
()))
{
referenceHandlerThread
=
threads
[
i
];
}
}
if
(
referenceHandlerThread
==
null
)
{
throw
new
IllegalStateException
(
"Couldn't find Reference Handler thread."
);
}
ReferenceQueue
<
Object
>
refQueue
=
new
ReferenceQueue
<>();
Object
referent
=
new
Object
();
WeakReference
<
Object
>
weakRef
=
new
WeakReference
<>(
referent
,
refQueue
);
Object
waste
=
fillHeap
();
referenceHandlerThread
.
interrupt
();
// allow referenceHandlerThread some time to throw OOME
Thread
.
sleep
(
500L
);
// release waste & referent
waste
=
null
;
referent
=
null
;
// wait at most 10 seconds for success or failure
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
if
(
refQueue
.
poll
()
!=
null
)
{
// Reference Handler thread still working -> success
return
;
}
System
.
gc
();
Thread
.
sleep
(
500L
);
// wait a little to allow GC to do it's work before allocating objects
if
(!
referenceHandlerThread
.
isAlive
())
{
// Reference Handler thread died -> failure
throw
new
Exception
(
"Reference Handler thread died."
);
}
}
// no sure answer after 10 seconds
throw
new
IllegalStateException
(
"Reference Handler thread stuck."
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录