Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
5606a2cd
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看板
提交
5606a2cd
编写于
10月 07, 2014
作者:
J
jcoomes
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
c0d03e3d
975a1af4
变更
87
显示空白变更内容
内联
并排
Showing
87 changed file
with
5262 addition
and
2238 deletion
+5262
-2238
make/data/jdwp/jdwp.spec
make/data/jdwp/jdwp.spec
+83
-3
src/share/back/InterfaceTypeImpl.c
src/share/back/InterfaceTypeImpl.c
+39
-0
src/share/back/InterfaceTypeImpl.h
src/share/back/InterfaceTypeImpl.h
+25
-0
src/share/back/VirtualMachineImpl.c
src/share/back/VirtualMachineImpl.c
+1
-1
src/share/back/debugDispatch.c
src/share/back/debugDispatch.c
+2
-0
src/share/back/util.c
src/share/back/util.c
+2
-0
src/share/classes/com/sun/jarsigner/ContentSigner.java
src/share/classes/com/sun/jarsigner/ContentSigner.java
+1
-0
src/share/classes/com/sun/jarsigner/package-info.java
src/share/classes/com/sun/jarsigner/package-info.java
+35
-0
src/share/classes/com/sun/jarsigner/package.html
src/share/classes/com/sun/jarsigner/package.html
+0
-38
src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java
...classes/com/sun/java/util/jar/pack/DriverResource_ja.java
+2
-2
src/share/classes/com/sun/jdi/ClassType.java
src/share/classes/com/sun/jdi/ClassType.java
+6
-6
src/share/classes/com/sun/jdi/InterfaceType.java
src/share/classes/com/sun/jdi/InterfaceType.java
+119
-0
src/share/classes/com/sun/jdi/Method.java
src/share/classes/com/sun/jdi/Method.java
+12
-0
src/share/classes/com/sun/jdi/ObjectReference.java
src/share/classes/com/sun/jdi/ObjectReference.java
+6
-6
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties
...n/swing/internal/plaf/basic/resources/basic_ja.properties
+3
-3
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties
...n/swing/internal/plaf/basic/resources/basic_ko.properties
+3
-3
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties
...wing/internal/plaf/basic/resources/basic_zh_CN.properties
+3
-3
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties
...wing/internal/plaf/basic/resources/basic_zh_TW.properties
+3
-3
src/share/classes/com/sun/tools/example/debug/expr/LValue.java
...hare/classes/com/sun/tools/example/debug/expr/LValue.java
+3
-0
src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java
src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java
+3
-1
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
+45
-177
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
+51
-90
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
+305
-0
src/share/classes/com/sun/tools/jdi/MethodImpl.java
src/share/classes/com/sun/tools/jdi/MethodImpl.java
+7
-0
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
+30
-6
src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
+2
-2
src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
.../classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
+1
-1
src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
...re/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+2
-2
src/share/classes/java/net/URLClassLoader.java
src/share/classes/java/net/URLClassLoader.java
+8
-3
src/share/classes/java/security/KeyPairGenerator.java
src/share/classes/java/security/KeyPairGenerator.java
+18
-1
src/share/classes/java/security/KeyStore.java
src/share/classes/java/security/KeyStore.java
+12
-0
src/share/classes/java/security/MessageDigest.java
src/share/classes/java/security/MessageDigest.java
+19
-7
src/share/classes/java/security/SecureRandom.java
src/share/classes/java/security/SecureRandom.java
+11
-0
src/share/classes/java/security/Signature.java
src/share/classes/java/security/Signature.java
+26
-1
src/share/classes/java/util/concurrent/ForkJoinPool.java
src/share/classes/java/util/concurrent/ForkJoinPool.java
+1478
-1374
src/share/classes/java/util/concurrent/ForkJoinTask.java
src/share/classes/java/util/concurrent/ForkJoinTask.java
+83
-104
src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
...re/classes/java/util/concurrent/ForkJoinWorkerThread.java
+5
-6
src/share/classes/java/util/logging/FileHandler.java
src/share/classes/java/util/logging/FileHandler.java
+9
-1
src/share/classes/javax/crypto/Cipher.java
src/share/classes/javax/crypto/Cipher.java
+45
-1
src/share/classes/javax/crypto/KeyAgreement.java
src/share/classes/javax/crypto/KeyAgreement.java
+16
-1
src/share/classes/javax/crypto/KeyGenerator.java
src/share/classes/javax/crypto/KeyGenerator.java
+17
-1
src/share/classes/javax/crypto/Mac.java
src/share/classes/javax/crypto/Mac.java
+16
-1
src/share/classes/sun/awt/datatransfer/DataTransferer.java
src/share/classes/sun/awt/datatransfer/DataTransferer.java
+8
-0
src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
...share/classes/sun/security/jgss/spnego/SpNegoContext.java
+34
-11
src/share/classes/sun/security/tools/keytool/Resources.java
src/share/classes/sun/security/tools/keytool/Resources.java
+1
-1
src/share/classes/sun/security/tools/keytool/Resources_de.java
...hare/classes/sun/security/tools/keytool/Resources_de.java
+1
-1
src/share/classes/sun/security/tools/keytool/Resources_es.java
...hare/classes/sun/security/tools/keytool/Resources_es.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_fr.java
...hare/classes/sun/security/tools/keytool/Resources_fr.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_it.java
...hare/classes/sun/security/tools/keytool/Resources_it.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_ja.java
...hare/classes/sun/security/tools/keytool/Resources_ja.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_ko.java
...hare/classes/sun/security/tools/keytool/Resources_ko.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_pt_BR.java
...e/classes/sun/security/tools/keytool/Resources_pt_BR.java
+1
-1
src/share/classes/sun/security/tools/keytool/Resources_sv.java
...hare/classes/sun/security/tools/keytool/Resources_sv.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_zh_CN.java
...e/classes/sun/security/tools/keytool/Resources_zh_CN.java
+2
-2
src/share/classes/sun/security/tools/keytool/Resources_zh_TW.java
...e/classes/sun/security/tools/keytool/Resources_zh_TW.java
+2
-2
src/share/classes/sun/security/util/Debug.java
src/share/classes/sun/security/util/Debug.java
+10
-2
src/share/classes/sun/text/resources/FormatData.java
src/share/classes/sun/text/resources/FormatData.java
+13
-13
src/share/classes/sun/text/resources/en/FormatData_en.java
src/share/classes/sun/text/resources/en/FormatData_en.java
+18
-1
src/share/classes/sun/tools/jconsole/resources/messages_ja.properties
...asses/sun/tools/jconsole/resources/messages_ja.properties
+1
-1
src/share/native/sun/security/ec/ECC_JNI.cpp
src/share/native/sun/security/ec/ECC_JNI.cpp
+39
-6
src/solaris/classes/sun/awt/X11/XRootWindow.java
src/solaris/classes/sun/awt/X11/XRootWindow.java
+3
-2
src/solaris/classes/sun/awt/X11/XToolkit.java
src/solaris/classes/sun/awt/X11/XToolkit.java
+14
-47
src/solaris/native/sun/awt/awt_util.h
src/solaris/native/sun/awt/awt_util.h
+2
-0
src/solaris/native/sun/xawt/XlibWrapper.c
src/solaris/native/sun/xawt/XlibWrapper.c
+12
-5
src/windows/native/sun/java2d/windows/GDIRenderer.cpp
src/windows/native/sun/java2d/windows/GDIRenderer.cpp
+1
-1
src/windows/native/sun/security/mscapi/security.cpp
src/windows/native/sun/security/mscapi/security.cpp
+96
-33
src/windows/native/sun/windows/awt_Component.cpp
src/windows/native/sun/windows/awt_Component.cpp
+0
-1
src/windows/native/sun/windows/awt_TextArea.cpp
src/windows/native/sun/windows/awt_TextArea.cpp
+1
-213
src/windows/native/sun/windows/awt_TextArea.h
src/windows/native/sun/windows/awt_TextArea.h
+0
-21
src/windows/native/sun/windows/awt_TextComponent.cpp
src/windows/native/sun/windows/awt_TextComponent.cpp
+203
-1
src/windows/native/sun/windows/awt_TextComponent.h
src/windows/native/sun/windows/awt_TextComponent.h
+24
-0
src/windows/native/sun/windows/awt_TextField.cpp
src/windows/native/sun/windows/awt_TextField.cpp
+1
-7
test/com/sun/jdi/EvalInterfaceStatic.sh
test/com/sun/jdi/EvalInterfaceStatic.sh
+126
-0
test/com/sun/jdi/InterfaceMethodsTest.java
test/com/sun/jdi/InterfaceMethodsTest.java
+422
-0
test/com/sun/jdi/VisibleMethods.java
test/com/sun/jdi/VisibleMethods.java
+141
-0
test/java/awt/Focus/SortingFPT/JDK8048887.java
test/java/awt/Focus/SortingFPT/JDK8048887.java
+1
-1
test/java/net/InetAddress/IPv4Formats.java
test/java/net/InetAddress/IPv4Formats.java
+2
-1
test/java/util/logging/FileHandlerPath.java
test/java/util/logging/FileHandlerPath.java
+315
-0
test/javax/xml/ws/xsanymixed/CopyingResponse.java
test/javax/xml/ws/xsanymixed/CopyingResponse.java
+35
-0
test/javax/xml/ws/xsanymixed/ServiceImpl.java
test/javax/xml/ws/xsanymixed/ServiceImpl.java
+51
-0
test/javax/xml/ws/xsanymixed/Test.java
test/javax/xml/ws/xsanymixed/Test.java
+197
-0
test/javax/xml/ws/xsanymixed/compile-wsdl.sh
test/javax/xml/ws/xsanymixed/compile-wsdl.sh
+36
-0
test/javax/xml/ws/xsanymixed/service.wsdl
test/javax/xml/ws/xsanymixed/service.wsdl
+87
-0
test/sun/awt/datatransfer/DataFlavorComparatorTest1.java
test/sun/awt/datatransfer/DataFlavorComparatorTest1.java
+115
-0
test/sun/security/jgss/spnego/NotPreferredMech.java
test/sun/security/jgss/spnego/NotPreferredMech.java
+100
-0
test/sun/text/resources/LocaleData
test/sun/text/resources/LocaleData
+577
-3
test/sun/text/resources/LocaleDataTest.java
test/sun/text/resources/LocaleDataTest.java
+1
-1
未找到文件。
make/data/jdwp/jdwp.spec
浏览文件 @
5606a2cd
...
@@ -1147,7 +1147,8 @@ JDWP "Java(tm) Debug Wire Protocol"
...
@@ -1147,7 +1147,8 @@ JDWP "Java(tm) Debug Wire Protocol"
(ErrorSet
(ErrorSet
(Error INVALID_CLASS "clazz is not the ID of a class.")
(Error INVALID_CLASS "clazz is not the ID of a class.")
(Error INVALID_OBJECT "clazz is not a known ID.")
(Error INVALID_OBJECT "clazz is not a known ID.")
(Error INVALID_METHODID "methodID is not the ID of a method.")
(Error INVALID_METHODID "methodID is not the ID of a static method in "
"this class type or one of its superclasses.")
(Error INVALID_THREAD)
(Error INVALID_THREAD)
(Error THREAD_NOT_SUSPENDED)
(Error THREAD_NOT_SUSPENDED)
(Error VM_DEAD)
(Error VM_DEAD)
...
@@ -1250,6 +1251,83 @@ JDWP "Java(tm) Debug Wire Protocol"
...
@@ -1250,6 +1251,83 @@ JDWP "Java(tm) Debug Wire Protocol"
)
)
)
)
(CommandSet InterfaceType=5
(CommandSet InterfaceType=5
(Command InvokeMethod=1
"Invokes a static method. "
"The method must not be a static initializer. "
"The method must be a member of the interface type. "
"<p>Since JDWP version 1.8 "
"<p>"
"The method invocation will occur in the specified thread. "
"Method invocation can occur only if the specified thread "
"has been suspended by an event. "
"Method invocation is not supported "
"when the target VM has been suspended by the front-end. "
"<p>"
"The specified method is invoked with the arguments in the specified "
"argument list. "
"The method invocation is synchronous; the reply packet is not "
"sent until the invoked method returns in the target VM. "
"The return value (possibly the void value) is "
"included in the reply packet. "
"If the invoked method throws an exception, the "
"exception object ID is set in the reply packet; otherwise, the "
"exception object ID is null. "
"<p>"
"For primitive arguments, the argument value's type must match the "
"argument's type exactly. For object arguments, there must exist a "
"widening reference conversion from the argument value's type to the "
"argument's type and the argument's type must be loaded. "
"<p>"
"By default, all threads in the target VM are resumed while "
"the method is being invoked if they were previously "
"suspended by an event or by a command. "
"This is done to prevent the deadlocks "
"that will occur if any of the threads own monitors "
"that will be needed by the invoked method. It is possible that "
"breakpoints or other events might occur during the invocation. "
"Note, however, that this implicit resume acts exactly like "
"the ThreadReference resume command, so if the thread's suspend "
"count is greater than 1, it will remain in a suspended state "
"during the invocation. By default, when the invocation completes, "
"all threads in the target VM are suspended, regardless their state "
"before the invocation. "
"<p>"
"The resumption of other threads during the invoke can be prevented "
"by specifying the INVOKE_SINGLE_THREADED "
"bit flag in the <code>options</code> field; however, "
"there is no protection against or recovery from the deadlocks "
"described above, so this option should be used with great caution. "
"Only the specified thread will be resumed (as described for all "
"threads above). Upon completion of a single threaded invoke, the invoking thread "
"will be suspended once again. Note that any threads started during "
"the single threaded invocation will not be suspended when the "
"invocation completes. "
"<p>"
"If the target VM is disconnected during the invoke (for example, through "
"the VirtualMachine dispose command) the method invocation continues. "
(Out
(interfaceType clazz "The interface type ID.")
(threadObject thread "The thread in which to invoke.")
(method methodID "The method to invoke.")
(Repeat arguments
(value arg "The argument value.")
)
(int options "Invocation <a href=\"#JDWP_InvokeOptions\">options</a>")
)
(Reply
(value returnValue "The returned value.")
(tagged-object exception "The thrown exception.")
)
(ErrorSet
(Error INVALID_CLASS "clazz is not the ID of an interface.")
(Error INVALID_OBJECT "clazz is not a known ID.")
(Error INVALID_METHODID "methodID is not the ID of a static method in this "
"interface type or is the ID of a static initializer.")
(Error INVALID_THREAD)
(Error THREAD_NOT_SUSPENDED)
(Error VM_DEAD)
)
)
)
)
(CommandSet Method=6
(CommandSet Method=6
(Command LineTable=1
(Command LineTable=1
...
@@ -1543,7 +1621,7 @@ JDWP "Java(tm) Debug Wire Protocol"
...
@@ -1543,7 +1621,7 @@ JDWP "Java(tm) Debug Wire Protocol"
"<p>"
"<p>"
"By default, all threads in the target VM are resumed while "
"By default, all threads in the target VM are resumed while "
"the method is being invoked if they were previously "
"the method is being invoked if they were previously "
"suspended by an event or by command. "
"suspended by an event or by
a
command. "
"This is done to prevent the deadlocks "
"This is done to prevent the deadlocks "
"that will occur if any of the threads own monitors "
"that will occur if any of the threads own monitors "
"that will be needed by the invoked method. It is possible that "
"that will be needed by the invoked method. It is possible that "
...
@@ -1586,7 +1664,9 @@ JDWP "Java(tm) Debug Wire Protocol"
...
@@ -1586,7 +1664,9 @@ JDWP "Java(tm) Debug Wire Protocol"
(Error INVALID_OBJECT)
(Error INVALID_OBJECT)
(Error INVALID_CLASS "clazz is not the ID of a reference "
(Error INVALID_CLASS "clazz is not the ID of a reference "
"type.")
"type.")
(Error INVALID_METHODID "methodID is not the ID of a method.")
(Error INVALID_METHODID "methodID is not the ID of an instance method "
"in this object's type or one of its superclasses, "
"superinterfaces, or implemented interfaces.")
(Error INVALID_THREAD)
(Error INVALID_THREAD)
(Error THREAD_NOT_SUSPENDED)
(Error THREAD_NOT_SUSPENDED)
(Error VM_DEAD)
(Error VM_DEAD)
...
...
src/share/back/InterfaceTypeImpl.c
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "util.h"
#include "InterfaceTypeImpl.h"
#include "inStream.h"
#include "outStream.h"
static
jboolean
invokeStatic
(
PacketInputStream
*
in
,
PacketOutputStream
*
out
)
{
return
sharedInvoke
(
in
,
out
);
}
void
*
InterfaceType_Cmds
[]
=
{
(
void
*
)
0x1
,
(
void
*
)
invokeStatic
};
src/share/back/InterfaceTypeImpl.h
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
extern
void
*
InterfaceType_Cmds
[];
src/share/back/VirtualMachineImpl.c
浏览文件 @
5606a2cd
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
static
char
*
versionName
=
"Java Debug Wire Protocol (Reference Implementation)"
;
static
char
*
versionName
=
"Java Debug Wire Protocol (Reference Implementation)"
;
static
int
majorVersion
=
1
;
/* JDWP major version */
static
int
majorVersion
=
1
;
/* JDWP major version */
static
int
minorVersion
=
6
;
/* JDWP minor version */
static
int
minorVersion
=
8
;
/* JDWP minor version */
static
jboolean
static
jboolean
version
(
PacketInputStream
*
in
,
PacketOutputStream
*
out
)
version
(
PacketInputStream
*
in
,
PacketOutputStream
*
out
)
...
...
src/share/back/debugDispatch.c
浏览文件 @
5606a2cd
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
#include "VirtualMachineImpl.h"
#include "VirtualMachineImpl.h"
#include "ReferenceTypeImpl.h"
#include "ReferenceTypeImpl.h"
#include "ClassTypeImpl.h"
#include "ClassTypeImpl.h"
#include "InterfaceTypeImpl.h"
#include "ArrayTypeImpl.h"
#include "ArrayTypeImpl.h"
#include "FieldImpl.h"
#include "FieldImpl.h"
#include "MethodImpl.h"
#include "MethodImpl.h"
...
@@ -67,6 +68,7 @@ debugDispatch_initialize(void)
...
@@ -67,6 +68,7 @@ debugDispatch_initialize(void)
l1Array
[
JDWP_COMMAND_SET
(
VirtualMachine
)]
=
(
void
*
)
VirtualMachine_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
VirtualMachine
)]
=
(
void
*
)
VirtualMachine_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ReferenceType
)]
=
(
void
*
)
ReferenceType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ReferenceType
)]
=
(
void
*
)
ReferenceType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ClassType
)]
=
(
void
*
)
ClassType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ClassType
)]
=
(
void
*
)
ClassType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
InterfaceType
)]
=
(
void
*
)
InterfaceType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ArrayType
)]
=
(
void
*
)
ArrayType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
ArrayType
)]
=
(
void
*
)
ArrayType_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
Field
)]
=
(
void
*
)
Field_Cmds
;
l1Array
[
JDWP_COMMAND_SET
(
Field
)]
=
(
void
*
)
Field_Cmds
;
...
...
src/share/back/util.c
浏览文件 @
5606a2cd
...
@@ -591,6 +591,8 @@ sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
...
@@ -591,6 +591,8 @@ sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
invokeType
=
INVOKE_CONSTRUCTOR
;
invokeType
=
INVOKE_CONSTRUCTOR
;
}
else
if
(
inStream_command
(
in
)
==
JDWP_COMMAND
(
ClassType
,
InvokeMethod
))
{
}
else
if
(
inStream_command
(
in
)
==
JDWP_COMMAND
(
ClassType
,
InvokeMethod
))
{
invokeType
=
INVOKE_STATIC
;
invokeType
=
INVOKE_STATIC
;
}
else
if
(
inStream_command
(
in
)
==
JDWP_COMMAND
(
InterfaceType
,
InvokeMethod
))
{
invokeType
=
INVOKE_STATIC
;
}
else
if
(
inStream_command
(
in
)
==
JDWP_COMMAND
(
ObjectReference
,
InvokeMethod
))
{
}
else
if
(
inStream_command
(
in
)
==
JDWP_COMMAND
(
ObjectReference
,
InvokeMethod
))
{
invokeType
=
INVOKE_INSTANCE
;
invokeType
=
INVOKE_INSTANCE
;
}
else
{
}
else
{
...
...
src/share/classes/com/sun/jarsigner/ContentSigner.java
浏览文件 @
5606a2cd
...
@@ -37,6 +37,7 @@ import java.security.cert.CertificateException;
...
@@ -37,6 +37,7 @@ import java.security.cert.CertificateException;
* @author Vincent Ryan
* @author Vincent Ryan
*/
*/
@jdk
.
Exported
public
abstract
class
ContentSigner
{
public
abstract
class
ContentSigner
{
/**
/**
...
...
src/share/classes/com/sun/jarsigner/package-info.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This package comprises the interfaces and classes used to define the
* signing mechanism used by the <tt>jarsigner</tt> tool.
* <p>
* Clients may override the default signing mechanism of the <tt>jarsigner</tt>
* tool by supplying an alternative implementation of
* {@link com.sun.jarsigner.ContentSigner}.
*/
@jdk
.
Exported
package
com.sun.jarsigner
;
src/share/classes/com/sun/jarsigner/package.html
已删除
100644 → 0
浏览文件 @
c0d03e3d
<html>
<!--
Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
-->
<head>
<title>
Jarsigner Signing Mechanism Package
</title>
</head>
<body>
This package comprises the interfaces and classes used to define the
signing mechanism used by the
<tt>
jarsigner
</tt>
tool.
<p>
Clients may override the default signing mechanism of the
<tt>
jarsigner
</tt>
tool by supplying an alternative implementation of
{@link com.sun.jarsigner.ContentSigner}.
</body>
</html>
src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2005, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -84,7 +84,7 @@ public class DriverResource_ja extends ListResourceBundle {
...
@@ -84,7 +84,7 @@ public class DriverResource_ja extends ListResourceBundle {
" -V\u3001--version \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059"
,
" -V\u3001--version \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059"
,
" -J{X} \u30AA\u30D7\u30B7\u30E7\u30F3X\u3092\u57FA\u790E\u3068\u306A\u308BJava VM\u306B\u6E21\u3057\u307E\u3059"
,
" -J{X} \u30AA\u30D7\u30B7\u30E7\u30F3X\u3092\u57FA\u790E\u3068\u306A\u308BJava VM\u306B\u6E21\u3057\u307E\u3059"
,
""
,
""
,
"\u6CE8
\u610F
:"
,
"\u6CE8:"
,
" -P\u3001-C\u3001-F\u3001-M\u304A\u3088\u3073-D\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u7D2F\u7A4D\u3055\u308C\u307E\u3059\u3002"
,
" -P\u3001-C\u3001-F\u3001-M\u304A\u3088\u3073-D\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u7D2F\u7A4D\u3055\u308C\u307E\u3059\u3002"
,
" \u5C5E\u6027\u5B9A\u7FA9\u306E\u4F8B: -C SourceFile=RUH ."
,
" \u5C5E\u6027\u5B9A\u7FA9\u306E\u4F8B: -C SourceFile=RUH ."
,
" Config.\u30D5\u30A1\u30A4\u30EB\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306F\u3001Pack200 API\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002"
,
" Config.\u30D5\u30A1\u30A4\u30EB\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306F\u3001Pack200 API\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002"
,
...
...
src/share/classes/com/sun/jdi/ClassType.java
浏览文件 @
5606a2cd
...
@@ -103,7 +103,7 @@ public interface ClassType extends ReferenceType {
...
@@ -103,7 +103,7 @@ public interface ClassType extends ReferenceType {
* <p>
* <p>
* Object values must be assignment compatible with the field type
* Object values must be assignment compatible with the field type
* (This implies that the field type must be loaded through the
* (This implies that the field type must be loaded through the
* enclosing class'
s
class loader). Primitive values must be
* enclosing class' class loader). Primitive values must be
* either assignment compatible with the field type or must be
* either assignment compatible with the field type or must be
* convertible to the field type without loss of information.
* convertible to the field type without loss of information.
* See JLS section 5.2 for more information on assignment
* See JLS section 5.2 for more information on assignment
...
@@ -153,7 +153,7 @@ public interface ClassType extends ReferenceType {
...
@@ -153,7 +153,7 @@ public interface ClassType extends ReferenceType {
* <p>
* <p>
* Object arguments must be assignment compatible with the argument type
* Object arguments must be assignment compatible with the argument type
* (This implies that the argument type must be loaded through the
* (This implies that the argument type must be loaded through the
* enclosing class'
s
class loader). Primitive arguments must be
* enclosing class' class loader). Primitive arguments must be
* either assignment compatible with the argument type or must be
* either assignment compatible with the argument type or must be
* convertible to the argument type without loss of information.
* convertible to the argument type without loss of information.
* If the method being called accepts a variable number of arguments,
* If the method being called accepts a variable number of arguments,
...
@@ -216,7 +216,7 @@ public interface ClassType extends ReferenceType {
...
@@ -216,7 +216,7 @@ public interface ClassType extends ReferenceType {
* @return a {@link Value} mirror of the invoked method's return value.
* @return a {@link Value} mirror of the invoked method's return value.
* @throws java.lang.IllegalArgumentException if the method is not
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this class or a superclass, if the size of the argument list
* a member of this class or a superclass, if the size of the argument list
* does not match the number of declared argu
em
nts for the method, or
* does not match the number of declared argu
me
nts for the method, or
* if the method is an initializer, constructor or static intializer.
* if the method is an initializer, constructor or static intializer.
* @throws {@link InvalidTypeException} if any argument in the
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* argument list is not assignable to the corresponding method argument
...
@@ -230,7 +230,7 @@ public interface ClassType extends ReferenceType {
...
@@ -230,7 +230,7 @@ public interface ClassType extends ReferenceType {
* @throws InvalidTypeException If the arguments do not meet this requirement --
* @throws InvalidTypeException If the arguments do not meet this requirement --
* Object arguments must be assignment compatible with the argument
* Object arguments must be assignment compatible with the argument
* type. This implies that the argument type must be
* type. This implies that the argument type must be
* loaded through the enclosing class'
s
class loader.
* loaded through the enclosing class' class loader.
* Primitive arguments must be either assignment compatible with the
* Primitive arguments must be either assignment compatible with the
* argument type or must be convertible to the argument type without loss
* argument type or must be convertible to the argument type without loss
* of information. See JLS section 5.2 for more information on assignment
* of information. See JLS section 5.2 for more information on assignment
...
@@ -267,7 +267,7 @@ public interface ClassType extends ReferenceType {
...
@@ -267,7 +267,7 @@ public interface ClassType extends ReferenceType {
* <p>
* <p>
* Object arguments must be assignment compatible with the argument type
* Object arguments must be assignment compatible with the argument type
* (This implies that the argument type must be loaded through the
* (This implies that the argument type must be loaded through the
* enclosing class'
s
class loader). Primitive arguments must be
* enclosing class' class loader). Primitive arguments must be
* either assignment compatible with the argument type or must be
* either assignment compatible with the argument type or must be
* convertible to the argument type without loss of information.
* convertible to the argument type without loss of information.
* If the method being called accepts a variable number of arguments,
* If the method being called accepts a variable number of arguments,
...
@@ -335,7 +335,7 @@ public interface ClassType extends ReferenceType {
...
@@ -335,7 +335,7 @@ public interface ClassType extends ReferenceType {
* @throws InvalidTypeException If the arguments do not meet this requirement --
* @throws InvalidTypeException If the arguments do not meet this requirement --
* Object arguments must be assignment compatible with the argument
* Object arguments must be assignment compatible with the argument
* type. This implies that the argument type must be
* type. This implies that the argument type must be
* loaded through the enclosing class'
s
class loader.
* loaded through the enclosing class' class loader.
* Primitive arguments must be either assignment compatible with the
* Primitive arguments must be either assignment compatible with the
* argument type or must be convertible to the argument type without loss
* argument type or must be convertible to the argument type without loss
* of information. See JLS section 5.2 for more information on assignment
* of information. See JLS section 5.2 for more information on assignment
...
...
src/share/classes/com/sun/jdi/InterfaceType.java
浏览文件 @
5606a2cd
...
@@ -79,4 +79,123 @@ public interface InterfaceType extends ReferenceType {
...
@@ -79,4 +79,123 @@ public interface InterfaceType extends ReferenceType {
* If none exist, returns a zero length List.
* If none exist, returns a zero length List.
*/
*/
List
<
ClassType
>
implementors
();
List
<
ClassType
>
implementors
();
/**
* Invokes the specified static {@link Method} in the
* target VM. The
* specified method must be defined in this interface.
* The method must be a static method
* but not a static initializer.
* <p>
* The method invocation will occur in the specified thread.
* Method invocation can occur only if the specified thread
* has been suspended by an event which occurred in that thread.
* Method invocation is not supported
* when the target VM has been suspended through
* {@link VirtualMachine#suspend} or when the specified thread
* is suspended through {@link ThreadReference#suspend}.
* <p>
* The specified method is invoked with the arguments in the specified
* argument list. The method invocation is synchronous; this method
* does not return until the invoked method returns in the target VM.
* If the invoked method throws an exception, this method will throw
* an {@link InvocationException} which contains a mirror to the exception
* object thrown.
* <p>
* Object arguments must be assignment compatible with the argument type
* (This implies that the argument type must be loaded through the
* enclosing class' class loader). Primitive arguments must be
* either assignment compatible with the argument type or must be
* convertible to the argument type without loss of information.
* If the method being called accepts a variable number of arguments,
* then the last argument type is an array of some component type.
* The argument in the matching position can be omitted, or can be null,
* an array of the same component type, or an argument of the
* component type followed by any number of other arguments of the same
* type. If the argument is omitted, then a 0 length array of the
* component type is passed. The component type can be a primitive type.
* Autoboxing is not supported.
*
* See Section 5.2 of
* <cite>The Java™ Language Specification</cite>
* for more information on assignment compatibility.
* <p>
* By default, all threads in the target VM are resumed while
* the method is being invoked if they were previously
* suspended by an event or by {@link VirtualMachine#suspend} or
* {@link ThreadReference#suspend}. This is done to prevent the deadlocks
* that will occur if any of the threads own monitors
* that will be needed by the invoked method.
* Note, however, that this implicit resume acts exactly like
* {@link ThreadReference#resume}, so if the thread's suspend
* count is greater than 1, it will remain in a suspended state
* during the invocation and thus a deadlock could still occur.
* By default, when the invocation completes,
* all threads in the target VM are suspended, regardless their state
* before the invocation.
* It is possible that
* breakpoints or other events might occur during the invocation.
* This can cause deadlocks as described above. It can also cause a deadlock
* if invokeMethod is called from the client's event handler thread. In this
* case, this thread will be waiting for the invokeMethod to complete and
* won't read the EventSet that comes in for the new event. If this
* new EventSet is SUSPEND_ALL, then a deadlock will occur because no
* one will resume the EventSet. To avoid this, all EventRequests should
* be disabled before doing the invokeMethod, or the invokeMethod should
* not be done from the client's event handler thread.
* <p>
* The resumption of other threads during the invocation can be prevented
* by specifying the {@link #INVOKE_SINGLE_THREADED}
* bit flag in the <code>options</code> argument; however,
* there is no protection against or recovery from the deadlocks
* described above, so this option should be used with great caution.
* Only the specified thread will be resumed (as described for all
* threads above). Upon completion of a single threaded invoke, the invoking thread
* will be suspended once again. Note that any threads started during
* the single threaded invocation will not be suspended when the
* invocation completes.
* <p>
* If the target VM is disconnected during the invoke (for example, through
* {@link VirtualMachine#dispose}) the method invocation continues.
*
* @param thread the thread in which to invoke.
* @param method the {@link Method} to invoke.
* @param arguments the list of {@link Value} arguments bound to the
* invoked method. Values from the list are assigned to arguments
* in the order they appear in the method signature.
* @param options the integer bit flag options.
* @return a {@link Value} mirror of the invoked method's return value.
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this interface, if the size of the argument list
* does not match the number of declared arguments for the method, or
* if the method is not static or is a static initializer.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
* been suspended by an event.
* @throws InvocationException if the method invocation resulted in
* an exception in the target VM.
* @throws InvalidTypeException If the arguments do not meet this requirement --
* Object arguments must be assignment compatible with the argument
* type. This implies that the argument type must be
* loaded through the enclosing class' class loader.
* Primitive arguments must be either assignment compatible with the
* argument type or must be convertible to the argument type without loss
* of information. See JLS section 5.2 for more information on assignment
* compatibility.
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}.
*
* @since 1.8
*/
default
Value
invokeMethod
(
ThreadReference
thread
,
Method
method
,
List
<?
extends
Value
>
arguments
,
int
options
)
throws
InvalidTypeException
,
ClassNotLoadedException
,
IncompatibleThreadStateException
,
InvocationException
{
throw
new
UnsupportedOperationException
();
}
}
}
src/share/classes/com/sun/jdi/Method.java
浏览文件 @
5606a2cd
...
@@ -137,6 +137,18 @@ public interface Method extends TypeComponent, Locatable, Comparable<Method> {
...
@@ -137,6 +137,18 @@ public interface Method extends TypeComponent, Locatable, Comparable<Method> {
*/
*/
boolean
isAbstract
();
boolean
isAbstract
();
/**
* Determine if this method is a default method
*
* @return <code>true</code> if the method is declared default;
* false otherwise
*
* @since 1.8
*/
default
boolean
isDefault
()
{
throw
new
UnsupportedOperationException
();
}
/**
/**
* Determine if this method is synchronized.
* Determine if this method is synchronized.
*
*
...
...
src/share/classes/com/sun/jdi/ObjectReference.java
浏览文件 @
5606a2cd
...
@@ -194,10 +194,10 @@ public interface ObjectReference extends Value {
...
@@ -194,10 +194,10 @@ public interface ObjectReference extends Value {
* {@link #INVOKE_NONVIRTUAL} bit flag in the <code>options</code>
* {@link #INVOKE_NONVIRTUAL} bit flag in the <code>options</code>
* argument. If this flag is set, the specified method is invoked
* argument. If this flag is set, the specified method is invoked
* whether or not it is overridden for this object's runtime type.
* whether or not it is overridden for this object's runtime type.
* The method, in this case, must
not belong to an interface and
* The method, in this case, must
have an implementation, either in a class
*
must not be abstract. This option is useful for performing method
*
or an interface. This option is useful for performing method invocations
*
invocations like those done with the <code>super</code> keyword in
*
like those done with the <code>super</code> keyword in the Java programming
*
the Java programming
language.
* language.
* <p>
* <p>
* By default, all threads in the target VM are resumed while
* By default, all threads in the target VM are resumed while
* the method is being invoked if they were previously
* the method is being invoked if they were previously
...
@@ -246,10 +246,10 @@ public interface ObjectReference extends Value {
...
@@ -246,10 +246,10 @@ public interface ObjectReference extends Value {
* @return a {@link Value} mirror of the invoked method's return value.
* @return a {@link Value} mirror of the invoked method's return value.
* @throws java.lang.IllegalArgumentException if the method is not
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this object's class, if the size of the argument list
* a member of this object's class, if the size of the argument list
* does not match the number of declared argu
em
nts for the method,
* does not match the number of declared argu
me
nts for the method,
* if the method is a constructor or static intializer, or
* if the method is a constructor or static intializer, or
* if {@link #INVOKE_NONVIRTUAL} is specified and the method is
* if {@link #INVOKE_NONVIRTUAL} is specified and the method is
* either abstract or a
n
interface member.
* either abstract or a
non-default
interface member.
* @throws {@link InvalidTypeException} if any argument in the
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* argument list is not assignable to the corresponding method argument
* type.
* type.
...
...
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties
浏览文件 @
5606a2cd
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\u306E\u540D\u524D\u3092\u5909\u66F4\
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\u306E\u540D\u524D\u3092\u5909\u66F4\
FileChooser.renameErrorFileExists.textAndMnemonic
=
{0}
\u
306E
\u
540D
\u
524D
\u3092\u5909\u
66F4
\u3067\u
304D
\u
307E
\u
305B
\u3093
:
\u6307\u
5B9A
\u3057\u
305F
\u
540D
\u
524D
\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
\u
306F
\u3059\u3067\u
306B
\u
5B58
\u5728\u3057\u
307E
\u3059\u3002\u5225\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
\u
540D
\u3092\u6307\u
5B9A
\u3057\u3066\u
304F
\u3060\u3055\u3044\u3002
FileChooser.renameErrorFileExists.textAndMnemonic
=
{0}
\u
306E
\u
540D
\u
524D
\u3092\u5909\u
66F4
\u3067\u
304D
\u
307E
\u
305B
\u3093
:
\u6307\u
5B9A
\u3057\u
305F
\u
540D
\u
524D
\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
\u
306F
\u3059\u3067\u
306B
\u
5B58
\u5728\u3057\u
307E
\u3059\u3002\u5225\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
\u
540D
\u3092\u6307\u
5B9A
\u3057\u3066\u
304F
\u3060\u3055\u3044\u3002
FileChooser.acceptAllFileFilter.textAndMnemonic=
\u3059\u3079\u3066\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
FileChooser.acceptAllFileFilter.textAndMnemonic=
\u3059\u3079\u3066\u
306E
\u
30D5
\u
30A1
\u
30A4
\u
30EB
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.saveButton.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.saveButton.textAndMnemonic
=
\u
4FDD
\u
5B58
(&S)
FileChooser.openButton.textAndMnemonic
=
\u
958B
\u
304F
FileChooser.openButton.textAndMnemonic
=
\u
958B
\u
304F
(&O)
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.openDialogTitle.textAndMnemonic
=
\u
958B
\u
304F
FileChooser.openDialogTitle.textAndMnemonic
=
\u
958B
\u
304F
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.helpButton.textAndMnemonic
=
\u
30D8
\u
30EB
\u
30D7(&H)
FileChooser.helpButton.textAndMnemonic
=
\u
30D8
\u
30EB
\u
30D7(&H)
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
958B
\u
304F
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
958B
\u
304F
(&O)
# File Size Units
# File Size Units
FileChooser.fileSizeKiloBytes
=
{0} KB
FileChooser.fileSizeKiloBytes
=
{0} KB
...
...
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties
浏览文件 @
5606a2cd
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\uC758 \uC774\uB984\uC744 \uBC14\uAFC
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\uC758 \uC774\uB984\uC744 \uBC14\uAFC
FileChooser.renameErrorFileExists.textAndMnemonic
=
{0}
\u
C758
\u
C774
\u
B984
\u
C744
\u
BC14
\u
AFC0
\u
C218
\u
C5C6
\u
C74C:
\u
C9C0
\u
C815
\u
D55C
\u
C774
\u
B984
\u
C744
\u
C0AC
\u
C6A9
\u
D558
\u
B294
\u
D30C
\u
C77C
\u
C774
\u
C874
\u
C7AC
\u
D569
\u
B2C8
\u
B2E4.
\u
B2E4
\u
B978
\u
D30C
\u
C77C
\u
C774
\u
B984
\u
C744
\u
C9C0
\u
C815
\u
D558
\u
C2ED
\u
C2DC
\u
C624.
FileChooser.renameErrorFileExists.textAndMnemonic
=
{0}
\u
C758
\u
C774
\u
B984
\u
C744
\u
BC14
\u
AFC0
\u
C218
\u
C5C6
\u
C74C:
\u
C9C0
\u
C815
\u
D55C
\u
C774
\u
B984
\u
C744
\u
C0AC
\u
C6A9
\u
D558
\u
B294
\u
D30C
\u
C77C
\u
C774
\u
C874
\u
C7AC
\u
D569
\u
B2C8
\u
B2E4.
\u
B2E4
\u
B978
\u
D30C
\u
C77C
\u
C774
\u
B984
\u
C744
\u
C9C0
\u
C815
\u
D558
\u
C2ED
\u
C2DC
\u
C624.
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u
BAA8
\u
B4E0
\u
D30C
\u
C77C
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u
BAA8
\u
B4E0
\u
D30C
\u
C77C
FileChooser.cancelButton.textAndMnemonic
=
\u
CDE8
\u
C18C
FileChooser.cancelButton.textAndMnemonic
=
\u
CDE8
\u
C18C
FileChooser.saveButton.textAndMnemonic
=
\u
C800
\u
C7A5
FileChooser.saveButton.textAndMnemonic
=
\u
C800
\u
C7A5
(&S)
FileChooser.openButton.textAndMnemonic
=
\u
C5F4
\u
AE30
FileChooser.openButton.textAndMnemonic
=
\u
C5F4
\u
AE30
(&O)
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
C800
\u
C7A5
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
C800
\u
C7A5
FileChooser.openDialogTitle.textAndMnemonic
=
\u
C5F4
\u
AE30
FileChooser.openDialogTitle.textAndMnemonic
=
\u
C5F4
\u
AE30
FileChooser.updateButton.textAndMnemonic
=
\u
C5C5
\u
B370
\u
C774
\u
D2B8(&U)
FileChooser.updateButton.textAndMnemonic
=
\u
C5C5
\u
B370
\u
C774
\u
D2B8(&U)
FileChooser.helpButton.textAndMnemonic
=
\u
B3C4
\u
C6C0
\u
B9D0(&H)
FileChooser.helpButton.textAndMnemonic
=
\u
B3C4
\u
C6C0
\u
B9D0(&H)
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
C5F4
\u
AE30
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
C5F4
\u
AE30
(&O)
# File Size Units
# File Size Units
FileChooser.fileSizeKiloBytes
=
{0} KB
FileChooser.fileSizeKiloBytes
=
{0} KB
...
...
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties
浏览文件 @
5606a2cd
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u65E0\u6CD5\u91CD\u547D\u540D{0}
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u65E0\u6CD5\u91CD\u547D\u540D{0}
FileChooser.renameErrorFileExists.textAndMnemonic
=
\u
65E0
\u
6CD5
\u
91CD
\u
547D
\u
540D{0}:
\u
5DF2
\u
5B58
\u5728\u5177\u6709\u6240\u6307\u
5B9A
\u
540D
\u
79F0
\u7684\u6587\u
4EF6
\u3002\u
8BF7
\u6307\u
5B9A
\u5176\u
4ED6
\u6587\u
4EF6
\u
540D
\u3002
FileChooser.renameErrorFileExists.textAndMnemonic
=
\u
65E0
\u
6CD5
\u
91CD
\u
547D
\u
540D{0}:
\u
5DF2
\u
5B58
\u5728\u5177\u6709\u6240\u6307\u
5B9A
\u
540D
\u
79F0
\u7684\u6587\u
4EF6
\u3002\u
8BF7
\u6307\u
5B9A
\u5176\u
4ED6
\u6587\u
4EF6
\u
540D
\u3002
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u6240\u6709\u6587\u
4EF6
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u6240\u6709\u6587\u
4EF6
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.saveButton.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.saveButton.textAndMnemonic
=
\u
4FDD
\u
5B58
(&S)
FileChooser.openButton.textAndMnemonic
=
\u6253\u
5F00
FileChooser.openButton.textAndMnemonic
=
\u6253\u
5F00
(&O)
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.saveDialogTitle.textAndMnemonic
=
\u
4FDD
\u
5B58
FileChooser.openDialogTitle.textAndMnemonic
=
\u6253\u
5F00
FileChooser.openDialogTitle.textAndMnemonic
=
\u6253\u
5F00
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.helpButton.textAndMnemonic
=
\u
5E2E
\u
52A9(&H)
FileChooser.helpButton.textAndMnemonic
=
\u
5E2E
\u
52A9(&H)
FileChooser.directoryOpenButton.textAndMnemonic
=
\u6253\u
5F00
FileChooser.directoryOpenButton.textAndMnemonic
=
\u6253\u
5F00
(&O)
# File Size Units
# File Size Units
FileChooser.fileSizeKiloBytes
=
{0} KB
FileChooser.fileSizeKiloBytes
=
{0} KB
...
...
src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties
浏览文件 @
5606a2cd
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u7121\u6CD5\u91CD\u65B0\u547D\u540D {0}
...
@@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u7121\u6CD5\u91CD\u65B0\u547D\u540D {0}
FileChooser.renameErrorFileExists.textAndMnemonic
=
\u7121\u
6CD5
\u
91CD
\u
65B0
\u
547D
\u
540D {0}:
\u
5DF2
\u
7D93
\u
5B58
\u5728\u
60A8
\u6240\u6307\u
5B9A
\u
540D
\u
7A31
\u7684\u
6A94
\u6848\u3002\u
8ACB
\u6307\u
5B9A
\u
4E0D
\u
540C
\u7684\u
540D
\u
7A31
\u3002
FileChooser.renameErrorFileExists.textAndMnemonic
=
\u7121\u
6CD5
\u
91CD
\u
65B0
\u
547D
\u
540D {0}:
\u
5DF2
\u
7D93
\u
5B58
\u5728\u
60A8
\u6240\u6307\u
5B9A
\u
540D
\u
7A31
\u7684\u
6A94
\u6848\u3002\u
8ACB
\u6307\u
5B9A
\u
4E0D
\u
540C
\u7684\u
540D
\u
7A31
\u3002
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u6240\u6709\u
6A94
\u6848
FileChooser.acceptAllFileFilter.textAndMnemonic
=
\u6240\u6709\u
6A94
\u6848
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.cancelButton.textAndMnemonic
=
\u
53D6
\u
6D88
FileChooser.saveButton.textAndMnemonic
=
\u5132\u
5B58
FileChooser.saveButton.textAndMnemonic
=
\u5132\u
5B58
(&S)
FileChooser.openButton.textAndMnemonic
=
\u
958B
\u
555F
FileChooser.openButton.textAndMnemonic
=
\u
958B
\u
555F
(&O)
FileChooser.saveDialogTitle.textAndMnemonic
=
\u5132\u
5B58
FileChooser.saveDialogTitle.textAndMnemonic
=
\u5132\u
5B58
FileChooser.openDialogTitle.textAndMnemonic
=
\u
958B
\u
555F
FileChooser.openDialogTitle.textAndMnemonic
=
\u
958B
\u
555F
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.updateButton.textAndMnemonic
=
\u
66F4
\u
65B0(&U)
FileChooser.helpButton.textAndMnemonic
=
\u
8AAA
\u
660E(&H)
FileChooser.helpButton.textAndMnemonic
=
\u
8AAA
\u
660E(&H)
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
958B
\u
555F
FileChooser.directoryOpenButton.textAndMnemonic
=
\u
958B
\u
555F
(&O)
# File Size Units
# File Size Units
FileChooser.fileSizeKiloBytes
=
{0} KB
FileChooser.fileSizeKiloBytes
=
{0} KB
...
...
src/share/classes/com/sun/tools/example/debug/expr/LValue.java
浏览文件 @
5606a2cd
...
@@ -559,6 +559,9 @@ abstract class LValue {
...
@@ -559,6 +559,9 @@ abstract class LValue {
}
else
if
(
refType
instanceof
ClassType
)
{
}
else
if
(
refType
instanceof
ClassType
)
{
ClassType
clazz
=
(
ClassType
)
refType
;
ClassType
clazz
=
(
ClassType
)
refType
;
return
jdiValue
=
clazz
.
invokeMethod
(
thread
,
matchingMethod
,
methodArguments
,
0
);
return
jdiValue
=
clazz
.
invokeMethod
(
thread
,
matchingMethod
,
methodArguments
,
0
);
}
else
if
(
refType
instanceof
InterfaceType
)
{
InterfaceType
iface
=
(
InterfaceType
)
refType
;
return
jdiValue
=
iface
.
invokeMethod
(
thread
,
matchingMethod
,
methodArguments
,
0
);
}
else
{
}
else
{
throw
new
InvalidTypeException
(
"Cannot invoke static method on "
+
throw
new
InvalidTypeException
(
"Cannot invoke static method on "
+
refType
.
name
());
refType
.
name
());
...
...
src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java
浏览文件 @
5606a2cd
...
@@ -31,6 +31,7 @@ import java.util.List;
...
@@ -31,6 +31,7 @@ import java.util.List;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
public
class
ArrayTypeImpl
extends
ReferenceTypeImpl
public
class
ArrayTypeImpl
extends
ReferenceTypeImpl
implements
ArrayType
implements
ArrayType
...
@@ -61,7 +62,8 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
...
@@ -61,7 +62,8 @@ public class ArrayTypeImpl extends ReferenceTypeImpl
return
findType
(
componentSignature
());
return
findType
(
componentSignature
());
}
}
void
addVisibleMethods
(
Map
<
String
,
Method
>
map
)
{
@Override
void
addVisibleMethods
(
Map
<
String
,
Method
>
map
,
Set
<
InterfaceType
>
seenInterfaces
)
{
// arrays don't have methods
// arrays don't have methods
}
}
...
...
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
浏览文件 @
5606a2cd
...
@@ -29,9 +29,27 @@ import com.sun.jdi.*;
...
@@ -29,9 +29,27 @@ import com.sun.jdi.*;
import
java.util.*
;
import
java.util.*
;
public
class
ClassTypeImpl
extends
Referenc
eTypeImpl
final
public
class
ClassTypeImpl
extends
Invokabl
eTypeImpl
implements
ClassType
implements
ClassType
{
{
private
static
class
IResult
implements
InvocationResult
{
final
private
JDWP
.
ClassType
.
InvokeMethod
rslt
;
public
IResult
(
JDWP
.
ClassType
.
InvokeMethod
rslt
)
{
this
.
rslt
=
rslt
;
}
@Override
public
ObjectReferenceImpl
getException
()
{
return
rslt
.
exception
;
}
@Override
public
ValueImpl
getResult
()
{
return
rslt
.
returnValue
;
}
}
private
boolean
cachedSuperclass
=
false
;
private
boolean
cachedSuperclass
=
false
;
private
ClassType
superclass
=
null
;
private
ClassType
superclass
=
null
;
private
int
lastLine
=
-
1
;
private
int
lastLine
=
-
1
;
...
@@ -65,6 +83,7 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -65,6 +83,7 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
superclass
;
return
superclass
;
}
}
@Override
public
List
<
InterfaceType
>
interfaces
()
{
public
List
<
InterfaceType
>
interfaces
()
{
if
(
interfaces
==
null
)
{
if
(
interfaces
==
null
)
{
interfaces
=
getInterfaces
();
interfaces
=
getInterfaces
();
...
@@ -72,26 +91,9 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -72,26 +91,9 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
interfaces
;
return
interfaces
;
}
}
void
addInterfaces
(
List
<
InterfaceType
>
list
)
{
@Override
List
<
InterfaceType
>
immediate
=
interfaces
();
list
.
addAll
(
interfaces
());
Iterator
<
InterfaceType
>
iter
=
immediate
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
interfaze
.
addSuperinterfaces
(
list
);
}
ClassTypeImpl
superclass
=
(
ClassTypeImpl
)
superclass
();
if
(
superclass
!=
null
)
{
superclass
.
addInterfaces
(
list
);
}
}
public
List
<
InterfaceType
>
allInterfaces
()
{
public
List
<
InterfaceType
>
allInterfaces
()
{
List
<
InterfaceType
>
all
=
new
ArrayList
<
InterfaceType
>();
return
getAllInterfaces
();
addInterfaces
(
all
);
return
all
;
}
}
public
List
<
ClassType
>
subclasses
()
{
public
List
<
ClassType
>
subclasses
()
{
...
@@ -159,28 +161,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -159,28 +161,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
}
}
}
}
PacketStream
sendInvokeCommand
(
final
ThreadReferenceImpl
thread
,
final
MethodImpl
method
,
final
ValueImpl
[]
args
,
final
int
options
)
{
CommandSender
sender
=
new
CommandSender
()
{
public
PacketStream
send
()
{
return
JDWP
.
ClassType
.
InvokeMethod
.
enqueueCommand
(
vm
,
ClassTypeImpl
.
this
,
thread
,
method
.
ref
(),
args
,
options
);
}
};
PacketStream
stream
;
if
((
options
&
INVOKE_SINGLE_THREADED
)
!=
0
)
{
stream
=
thread
.
sendResumingCommand
(
sender
);
}
else
{
stream
=
vm
.
sendResumingCommand
(
sender
);
}
return
stream
;
}
PacketStream
sendNewInstanceCommand
(
final
ThreadReferenceImpl
thread
,
PacketStream
sendNewInstanceCommand
(
final
ThreadReferenceImpl
thread
,
final
MethodImpl
method
,
final
MethodImpl
method
,
final
ValueImpl
[]
args
,
final
ValueImpl
[]
args
,
...
@@ -203,52 +183,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -203,52 +183,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
stream
;
return
stream
;
}
}
public
Value
invokeMethod
(
ThreadReference
threadIntf
,
Method
methodIntf
,
List
<?
extends
Value
>
origArguments
,
int
options
)
throws
InvalidTypeException
,
ClassNotLoadedException
,
IncompatibleThreadStateException
,
InvocationException
{
validateMirror
(
threadIntf
);
validateMirror
(
methodIntf
);
validateMirrorsOrNulls
(
origArguments
);
MethodImpl
method
=
(
MethodImpl
)
methodIntf
;
ThreadReferenceImpl
thread
=
(
ThreadReferenceImpl
)
threadIntf
;
validateMethodInvocation
(
method
);
List
<?
extends
Value
>
arguments
=
method
.
validateAndPrepareArgumentsForInvoke
(
origArguments
);
ValueImpl
[]
args
=
arguments
.
toArray
(
new
ValueImpl
[
0
]);
JDWP
.
ClassType
.
InvokeMethod
ret
;
try
{
PacketStream
stream
=
sendInvokeCommand
(
thread
,
method
,
args
,
options
);
ret
=
JDWP
.
ClassType
.
InvokeMethod
.
waitForReply
(
vm
,
stream
);
}
catch
(
JDWPException
exc
)
{
if
(
exc
.
errorCode
()
==
JDWP
.
Error
.
INVALID_THREAD
)
{
throw
new
IncompatibleThreadStateException
();
}
else
{
throw
exc
.
toJDIException
();
}
}
/*
* There is an implict VM-wide suspend at the conclusion
* of a normal (non-single-threaded) method invoke
*/
if
((
options
&
INVOKE_SINGLE_THREADED
)
==
0
)
{
vm
.
notifySuspend
();
}
if
(
ret
.
exception
!=
null
)
{
throw
new
InvocationException
(
ret
.
exception
);
}
else
{
return
ret
.
returnValue
;
}
}
public
ObjectReference
newInstance
(
ThreadReference
threadIntf
,
public
ObjectReference
newInstance
(
ThreadReference
threadIntf
,
Method
methodIntf
,
Method
methodIntf
,
List
<?
extends
Value
>
origArguments
,
List
<?
extends
Value
>
origArguments
,
...
@@ -311,58 +245,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -311,58 +245,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
method
;
return
method
;
}
}
public
List
<
Method
>
allMethods
()
{
ArrayList
<
Method
>
list
=
new
ArrayList
<
Method
>(
methods
());
ClassType
clazz
=
superclass
();
while
(
clazz
!=
null
)
{
list
.
addAll
(
clazz
.
methods
());
clazz
=
clazz
.
superclass
();
}
/*
* Avoid duplicate checking on each method by iterating through
* duplicate-free allInterfaces() rather than recursing
*/
for
(
InterfaceType
interfaze
:
allInterfaces
())
{
list
.
addAll
(
interfaze
.
methods
());
}
return
list
;
}
List
<
ReferenceType
>
inheritedTypes
()
{
List
<
ReferenceType
>
inherited
=
new
ArrayList
<
ReferenceType
>();
if
(
superclass
()
!=
null
)
{
inherited
.
add
(
0
,
(
ReferenceType
)
superclass
());
/* insert at front */
}
for
(
ReferenceType
rt
:
interfaces
())
{
inherited
.
add
(
rt
);
}
return
inherited
;
}
void
validateMethodInvocation
(
Method
method
)
throws
InvalidTypeException
,
InvocationException
{
/*
* Method must be in this class or a superclass.
*/
ReferenceTypeImpl
declType
=
(
ReferenceTypeImpl
)
method
.
declaringType
();
if
(!
declType
.
isAssignableFrom
(
this
))
{
throw
new
IllegalArgumentException
(
"Invalid method"
);
}
/*
* Method must be a static and not a static initializer
*/
if
(!
method
.
isStatic
())
{
throw
new
IllegalArgumentException
(
"Cannot invoke instance method on a class type"
);
}
else
if
(
method
.
isStaticInitializer
())
{
throw
new
IllegalArgumentException
(
"Cannot invoke static initializer"
);
}
}
void
validateConstructorInvocation
(
Method
method
)
void
validateConstructorInvocation
(
Method
method
)
throws
InvalidTypeException
,
throws
InvalidTypeException
,
InvocationException
{
InvocationException
{
...
@@ -382,47 +264,33 @@ public class ClassTypeImpl extends ReferenceTypeImpl
...
@@ -382,47 +264,33 @@ public class ClassTypeImpl extends ReferenceTypeImpl
}
}
}
}
void
addVisibleMethods
(
Map
<
String
,
Method
>
methodMap
)
{
/*
* Add methods from
* parent types first, so that the methods in this class will
* overwrite them in the hash table
*/
Iterator
<
InterfaceType
>
iter
=
interfaces
().
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
interfaze
.
addVisibleMethods
(
methodMap
);
}
ClassTypeImpl
clazz
=
(
ClassTypeImpl
)
superclass
();
public
String
toString
()
{
if
(
clazz
!=
null
)
{
return
"class "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
clazz
.
addVisibleMethods
(
methodMap
);
}
}
addToMethodMap
(
methodMap
,
methods
());
@Override
CommandSender
getInvokeMethodSender
(
ThreadReferenceImpl
thread
,
MethodImpl
method
,
ValueImpl
[]
args
,
int
options
)
{
return
()
->
JDWP
.
ClassType
.
InvokeMethod
.
enqueueCommand
(
vm
,
ClassTypeImpl
.
this
,
thread
,
method
.
ref
(),
args
,
options
);
}
}
boolean
isAssignableTo
(
ReferenceType
type
)
{
@Override
ClassTypeImpl
superclazz
=
(
ClassTypeImpl
)
superclass
();
InvocationResult
waitForReply
(
PacketStream
stream
)
throws
JDWPException
{
if
(
this
.
equals
(
type
))
{
return
new
IResult
(
JDWP
.
ClassType
.
InvokeMethod
.
waitForReply
(
vm
,
stream
));
return
true
;
}
else
if
((
superclazz
!=
null
)
&&
superclazz
.
isAssignableTo
(
type
))
{
return
true
;
}
else
{
List
<
InterfaceType
>
interfaces
=
interfaces
();
Iterator
<
InterfaceType
>
iter
=
interfaces
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
if
(
interfaze
.
isAssignableTo
(
type
))
{
return
true
;
}
}
return
false
;
}
}
}
public
String
toString
()
{
@Override
return
"class "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
boolean
canInvoke
(
Method
method
)
{
// Method must be in this class or a superclass.
return
((
ReferenceTypeImpl
)
method
.
declaringType
()).
isAssignableFrom
(
this
);
}
}
}
}
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
浏览文件 @
5606a2cd
...
@@ -29,14 +29,32 @@ import com.sun.jdi.*;
...
@@ -29,14 +29,32 @@ import com.sun.jdi.*;
import
java.util.List
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Map
;
import
java.util.Iterator
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Set
;
import
java.lang.ref.SoftReference
;
import
java.lang.ref.SoftReference
;
public
class
InterfaceTypeImpl
extends
Referenc
eTypeImpl
final
public
class
InterfaceTypeImpl
extends
Invokabl
eTypeImpl
implements
InterfaceType
{
implements
InterfaceType
{
private
static
class
IResult
implements
InvocationResult
{
final
private
JDWP
.
InterfaceType
.
InvokeMethod
rslt
;
public
IResult
(
JDWP
.
InterfaceType
.
InvokeMethod
rslt
)
{
this
.
rslt
=
rslt
;
}
@Override
public
ObjectReferenceImpl
getException
()
{
return
rslt
.
exception
;
}
@Override
public
ValueImpl
getResult
()
{
return
rslt
.
returnValue
;
}
}
private
SoftReference
<
List
<
InterfaceType
>>
superinterfacesRef
=
null
;
private
SoftReference
<
List
<
InterfaceType
>>
superinterfacesRef
=
null
;
protected
InterfaceTypeImpl
(
VirtualMachine
aVm
,
long
aRef
)
{
protected
InterfaceTypeImpl
(
VirtualMachine
aVm
,
long
aRef
)
{
...
@@ -80,103 +98,46 @@ public class InterfaceTypeImpl extends ReferenceTypeImpl
...
@@ -80,103 +98,46 @@ public class InterfaceTypeImpl extends ReferenceTypeImpl
return
implementors
;
return
implementors
;
}
}
void
addVisibleMethods
(
Map
<
String
,
Method
>
methodMap
)
{
public
boolean
isInitialized
()
{
/*
return
isPrepared
();
* Add methods from
* parent types first, so that the methods in this class will
* overwrite them in the hash table
*/
for
(
InterfaceType
interfaze
:
superinterfaces
())
{
((
InterfaceTypeImpl
)
interfaze
).
addVisibleMethods
(
methodMap
);
}
addToMethodMap
(
methodMap
,
methods
());
}
public
List
<
Method
>
allMethods
()
{
ArrayList
<
Method
>
list
=
new
ArrayList
<
Method
>(
methods
());
/*
* It's more efficient if don't do this
* recursively.
*/
for
(
InterfaceType
interfaze
:
allSuperinterfaces
())
{
list
.
addAll
(
interfaze
.
methods
());
}
return
list
;
}
List
<
InterfaceType
>
allSuperinterfaces
()
{
ArrayList
<
InterfaceType
>
list
=
new
ArrayList
<
InterfaceType
>();
addSuperinterfaces
(
list
);
return
list
;
}
}
void
addSuperinterfaces
(
List
<
InterfaceType
>
list
)
{
public
String
toString
()
{
/*
return
"interface "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
* This code is a little strange because it
* builds the list with a more suitable order than the
* depth-first approach a normal recursive solution would
* take. Instead, all direct superinterfaces precede all
* indirect ones.
*/
/*
* Get a list of direct superinterfaces that's not already in the
* list being built.
*/
List
<
InterfaceType
>
immediate
=
new
ArrayList
<
InterfaceType
>(
superinterfaces
());
Iterator
<
InterfaceType
>
iter
=
immediate
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceType
interfaze
=
iter
.
next
();
if
(
list
.
contains
(
interfaze
))
{
iter
.
remove
();
}
}
}
/*
@Override
* Add all new direct superinterfaces
InvocationResult
waitForReply
(
PacketStream
stream
)
throws
JDWPException
{
*/
return
new
IResult
(
JDWP
.
InterfaceType
.
InvokeMethod
.
waitForReply
(
vm
,
stream
));
list
.
addAll
(
immediate
);
/*
* Recurse for all new direct superinterfaces.
*/
iter
=
immediate
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
interfaze
.
addSuperinterfaces
(
list
);
}
}
}
boolean
isAssignableTo
(
ReferenceType
type
)
{
// Exact match?
@Override
if
(
this
.
equals
(
type
))
{
CommandSender
getInvokeMethodSender
(
final
ThreadReferenceImpl
thread
,
return
true
;
final
MethodImpl
method
,
}
else
{
final
ValueImpl
[]
args
,
// Try superinterfaces.
final
int
options
)
{
for
(
InterfaceType
interfaze
:
superinterfaces
())
{
return
()
->
if
(((
InterfaceTypeImpl
)
interfaze
).
isAssignableTo
(
type
))
{
JDWP
.
InterfaceType
.
InvokeMethod
.
enqueueCommand
(
vm
,
return
true
;
InterfaceTypeImpl
.
this
,
}
thread
,
method
.
ref
(),
args
,
options
);
}
}
return
false
;
@Override
}
ClassType
superclass
()
{
return
null
;
}
}
List
<
InterfaceType
>
inheritedTypes
()
{
@Override
List
<
InterfaceType
>
interfaces
()
{
return
superinterfaces
();
return
superinterfaces
();
}
}
public
boolean
isInitialized
()
{
@Override
return
isPrepared
();
boolean
canInvoke
(
Method
method
)
{
}
// method must be directly in this interface
return
this
.
equals
(
method
.
declaringType
());
public
String
toString
()
{
return
"interface "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
}
}
}
}
\ No newline at end of file
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
com.sun.tools.jdi
;
import
com.sun.jdi.ClassNotLoadedException
;
import
com.sun.jdi.ClassType
;
import
com.sun.jdi.IncompatibleThreadStateException
;
import
com.sun.jdi.InterfaceType
;
import
com.sun.jdi.InvalidTypeException
;
import
com.sun.jdi.InvocationException
;
import
com.sun.jdi.Method
;
import
com.sun.jdi.ReferenceType
;
import
com.sun.jdi.ThreadReference
;
import
com.sun.jdi.Value
;
import
com.sun.jdi.VirtualMachine
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* A supertype for ReferenceTypes allowing method invocations
*/
abstract
class
InvokableTypeImpl
extends
ReferenceTypeImpl
{
/**
* The invocation result wrapper
* It is necessary because both ClassType and InterfaceType
* use their own type to represent the invocation result
*/
static
interface
InvocationResult
{
ObjectReferenceImpl
getException
();
ValueImpl
getResult
();
}
InvokableTypeImpl
(
VirtualMachine
aVm
,
long
aRef
)
{
super
(
aVm
,
aRef
);
}
/**
* Method invocation support.
* Shared by ClassType and InterfaceType
* @param threadIntf the thread in which to invoke.
* @param methodIntf method the {@link Method} to invoke.
* @param origArguments the list of {@link Value} arguments bound to the
* invoked method. Values from the list are assigned to arguments
* in the order they appear in the method signature.
* @param options the integer bit flag options.
* @return a {@link Value} mirror of the invoked method's return value.
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this type, if the size of the argument list
* does not match the number of declared arguments for the method, or
* if the method is not static or is a static initializer.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
* been suspended by an event.
* @throws InvocationException if the method invocation resulted in
* an exception in the target VM.
* @throws InvalidTypeException If the arguments do not meet this requirement --
* Object arguments must be assignment compatible with the argument
* type. This implies that the argument type must be
* loaded through the enclosing class's class loader.
* Primitive arguments must be either assignment compatible with the
* argument type or must be convertible to the argument type without loss
* of information. See JLS section 5.2 for more information on assignment
* compatibility.
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}.
*/
final
public
Value
invokeMethod
(
ThreadReference
threadIntf
,
Method
methodIntf
,
List
<?
extends
Value
>
origArguments
,
int
options
)
throws
InvalidTypeException
,
ClassNotLoadedException
,
IncompatibleThreadStateException
,
InvocationException
{
validateMirror
(
threadIntf
);
validateMirror
(
methodIntf
);
validateMirrorsOrNulls
(
origArguments
);
MethodImpl
method
=
(
MethodImpl
)
methodIntf
;
ThreadReferenceImpl
thread
=
(
ThreadReferenceImpl
)
threadIntf
;
validateMethodInvocation
(
method
);
List
<?
extends
Value
>
arguments
=
method
.
validateAndPrepareArgumentsForInvoke
(
origArguments
);
ValueImpl
[]
args
=
arguments
.
toArray
(
new
ValueImpl
[
0
]);
InvocationResult
ret
;
try
{
PacketStream
stream
=
sendInvokeCommand
(
thread
,
method
,
args
,
options
);
ret
=
waitForReply
(
stream
);
}
catch
(
JDWPException
exc
)
{
if
(
exc
.
errorCode
()
==
JDWP
.
Error
.
INVALID_THREAD
)
{
throw
new
IncompatibleThreadStateException
();
}
else
{
throw
exc
.
toJDIException
();
}
}
/*
* There is an implict VM-wide suspend at the conclusion
* of a normal (non-single-threaded) method invoke
*/
if
((
options
&
ClassType
.
INVOKE_SINGLE_THREADED
)
==
0
)
{
vm
.
notifySuspend
();
}
if
(
ret
.
getException
()
!=
null
)
{
throw
new
InvocationException
(
ret
.
getException
());
}
else
{
return
ret
.
getResult
();
}
}
@Override
boolean
isAssignableTo
(
ReferenceType
type
)
{
ClassTypeImpl
superclazz
=
(
ClassTypeImpl
)
superclass
();
if
(
this
.
equals
(
type
))
{
return
true
;
}
else
if
((
superclazz
!=
null
)
&&
superclazz
.
isAssignableTo
(
type
))
{
return
true
;
}
else
{
List
<
InterfaceType
>
interfaces
=
interfaces
();
Iterator
<
InterfaceType
>
iter
=
interfaces
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
if
(
interfaze
.
isAssignableTo
(
type
))
{
return
true
;
}
}
return
false
;
}
}
@Override
final
void
addVisibleMethods
(
Map
<
String
,
Method
>
methodMap
,
Set
<
InterfaceType
>
seenInterfaces
)
{
/*
* Add methods from
* parent types first, so that the methods in this class will
* overwrite them in the hash table
*/
Iterator
<
InterfaceType
>
iter
=
interfaces
().
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
if
(!
seenInterfaces
.
contains
(
interfaze
))
{
interfaze
.
addVisibleMethods
(
methodMap
,
seenInterfaces
);
seenInterfaces
.
add
(
interfaze
);
}
}
ClassTypeImpl
clazz
=
(
ClassTypeImpl
)
superclass
();
if
(
clazz
!=
null
)
{
clazz
.
addVisibleMethods
(
methodMap
,
seenInterfaces
);
}
addToMethodMap
(
methodMap
,
methods
());
}
final
void
addInterfaces
(
List
<
InterfaceType
>
list
)
{
List
<
InterfaceType
>
immediate
=
interfaces
();
list
.
addAll
(
interfaces
());
Iterator
<
InterfaceType
>
iter
=
immediate
.
iterator
();
while
(
iter
.
hasNext
())
{
InterfaceTypeImpl
interfaze
=
(
InterfaceTypeImpl
)
iter
.
next
();
interfaze
.
addInterfaces
(
list
);
}
ClassTypeImpl
superclass
=
(
ClassTypeImpl
)
superclass
();
if
(
superclass
!=
null
)
{
superclass
.
addInterfaces
(
list
);
}
}
/**
* Returns all the implemented interfaces recursively
* @return A list of all the implemented interfaces (recursively)
*/
final
List
<
InterfaceType
>
getAllInterfaces
()
{
List
<
InterfaceType
>
all
=
new
ArrayList
<>();
addInterfaces
(
all
);
return
all
;
}
/**
* Shared implementation of {@linkplain ClassType#allMethods()} and
* {@linkplain InterfaceType#allMethods()}
* @return A list of all methods (recursively)
*/
public
final
List
<
Method
>
allMethods
()
{
ArrayList
<
Method
>
list
=
new
ArrayList
<>(
methods
());
ClassType
clazz
=
superclass
();
while
(
clazz
!=
null
)
{
list
.
addAll
(
clazz
.
methods
());
clazz
=
clazz
.
superclass
();
}
/*
* Avoid duplicate checking on each method by iterating through
* duplicate-free allInterfaces() rather than recursing
*/
for
(
InterfaceType
interfaze
:
getAllInterfaces
())
{
list
.
addAll
(
interfaze
.
methods
());
}
return
list
;
}
@Override
final
List
<
ReferenceType
>
inheritedTypes
()
{
List
<
ReferenceType
>
inherited
=
new
ArrayList
<>();
if
(
superclass
()
!=
null
)
{
inherited
.
add
(
0
,
superclass
());
/* insert at front */
}
for
(
ReferenceType
rt
:
interfaces
())
{
inherited
.
add
(
rt
);
}
return
inherited
;
}
private
PacketStream
sendInvokeCommand
(
final
ThreadReferenceImpl
thread
,
final
MethodImpl
method
,
final
ValueImpl
[]
args
,
final
int
options
)
{
CommandSender
sender
=
getInvokeMethodSender
(
thread
,
method
,
args
,
options
);
PacketStream
stream
;
if
((
options
&
ClassType
.
INVOKE_SINGLE_THREADED
)
!=
0
)
{
stream
=
thread
.
sendResumingCommand
(
sender
);
}
else
{
stream
=
vm
.
sendResumingCommand
(
sender
);
}
return
stream
;
}
private
void
validateMethodInvocation
(
Method
method
)
throws
InvalidTypeException
,
InvocationException
{
if
(!
canInvoke
(
method
))
{
throw
new
IllegalArgumentException
(
"Invalid method"
);
}
/*
* Method must be a static and not a static initializer
*/
if
(!
method
.
isStatic
())
{
throw
new
IllegalArgumentException
(
"Cannot invoke instance method on a class/interface type"
);
}
else
if
(
method
.
isStaticInitializer
())
{
throw
new
IllegalArgumentException
(
"Cannot invoke static initializer"
);
}
}
/**
* A subclass will provide specific {@linkplain CommandSender}
* @param thread the current invocation thread
* @param method the method to invoke
* @param args the arguments to pass to the method
* @param options the integer bit flag options
* @return the specific {@literal CommandSender} instance
*/
abstract
CommandSender
getInvokeMethodSender
(
ThreadReferenceImpl
thread
,
MethodImpl
method
,
ValueImpl
[]
args
,
int
options
);
/**
* Waits for the reply to the last sent command
* @param stream the stream to listen for the reply on
* @return the {@linkplain InvocationResult} instance
* @throws JDWPException when something goes wrong in JDWP
*/
abstract
InvocationResult
waitForReply
(
PacketStream
stream
)
throws
JDWPException
;
/**
* Get the {@linkplain ReferenceType} superclass
* @return the superclass or null
*/
abstract
ClassType
superclass
();
/**
* Get the implemented/extended interfaces
* @return the list of implemented/extended interfaces
*/
abstract
List
<
InterfaceType
>
interfaces
();
/**
* Checks the provided method whether it can be invoked
* @param method the method to check
* @return {@code TRUE} if the implementation knows how to invoke the method,
* {@code FALSE} otherwise
*/
abstract
boolean
canInvoke
(
Method
method
);
}
src/share/classes/com/sun/tools/jdi/MethodImpl.java
浏览文件 @
5606a2cd
...
@@ -187,6 +187,13 @@ public abstract class MethodImpl extends TypeComponentImpl
...
@@ -187,6 +187,13 @@ public abstract class MethodImpl extends TypeComponentImpl
return
isModifierSet
(
VMModifiers
.
ABSTRACT
);
return
isModifierSet
(
VMModifiers
.
ABSTRACT
);
}
}
public
boolean
isDefault
()
{
return
!
isModifierSet
(
VMModifiers
.
ABSTRACT
)
&&
!
isModifierSet
(
VMModifiers
.
STATIC
)
&&
!
isModifierSet
(
VMModifiers
.
PRIVATE
)
&&
declaringType
()
instanceof
InterfaceType
;
}
public
boolean
isSynchronized
()
{
public
boolean
isSynchronized
()
{
return
isModifierSet
(
VMModifiers
.
SYNCHRONIZED
);
return
isModifierSet
(
VMModifiers
.
SYNCHRONIZED
);
}
}
...
...
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
浏览文件 @
5606a2cd
...
@@ -277,7 +277,6 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -277,7 +277,6 @@ public class ObjectReferenceImpl extends ValueImpl
void
validateMethodInvocation
(
Method
method
,
int
options
)
void
validateMethodInvocation
(
Method
method
,
int
options
)
throws
InvalidTypeException
,
throws
InvalidTypeException
,
InvocationException
{
InvocationException
{
/*
/*
* Method must be in this object's class, a superclass, or
* Method must be in this object's class, a superclass, or
* implemented interface
* implemented interface
...
@@ -287,6 +286,19 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -287,6 +286,19 @@ public class ObjectReferenceImpl extends ValueImpl
throw
new
IllegalArgumentException
(
"Invalid method"
);
throw
new
IllegalArgumentException
(
"Invalid method"
);
}
}
if
(
declType
instanceof
ClassTypeImpl
)
{
validateClassMethodInvocation
(
method
,
options
);
}
else
if
(
declType
instanceof
InterfaceTypeImpl
)
{
validateIfaceMethodInvocation
(
method
,
options
);
}
else
{
throw
new
InvalidTypeException
();
}
}
void
validateClassMethodInvocation
(
Method
method
,
int
options
)
throws
InvalidTypeException
,
InvocationException
{
ClassTypeImpl
clazz
=
invokableReferenceType
(
method
);
ClassTypeImpl
clazz
=
invokableReferenceType
(
method
);
/*
/*
...
@@ -300,9 +312,7 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -300,9 +312,7 @@ public class ObjectReferenceImpl extends ValueImpl
* For nonvirtual invokes, method must have a body
* For nonvirtual invokes, method must have a body
*/
*/
if
((
options
&
INVOKE_NONVIRTUAL
)
!=
0
)
{
if
((
options
&
INVOKE_NONVIRTUAL
)
!=
0
)
{
if
(
method
.
declaringType
()
instanceof
InterfaceType
)
{
if
(
method
.
isAbstract
())
{
throw
new
IllegalArgumentException
(
"Interface method"
);
}
else
if
(
method
.
isAbstract
())
{
throw
new
IllegalArgumentException
(
"Abstract method"
);
throw
new
IllegalArgumentException
(
"Abstract method"
);
}
}
}
}
...
@@ -324,7 +334,7 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -324,7 +334,7 @@ public class ObjectReferenceImpl extends ValueImpl
*/
*/
Method
invoker
=
clazz
.
concreteMethodByName
(
method
.
name
(),
Method
invoker
=
clazz
.
concreteMethodByName
(
method
.
name
(),
method
.
signature
());
method
.
signature
());
// i
sAssignableFrom check above guarantees non-null
// i
nvoker is supposed to be non-null under normal circumstances
invokedClass
=
(
ClassTypeImpl
)
invoker
.
declaringType
();
invokedClass
=
(
ClassTypeImpl
)
invoker
.
declaringType
();
}
}
/* The above code is left over from previous versions.
/* The above code is left over from previous versions.
...
@@ -332,6 +342,17 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -332,6 +342,17 @@ public class ObjectReferenceImpl extends ValueImpl
*/
*/
}
}
void
validateIfaceMethodInvocation
(
Method
method
,
int
options
)
throws
InvalidTypeException
,
InvocationException
{
/*
* Only default methods allowed for nonvirtual invokes
*/
if
(!
method
.
isDefault
())
{
throw
new
IllegalArgumentException
(
"Not a default method"
);
}
}
PacketStream
sendInvokeCommand
(
final
ThreadReferenceImpl
thread
,
PacketStream
sendInvokeCommand
(
final
ThreadReferenceImpl
thread
,
final
ClassTypeImpl
refType
,
final
ClassTypeImpl
refType
,
final
MethodImpl
method
,
final
MethodImpl
method
,
...
@@ -370,7 +391,10 @@ public class ObjectReferenceImpl extends ValueImpl
...
@@ -370,7 +391,10 @@ public class ObjectReferenceImpl extends ValueImpl
ThreadReferenceImpl
thread
=
(
ThreadReferenceImpl
)
threadIntf
;
ThreadReferenceImpl
thread
=
(
ThreadReferenceImpl
)
threadIntf
;
if
(
method
.
isStatic
())
{
if
(
method
.
isStatic
())
{
if
(
referenceType
()
instanceof
ClassType
)
{
if
(
referenceType
()
instanceof
InterfaceType
)
{
InterfaceType
type
=
(
InterfaceType
)
referenceType
();
return
type
.
invokeMethod
(
thread
,
method
,
origArguments
,
options
);
}
else
if
(
referenceType
()
instanceof
ClassType
)
{
ClassType
type
=
(
ClassType
)
referenceType
();
ClassType
type
=
(
ClassType
)
referenceType
();
return
type
.
invokeMethod
(
thread
,
method
,
origArguments
,
options
);
return
type
.
invokeMethod
(
thread
,
method
,
origArguments
,
options
);
}
else
{
}
else
{
...
...
src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
浏览文件 @
5606a2cd
...
@@ -511,7 +511,7 @@ implements ReferenceType {
...
@@ -511,7 +511,7 @@ implements ReferenceType {
methodMap
.
put
(
method
.
name
().
concat
(
method
.
signature
()),
method
);
methodMap
.
put
(
method
.
name
().
concat
(
method
.
signature
()),
method
);
}
}
abstract
void
addVisibleMethods
(
Map
<
String
,
Method
>
methodMap
);
abstract
void
addVisibleMethods
(
Map
<
String
,
Method
>
methodMap
,
Set
<
InterfaceType
>
seenInterfaces
);
public
List
<
Method
>
visibleMethods
()
{
public
List
<
Method
>
visibleMethods
()
{
/*
/*
...
@@ -520,7 +520,7 @@ implements ReferenceType {
...
@@ -520,7 +520,7 @@ implements ReferenceType {
* concatenation of name and signature.
* concatenation of name and signature.
*/
*/
Map
<
String
,
Method
>
map
=
new
HashMap
<
String
,
Method
>();
Map
<
String
,
Method
>
map
=
new
HashMap
<
String
,
Method
>();
addVisibleMethods
(
map
);
addVisibleMethods
(
map
,
new
HashSet
<
InterfaceType
>()
);
/*
/*
* ... but the hash map destroys order. Methods should be
* ... but the hash map destroys order. Methods should be
...
...
src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
浏览文件 @
5606a2cd
...
@@ -48,7 +48,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
...
@@ -48,7 +48,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
private
ResourceBundle
messages
=
null
;
private
ResourceBundle
messages
=
null
;
private
int
vmSequenceNumber
=
0
;
private
int
vmSequenceNumber
=
0
;
private
static
final
int
majorVersion
=
1
;
private
static
final
int
majorVersion
=
1
;
private
static
final
int
minorVersion
=
6
;
private
static
final
int
minorVersion
=
8
;
private
static
final
Object
lock
=
new
Object
();
private
static
final
Object
lock
=
new
Object
();
private
static
VirtualMachineManagerImpl
vmm
;
private
static
VirtualMachineManagerImpl
vmm
;
...
...
src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
浏览文件 @
5606a2cd
...
@@ -62,7 +62,7 @@ class InvokerBytecodeGenerator {
...
@@ -62,7 +62,7 @@ class InvokerBytecodeGenerator {
private
static
final
String
CLL_SIG
=
"(L"
+
CLS
+
";L"
+
OBJ
+
";)L"
+
OBJ
+
";"
;
private
static
final
String
CLL_SIG
=
"(L"
+
CLS
+
";L"
+
OBJ
+
";)L"
+
OBJ
+
";"
;
/** Name of its super class*/
/** Name of its super class*/
private
static
final
String
superName
=
LF
;
private
static
final
String
superName
=
OBJ
;
/** Name of new class */
/** Name of new class */
private
final
String
className
;
private
final
String
className
;
...
@@ -97,7 +97,7 @@ class InvokerBytecodeGenerator {
...
@@ -97,7 +97,7 @@ class InvokerBytecodeGenerator {
if
(
DUMP_CLASS_FILES
)
{
if
(
DUMP_CLASS_FILES
)
{
className
=
makeDumpableClassName
(
className
);
className
=
makeDumpableClassName
(
className
);
}
}
this
.
className
=
superName
+
"$"
+
className
;
this
.
className
=
LF
+
"$"
+
className
;
this
.
sourceFile
=
"LambdaForm$"
+
className
;
this
.
sourceFile
=
"LambdaForm$"
+
className
;
this
.
lambdaForm
=
lambdaForm
;
this
.
lambdaForm
=
lambdaForm
;
this
.
invokerName
=
invokerName
;
this
.
invokerName
=
invokerName
;
...
...
src/share/classes/java/net/URLClassLoader.java
浏览文件 @
5606a2cd
...
@@ -356,8 +356,9 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
...
@@ -356,8 +356,9 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
protected
Class
<?>
findClass
(
final
String
name
)
protected
Class
<?>
findClass
(
final
String
name
)
throws
ClassNotFoundException
throws
ClassNotFoundException
{
{
final
Class
<?>
result
;
try
{
try
{
re
turn
AccessController
.
doPrivileged
(
re
sult
=
AccessController
.
doPrivileged
(
new
PrivilegedExceptionAction
<
Class
<?>>()
{
new
PrivilegedExceptionAction
<
Class
<?>>()
{
public
Class
<?>
run
()
throws
ClassNotFoundException
{
public
Class
<?>
run
()
throws
ClassNotFoundException
{
String
path
=
name
.
replace
(
'.'
,
'/'
).
concat
(
".class"
);
String
path
=
name
.
replace
(
'.'
,
'/'
).
concat
(
".class"
);
...
@@ -369,13 +370,17 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
...
@@ -369,13 +370,17 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
throw
new
ClassNotFoundException
(
name
,
e
);
throw
new
ClassNotFoundException
(
name
,
e
);
}
}
}
else
{
}
else
{
throw
new
ClassNotFoundException
(
name
)
;
return
null
;
}
}
}
}
},
acc
);
},
acc
);
}
catch
(
java
.
security
.
PrivilegedActionException
pae
)
{
}
catch
(
java
.
security
.
PrivilegedActionException
pae
)
{
throw
(
ClassNotFoundException
)
pae
.
getException
();
throw
(
ClassNotFoundException
)
pae
.
getException
();
}
}
if
(
result
==
null
)
{
throw
new
ClassNotFoundException
(
name
);
}
return
result
;
}
}
/*
/*
...
...
src/share/classes/java/security/KeyPairGenerator.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -33,6 +33,7 @@ import java.security.Provider.Service;
...
@@ -33,6 +33,7 @@ import java.security.Provider.Service;
import
sun.security.jca.*
;
import
sun.security.jca.*
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.util.Debug
;
/**
/**
* The KeyPairGenerator class is used to generate pairs of
* The KeyPairGenerator class is used to generate pairs of
...
@@ -126,6 +127,11 @@ import sun.security.jca.GetInstance.Instance;
...
@@ -126,6 +127,11 @@ import sun.security.jca.GetInstance.Instance;
public
abstract
class
KeyPairGenerator
extends
KeyPairGeneratorSpi
{
public
abstract
class
KeyPairGenerator
extends
KeyPairGeneratorSpi
{
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"keypairgenerator"
);
private
final
String
algorithm
;
private
final
String
algorithm
;
// The provider
// The provider
...
@@ -167,6 +173,12 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
...
@@ -167,6 +173,12 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
kpg
=
new
Delegate
(
spi
,
algorithm
);
kpg
=
new
Delegate
(
spi
,
algorithm
);
}
}
kpg
.
provider
=
instance
.
provider
;
kpg
.
provider
=
instance
.
provider
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyPairGenerator."
+
algorithm
+
" algorithm from: "
+
kpg
.
provider
.
getName
());
}
return
kpg
;
return
kpg
;
}
}
...
@@ -557,6 +569,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
...
@@ -557,6 +569,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
provider
=
instance
.
provider
;
provider
=
instance
.
provider
;
this
.
serviceIterator
=
serviceIterator
;
this
.
serviceIterator
=
serviceIterator
;
initType
=
I_NONE
;
initType
=
I_NONE
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyPairGenerator."
+
algorithm
+
" algorithm from: "
+
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/java/security/KeyStore.java
浏览文件 @
5606a2cd
...
@@ -37,6 +37,8 @@ import javax.crypto.SecretKey;
...
@@ -37,6 +37,8 @@ import javax.crypto.SecretKey;
import
javax.security.auth.DestroyFailedException
;
import
javax.security.auth.DestroyFailedException
;
import
javax.security.auth.callback.*
;
import
javax.security.auth.callback.*
;
import
sun.security.util.Debug
;
/**
/**
* This class represents a storage facility for cryptographic
* This class represents a storage facility for cryptographic
* keys and certificates.
* keys and certificates.
...
@@ -177,6 +179,11 @@ import javax.security.auth.callback.*;
...
@@ -177,6 +179,11 @@ import javax.security.auth.callback.*;
public
class
KeyStore
{
public
class
KeyStore
{
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"keystore"
);
/*
/*
* Constant to lookup in the Security properties file to determine
* Constant to lookup in the Security properties file to determine
* the default keystore type.
* the default keystore type.
...
@@ -801,6 +808,11 @@ public class KeyStore {
...
@@ -801,6 +808,11 @@ public class KeyStore {
this
.
keyStoreSpi
=
keyStoreSpi
;
this
.
keyStoreSpi
=
keyStoreSpi
;
this
.
provider
=
provider
;
this
.
provider
=
provider
;
this
.
type
=
type
;
this
.
type
=
type
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyStore."
+
type
.
toUpperCase
()
+
" type from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/java/security/MessageDigest.java
浏览文件 @
5606a2cd
...
@@ -35,6 +35,8 @@ import java.io.ByteArrayInputStream;
...
@@ -35,6 +35,8 @@ import java.io.ByteArrayInputStream;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
sun.security.util.Debug
;
/**
/**
* This MessageDigest class provides applications the functionality of a
* This MessageDigest class provides applications the functionality of a
* message digest algorithm, such as SHA-1 or SHA-256.
* message digest algorithm, such as SHA-1 or SHA-256.
...
@@ -103,6 +105,11 @@ import java.nio.ByteBuffer;
...
@@ -103,6 +105,11 @@ import java.nio.ByteBuffer;
public
abstract
class
MessageDigest
extends
MessageDigestSpi
{
public
abstract
class
MessageDigest
extends
MessageDigestSpi
{
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"messagedigest"
);
private
String
algorithm
;
private
String
algorithm
;
// The state of this digest
// The state of this digest
...
@@ -156,18 +163,23 @@ public abstract class MessageDigest extends MessageDigestSpi {
...
@@ -156,18 +163,23 @@ public abstract class MessageDigest extends MessageDigestSpi {
public
static
MessageDigest
getInstance
(
String
algorithm
)
public
static
MessageDigest
getInstance
(
String
algorithm
)
throws
NoSuchAlgorithmException
{
throws
NoSuchAlgorithmException
{
try
{
try
{
MessageDigest
md
;
Object
[]
objs
=
Security
.
getImpl
(
algorithm
,
"MessageDigest"
,
Object
[]
objs
=
Security
.
getImpl
(
algorithm
,
"MessageDigest"
,
(
String
)
null
);
(
String
)
null
);
if
(
objs
[
0
]
instanceof
MessageDigest
)
{
if
(
objs
[
0
]
instanceof
MessageDigest
)
{
MessageDigest
md
=
(
MessageDigest
)
objs
[
0
];
md
=
(
MessageDigest
)
objs
[
0
];
md
.
provider
=
(
Provider
)
objs
[
1
];
return
md
;
}
else
{
}
else
{
MessageDigest
delegate
=
md
=
new
Delegate
((
MessageDigestSpi
)
objs
[
0
],
algorithm
);
new
Delegate
((
MessageDigestSpi
)
objs
[
0
],
algorithm
);
}
delegate
.
provider
=
(
Provider
)
objs
[
1
];
md
.
provider
=
(
Provider
)
objs
[
1
];
return
delegate
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"MessageDigest."
+
algorithm
+
" algorithm from: "
+
md
.
provider
.
getName
());
}
}
return
md
;
}
catch
(
NoSuchProviderException
e
)
{
}
catch
(
NoSuchProviderException
e
)
{
throw
new
NoSuchAlgorithmException
(
algorithm
+
" not found"
);
throw
new
NoSuchAlgorithmException
(
algorithm
+
" not found"
);
}
}
...
...
src/share/classes/java/security/SecureRandom.java
浏览文件 @
5606a2cd
...
@@ -32,6 +32,7 @@ import java.security.Provider.Service;
...
@@ -32,6 +32,7 @@ import java.security.Provider.Service;
import
sun.security.jca.*
;
import
sun.security.jca.*
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.util.Debug
;
/**
/**
* This class provides a cryptographically strong random number
* This class provides a cryptographically strong random number
...
@@ -92,6 +93,11 @@ import sun.security.jca.GetInstance.Instance;
...
@@ -92,6 +93,11 @@ import sun.security.jca.GetInstance.Instance;
public
class
SecureRandom
extends
java
.
util
.
Random
{
public
class
SecureRandom
extends
java
.
util
.
Random
{
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"securerandom"
);
/**
/**
* The provider.
* The provider.
*
*
...
@@ -234,6 +240,11 @@ public class SecureRandom extends java.util.Random {
...
@@ -234,6 +240,11 @@ public class SecureRandom extends java.util.Random {
this
.
secureRandomSpi
=
secureRandomSpi
;
this
.
secureRandomSpi
=
secureRandomSpi
;
this
.
provider
=
provider
;
this
.
provider
=
provider
;
this
.
algorithm
=
algorithm
;
this
.
algorithm
=
algorithm
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"SecureRandom."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/java/security/Signature.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1996, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -121,6 +121,11 @@ public abstract class Signature extends SignatureSpi {
...
@@ -121,6 +121,11 @@ public abstract class Signature extends SignatureSpi {
private
static
final
Debug
debug
=
private
static
final
Debug
debug
=
Debug
.
getInstance
(
"jca"
,
"Signature"
);
Debug
.
getInstance
(
"jca"
,
"Signature"
);
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"signature"
);
/*
/*
* The algorithm for this signature object.
* The algorithm for this signature object.
* This value is used to map an OID to the particular algorithm.
* This value is used to map an OID to the particular algorithm.
...
@@ -451,6 +456,11 @@ public abstract class Signature extends SignatureSpi {
...
@@ -451,6 +456,11 @@ public abstract class Signature extends SignatureSpi {
throws
InvalidKeyException
{
throws
InvalidKeyException
{
engineInitVerify
(
publicKey
);
engineInitVerify
(
publicKey
);
state
=
VERIFY
;
state
=
VERIFY
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Signature."
+
algorithm
+
" verification algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -495,6 +505,11 @@ public abstract class Signature extends SignatureSpi {
...
@@ -495,6 +505,11 @@ public abstract class Signature extends SignatureSpi {
PublicKey
publicKey
=
certificate
.
getPublicKey
();
PublicKey
publicKey
=
certificate
.
getPublicKey
();
engineInitVerify
(
publicKey
);
engineInitVerify
(
publicKey
);
state
=
VERIFY
;
state
=
VERIFY
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Signature."
+
algorithm
+
" verification algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -511,6 +526,11 @@ public abstract class Signature extends SignatureSpi {
...
@@ -511,6 +526,11 @@ public abstract class Signature extends SignatureSpi {
throws
InvalidKeyException
{
throws
InvalidKeyException
{
engineInitSign
(
privateKey
);
engineInitSign
(
privateKey
);
state
=
SIGN
;
state
=
SIGN
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Signature."
+
algorithm
+
" signing algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -529,6 +549,11 @@ public abstract class Signature extends SignatureSpi {
...
@@ -529,6 +549,11 @@ public abstract class Signature extends SignatureSpi {
throws
InvalidKeyException
{
throws
InvalidKeyException
{
engineInitSign
(
privateKey
,
random
);
engineInitSign
(
privateKey
,
random
);
state
=
SIGN
;
state
=
SIGN
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Signature."
+
algorithm
+
" signing algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/java/util/concurrent/ForkJoinPool.java
浏览文件 @
5606a2cd
...
@@ -49,6 +49,7 @@ import java.util.concurrent.RejectedExecutionException;
...
@@ -49,6 +49,7 @@ import java.util.concurrent.RejectedExecutionException;
import
java.util.concurrent.RunnableFuture
;
import
java.util.concurrent.RunnableFuture
;
import
java.util.concurrent.ThreadLocalRandom
;
import
java.util.concurrent.ThreadLocalRandom
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicLong
;
import
java.security.AccessControlContext
;
import
java.security.AccessControlContext
;
import
java.security.ProtectionDomain
;
import
java.security.ProtectionDomain
;
import
java.security.Permissions
;
import
java.security.Permissions
;
...
@@ -80,9 +81,9 @@ import java.security.Permissions;
...
@@ -80,9 +81,9 @@ import java.security.Permissions;
*
*
* <p>For applications that require separate or custom pools, a {@code
* <p>For applications that require separate or custom pools, a {@code
* ForkJoinPool} may be constructed with a given target parallelism
* ForkJoinPool} may be constructed with a given target parallelism
* level; by default, equal to the number of available processors.
The
* level; by default, equal to the number of available processors.
*
pool attempts to maintain enough active (or available) threads by
*
The pool attempts to maintain enough active (or available) threads
* dynamically adding, suspending, or resuming internal worker
*
by
dynamically adding, suspending, or resuming internal worker
* threads, even if some tasks are stalled waiting to join others.
* threads, even if some tasks are stalled waiting to join others.
* However, no such adjustments are guaranteed in the face of blocked
* However, no such adjustments are guaranteed in the face of blocked
* I/O or other unmanaged synchronization. The nested {@link
* I/O or other unmanaged synchronization. The nested {@link
...
@@ -178,7 +179,14 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -178,7 +179,14 @@ public class ForkJoinPool extends AbstractExecutorService {
* that may be stolen by other workers. Preference rules give
* that may be stolen by other workers. Preference rules give
* first priority to processing tasks from their own queues (LIFO
* first priority to processing tasks from their own queues (LIFO
* or FIFO, depending on mode), then to randomized FIFO steals of
* or FIFO, depending on mode), then to randomized FIFO steals of
* tasks in other queues.
* tasks in other queues. This framework began as vehicle for
* supporting tree-structured parallelism using work-stealing.
* Over time, its scalability advantages led to extensions and
* changes to better support more diverse usage contexts. Because
* most internal methods and nested classes are interrelated,
* their main rationale and descriptions are presented here;
* individual methods and nested classes contain only brief
* comments about details.
*
*
* WorkQueues
* WorkQueues
* ==========
* ==========
...
@@ -198,201 +206,318 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -198,201 +206,318 @@ public class ForkJoinPool extends AbstractExecutorService {
* (http://research.sun.com/scalable/pubs/index.html) and
* (http://research.sun.com/scalable/pubs/index.html) and
* "Idempotent work stealing" by Michael, Saraswat, and Vechev,
* "Idempotent work stealing" by Michael, Saraswat, and Vechev,
* PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
* PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
* See also "Correct and Efficient Work-Stealing for Weak Memory
* The main differences ultimately stem from GC requirements that
* Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
* we null out taken slots as soon as we can, to maintain as small
* (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
* a footprint as possible even in programs generating huge
* analysis of memory ordering (atomic, volatile etc) issues. The
* numbers of tasks. To accomplish this, we shift the CAS
* main differences ultimately stem from GC requirements that we
* arbitrating pop vs poll (steal) from being on the indices
* null out taken slots as soon as we can, to maintain as small a
* ("base" and "top") to the slots themselves.
* footprint as possible even in programs generating huge numbers
*
* of tasks. To accomplish this, we shift the CAS arbitrating pop
* Adding tasks then takes the form of a classic array push(task):
* vs poll (steal) from being on the indices ("base" and "top") to
* q.array[q.top] = task; ++q.top;
* the slots themselves. So, both a successful pop and poll
*
* mainly entail a CAS of a slot from non-null to null. Because
* (The actual code needs to null-check and size-check the array,
* we rely on CASes of references, we do not need tag bits on base
* properly fence the accesses, and possibly signal waiting
* or top. They are simple ints as used in any circular
* workers to start scanning -- see below.) Both a successful pop
* and poll mainly entail a CAS of a slot from non-null to null.
*
* The pop operation (always performed by owner) is:
* if ((base != top) and
* (the task at top slot is not null) and
* (CAS slot to null))
* decrement top and return task;
*
* And the poll operation (usually by a stealer) is
* if ((base != top) and
* (the task at base slot is not null) and
* (base has not changed) and
* (CAS slot to null))
* increment base and return task;
*
* Because we rely on CASes of references, we do not need tag bits
* on base or top. They are simple ints as used in any circular
* array-based queue (see for example ArrayDeque). Updates to the
* array-based queue (see for example ArrayDeque). Updates to the
* indices must still be ordered in a way that guarantees that top
* indices guarantee that top == base means the queue is empty,
* == base means the queue is empty, but otherwise may err on the
* but otherwise may err on the side of possibly making the queue
* side of possibly making the queue appear nonempty when a push,
* appear nonempty when a push, pop, or poll have not fully
* pop, or poll have not fully committed. Note that this means
* committed. (Method isEmpty() checks the case of a partially
* that the poll operation, considered individually, is not
* completed removal of the last element.) Because of this, the
* wait-free. One thief cannot successfully continue until another
* poll operation, considered individually, is not wait-free. One
* in-progress one (or, if previously empty, a push) completes.
* thief cannot successfully continue until another in-progress
* However, in the aggregate, we ensure at least probabilistic
* one (or, if previously empty, a push) completes. However, in
* the aggregate, we ensure at least probabilistic
* non-blockingness. If an attempted steal fails, a thief always
* non-blockingness. If an attempted steal fails, a thief always
* chooses a different random victim target to try next. So, in
* chooses a different random victim target to try next. So, in
* order for one thief to progress, it suffices for any
* order for one thief to progress, it suffices for any
* in-progress poll or new push on any empty queue to
* in-progress poll or new push on any empty queue to
* complete. (This is why we normally use method pollAt and its
* complete. (This is why we normally use method pollAt and its
* variants that try once at the apparent base index, else
* variants that try once at the apparent base index, else
* consider alternative actions, rather than method poll.)
* consider alternative actions, rather than method poll, which
*
* retries.)
* This approach also enables support of a user mode in which local
*
* task processing is in FIFO, not LIFO order, simply by using
* This approach also enables support of a user mode in which
* poll rather than pop. This can be useful in message-passing
* local task processing is in FIFO, not LIFO order, simply by
* frameworks in which tasks are never joined. However neither
* using poll rather than pop. This can be useful in
* mode considers affinities, loads, cache localities, etc, so
* message-passing frameworks in which tasks are never joined.
* rarely provide the best possible performance on a given
* However neither mode considers affinities, loads, cache
* machine, but portably provide good throughput by averaging over
* localities, etc, so rarely provide the best possible
* these factors. (Further, even if we did try to use such
* performance on a given machine, but portably provide good
* information, we do not usually have a basis for exploiting it.
* throughput by averaging over these factors. Further, even if
* For example, some sets of tasks profit from cache affinities,
* we did try to use such information, we do not usually have a
* but others are harmed by cache pollution effects.)
* basis for exploiting it. For example, some sets of tasks
* profit from cache affinities, but others are harmed by cache
* pollution effects. Additionally, even though it requires
* scanning, long-term throughput is often best using random
* selection rather than directed selection policies, so cheap
* randomization of sufficient quality is used whenever
* applicable. Various Marsaglia XorShifts (some with different
* shift constants) are inlined at use points.
*
*
* WorkQueues are also used in a similar way for tasks submitted
* WorkQueues are also used in a similar way for tasks submitted
* to the pool. We cannot mix these tasks in the same queues used
* to the pool. We cannot mix these tasks in the same queues used
* for work-stealing (this would contaminate lifo/fifo
* by workers. Instead, we randomly associate submission queues
* processing). Instead, we randomly associate submission queues
* with submitting threads, using a form of hashing. The
* with submitting threads, using a form of hashing. The
* ThreadLocalRandom probe value serves as a hash code for
* ThreadLocalRandom probe value serves as a hash code for
* choosing existing queues, and may be randomly repositioned upon
* choosing existing queues, and may be randomly repositioned upon
* contention with other submitters. In essence, submitters act
* contention with other submitters. In essence, submitters act
* like workers except that they are restricted to executing local
* like workers except that they are restricted to executing local
* tasks that they submitted (or in the case of CountedCompleters,
* tasks that they submitted (or in the case of CountedCompleters,
* others with the same root task). However, because most
* others with the same root task). Insertion of tasks in shared
* shared/external queue operations are more expensive than
* internal, and because, at steady state, external submitters
* will compete for CPU with workers, ForkJoinTask.join and
* related methods disable them from repeatedly helping to process
* tasks if all workers are active. Insertion of tasks in shared
* mode requires a lock (mainly to protect in the case of
* mode requires a lock (mainly to protect in the case of
* resizing) but we use only a simple spinlock (using bits in
* resizing) but we use only a simple spinlock (using field
* field qlock), because submitters encountering a busy queue move
* qlock), because submitters encountering a busy queue move on to
* on to try or create other queues -- they block only when
* try or create other queues -- they block only when creating and
* creating and registering new queues.
* registering new queues. Additionally, "qlock" saturates to an
* unlockable value (-1) at shutdown. Unlocking still can be and
* is performed by cheaper ordered writes of "qlock" in successful
* cases, but uses CAS in unsuccessful cases.
*
*
* Management
* Management
* ==========
* ==========
*
*
* The main throughput advantages of work-stealing stem from
* The main throughput advantages of work-stealing stem from
* decentralized control -- workers mostly take tasks from
* decentralized control -- workers mostly take tasks from
* themselves or each other. We cannot negate this in the
* themselves or each other, at rates that can exceed a billion
* implementation of other management responsibilities. The main
* per second. The pool itself creates, activates (enables
* tactic for avoiding bottlenecks is packing nearly all
* scanning for and running tasks), deactivates, blocks, and
* essentially atomic control state into two volatile variables
* terminates threads, all with minimal central information.
* that are by far most often read (not written) as status and
* There are only a few properties that we can globally track or
* consistency checks.
* maintain, so we pack them into a small number of variables,
*
* often maintaining atomicity without blocking or locking.
* Field "ctl" contains 64 bits holding all the information needed
* Nearly all essentially atomic control state is held in two
* to atomically decide to add, inactivate, enqueue (on an event
* volatile variables that are by far most often read (not
* written) as status and consistency checks. (Also, field
* "config" holds unchanging configuration state.)
*
* Field "ctl" contains 64 bits holding information needed to
* atomically decide to add, inactivate, enqueue (on an event
* queue), dequeue, and/or re-activate workers. To enable this
* queue), dequeue, and/or re-activate workers. To enable this
* packing, we restrict maximum parallelism to (1<<15)-1 (which is
* packing, we restrict maximum parallelism to (1<<15)-1 (which is
* far in excess of normal operating range) to allow ids, counts,
* far in excess of normal operating range) to allow ids, counts,
* and their negations (used for thresholding) to fit into 16bit
* and their negations (used for thresholding) to fit into 16bit
* fields.
* subfields.
*
*
* Field "plock" is a form of sequence lock with a saturating
* Field "runState" holds lockable state bits (STARTED, STOP, etc)
* shutdown bit (similarly for per-queue "qlocks"), mainly
* also protecting updates to the workQueues array. When used as
* protecting updates to the workQueues array, as well as to
* a lock, it is normally held only for a few instructions (the
* enable shutdown. When used as a lock, it is normally only very
* only exceptions are one-time array initialization and uncommon
* briefly held, so is nearly always available after at most a
* resizing), so is nearly always available after at most a brief
* brief spin, but we use a monitor-based backup strategy to
* spin. But to be extra-cautious, after spinning, method
* block when needed.
* awaitRunStateLock (called only if an initial CAS fails), uses a
* wait/notify mechanics on a builtin monitor to block when
* (rarely) needed. This would be a terrible idea for a highly
* contended lock, but most pools run without the lock ever
* contending after the spin limit, so this works fine as a more
* conservative alternative. Because we don't otherwise have an
* internal Object to use as a monitor, the "stealCounter" (an
* AtomicLong) is used when available (it too must be lazily
* initialized; see externalSubmit).
*
* Usages of "runState" vs "ctl" interact in only one case:
* deciding to add a worker thread (see tryAddWorker), in which
* case the ctl CAS is performed while the lock is held.
*
*
* Recording WorkQueues. WorkQueues are recorded in the
* Recording WorkQueues. WorkQueues are recorded in the
* "workQueues" array that is created upon first use and expanded
* "workQueues" array. The array is created upon first use (see
* if necessary. Updates to the array while recording new workers
* externalSubmit) and expanded if necessary. Updates to the
* and unrecording terminated ones are protected from each other
* array while recording new workers and unrecording terminated
* by a lock but the array is otherwise concurrently readable, and
* ones are protected from each other by the runState lock, but
* accessed directly. To simplify index-based operations, the
* the array is otherwise concurrently readable, and accessed
* array size is always a power of two, and all readers must
* directly. We also ensure that reads of the array reference
* tolerate null slots. Worker queues are at odd indices. Shared
* itself never become too stale. To simplify index-based
* (submission) queues are at even indices, up to a maximum of 64
* operations, the array size is always a power of two, and all
* slots, to limit growth even if array needs to expand to add
* readers must tolerate null slots. Worker queues are at odd
* more workers. Grouping them together in this way simplifies and
* indices. Shared (submission) queues are at even indices, up to
* speeds up task scanning.
* a maximum of 64 slots, to limit growth even if array needs to
* expand to add more workers. Grouping them together in this way
* simplifies and speeds up task scanning.
*
*
* All worker thread creation is on-demand, triggered by task
* All worker thread creation is on-demand, triggered by task
* submissions, replacement of terminated workers, and/or
* submissions, replacement of terminated workers, and/or
* compensation for blocked workers. However, all other support
* compensation for blocked workers. However, all other support
* code is set up to work with other policies. To ensure that we
* code is set up to work with other policies. To ensure that we
* do not hold on to worker references that would prevent GC, A
LL
* do not hold on to worker references that would prevent GC, A
ll
* accesses to workQueues are via indices into the workQueues
* accesses to workQueues are via indices into the workQueues
* array (which is one source of some of the messy code
* array (which is one source of some of the messy code
* constructions here). In essence, the workQueues array serves as
* constructions here). In essence, the workQueues array serves as
* a weak reference mechanism. Thus for example the wait queue
* a weak reference mechanism. Thus for example the stack top
* field of ctl stores indices, not references. Access to the
* subfield of ctl stores indices, not references.
* workQueues in associated methods (for example signalWork) must
*
* both index-check and null-check the IDs. All such accesses
* Queuing Idle Workers. Unlike HPC work-stealing frameworks, we
* ignore bad IDs by returning out early from what they are doing,
* cannot let workers spin indefinitely scanning for tasks when
* since this can only be associated with termination, in which
* none can be found immediately, and we cannot start/resume
* case it is OK to give up. All uses of the workQueues array
* workers unless there appear to be tasks available. On the
* also check that it is non-null (even if previously
* other hand, we must quickly prod them into action when new
* non-null). This allows nulling during termination, which is
* tasks are submitted or generated. In many usages, ramp-up time
* currently not necessary, but remains an option for
* to activate workers is the main limiting factor in overall
* resource-revocation-based shutdown schemes. It also helps
* performance, which is compounded at program start-up by JIT
* reduce JIT issuance of uncommon-trap code, which tends to
* compilation and allocation. So we streamline this as much as
* unnecessarily complicate control flow in some methods.
* possible.
*
*
* Event Queuing. Unlike HPC work-stealing frameworks, we cannot
* The "ctl" field atomically maintains active and total worker
* let workers spin indefinitely scanning for tasks when none can
* counts as well as a queue to place waiting threads so they can
* be found immediately, and we cannot start/resume workers unless
* be located for signalling. Active counts also play the role of
* there appear to be tasks available. On the other hand, we must
* quiescence indicators, so are decremented when workers believe
* quickly prod them into action when new tasks are submitted or
* that there are no more tasks to execute. The "queue" is
* generated. In many usages, ramp-up time to activate workers is
* actually a form of Treiber stack. A stack is ideal for
* the main limiting factor in overall performance (this is
* activating threads in most-recently used order. This improves
* compounded at program start-up by JIT compilation and
* performance and locality, outweighing the disadvantages of
* allocation). So we try to streamline this as much as possible.
* being prone to contention and inability to release a worker
* We park/unpark workers after placing in an event wait queue
* unless it is topmost on stack. We park/unpark workers after
* when they cannot find work. This "queue" is actually a simple
* pushing on the idle worker stack (represented by the lower
* Treiber stack, headed by the "id" field of ctl, plus a 15bit
* 32bit subfield of ctl) when they cannot find work. The top
* counter value (that reflects the number of times a worker has
* stack state holds the value of the "scanState" field of the
* been inactivated) to avoid ABA effects (we need only as many
* worker: its index and status, plus a version counter that, in
* version numbers as worker threads). Successors are held in
* addition to the count subfields (also serving as version
* field WorkQueue.nextWait. Queuing deals with several intrinsic
* stamps) provide protection against Treiber stack ABA effects.
* races, mainly that a task-producing thread can miss seeing (and
*
* signalling) another thread that gave up looking for work but
* Field scanState is used by both workers and the pool to manage
* has not yet entered the wait queue. We solve this by requiring
* and track whether a worker is INACTIVE (possibly blocked
* a full sweep of all workers (via repeated calls to method
* waiting for a signal), or SCANNING for tasks (when neither hold
* scan()) both before and after a newly waiting worker is added
* it is busy running tasks). When a worker is inactivated, its
* to the wait queue. Because enqueued workers may actually be
* scanState field is set, and is prevented from executing tasks,
* rescanning rather than waiting, we set and clear the "parker"
* even though it must scan once for them to avoid queuing
* races. Note that scanState updates lag queue CAS releases so
* usage requires care. When queued, the lower 16 bits of
* scanState must hold its pool index. So we place the index there
* upon initialization (see registerWorker) and otherwise keep it
* there or restore it when necessary.
*
* Memory ordering. See "Correct and Efficient Work-Stealing for
* Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
* (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
* analysis of memory ordering requirements in work-stealing
* algorithms similar to the one used here. We usually need
* stronger than minimal ordering because we must sometimes signal
* workers, requiring Dekker-like full-fences to avoid lost
* signals. Arranging for enough ordering without expensive
* over-fencing requires tradeoffs among the supported means of
* expressing access constraints. The most central operations,
* taking from queues and updating ctl state, require full-fence
* CAS. Array slots are read using the emulation of volatiles
* provided by Unsafe. Access from other threads to WorkQueue
* base, top, and array requires a volatile load of the first of
* any of these read. We use the convention of declaring the
* "base" index volatile, and always read it before other fields.
* The owner thread must ensure ordered updates, so writes use
* ordered intrinsics unless they can piggyback on those for other
* writes. Similar conventions and rationales hold for other
* WorkQueue fields (such as "currentSteal") that are only written
* by owners but observed by others.
*
* Creating workers. To create a worker, we pre-increment total
* count (serving as a reservation), and attempt to construct a
* ForkJoinWorkerThread via its factory. Upon construction, the
* new thread invokes registerWorker, where it constructs a
* WorkQueue and is assigned an index in the workQueues array
* (expanding the array if necessary). The thread is then
* started. Upon any exception across these steps, or null return
* from factory, deregisterWorker adjusts counts and records
* accordingly. If a null return, the pool continues running with
* fewer than the target number workers. If exceptional, the
* exception is propagated, generally to some external caller.
* Worker index assignment avoids the bias in scanning that would
* occur if entries were sequentially packed starting at the front
* of the workQueues array. We treat the array as a simple
* power-of-two hash table, expanding as needed. The seedIndex
* increment ensures no collisions until a resize is needed or a
* worker is deregistered and replaced, and thereafter keeps
* probability of collision low. We cannot use
* ThreadLocalRandom.getProbe() for similar purposes here because
* the thread has not started yet, but do so for creating
* submission queues for existing external threads.
*
* Deactivation and waiting. Queuing encounters several intrinsic
* races; most notably that a task-producing thread can miss
* seeing (and signalling) another thread that gave up looking for
* work but has not yet entered the wait queue. When a worker
* cannot find a task to steal, it deactivates and enqueues. Very
* often, the lack of tasks is transient due to GC or OS
* scheduling. To reduce false-alarm deactivation, scanners
* compute checksums of queue states during sweeps. (The
* stability checks used here and elsewhere are probabilistic
* variants of snapshot techniques -- see Herlihy & Shavit.)
* Workers give up and try to deactivate only after the sum is
* stable across scans. Further, to avoid missed signals, they
* repeat this scanning process after successful enqueuing until
* again stable. In this state, the worker cannot take/run a task
* it sees until it is released from the queue, so the worker
* itself eventually tries to release itself or any successor (see
* tryRelease). Otherwise, upon an empty scan, a deactivated
* worker uses an adaptive local spin construction (see awaitWork)
* before blocking (via park). Note the unusual conventions about
* Thread.interrupts surrounding parking and other blocking:
* Because interrupts are used solely to alert threads to check
* termination, which is checked anyway upon blocking, we clear
* status (using Thread.interrupted) before any call to park, so
* that park does not immediately return due to status being set
* via some other unrelated call to interrupt in user code.
*
* Signalling and activation. Workers are created or activated
* only when there appears to be at least one task they might be
* able to find and execute. Upon push (either by a worker or an
* external submission) to a previously (possibly) empty queue,
* workers are signalled if idle, or created if fewer exist than
* the given parallelism level. These primary signals are
* buttressed by others whenever other threads remove a task from
* a queue and notice that there are other tasks there as well.
* On most platforms, signalling (unpark) overhead time is
* noticeably long, and the time between signalling a thread and
* it actually making progress can be very noticeably long, so it
* is worth offloading these delays from critical paths as much as
* possible. Also, because inactive workers are often rescanning
* or spinning rather than blocking, we set and clear the "parker"
* field of WorkQueues to reduce unnecessary calls to unpark.
* field of WorkQueues to reduce unnecessary calls to unpark.
* (This requires a secondary recheck to avoid missed signals.)
* (This requires a secondary recheck to avoid missed signals.)
* Note the unusual conventions about Thread.interrupts
* surrounding parking and other blocking: Because interrupts are
* used solely to alert threads to check termination, which is
* checked anyway upon blocking, we clear status (using
* Thread.interrupted) before any call to park, so that park does
* not immediately return due to status being set via some other
* unrelated call to interrupt in user code.
*
* Signalling. We create or wake up workers only when there
* appears to be at least one task they might be able to find and
* execute. When a submission is added or another worker adds a
* task to a queue that has fewer than two tasks, they signal
* waiting workers (or trigger creation of new ones if fewer than
* the given parallelism level -- signalWork). These primary
* signals are buttressed by others whenever other threads remove
* a task from a queue and notice that there are other tasks there
* as well. So in general, pools will be over-signalled. On most
* platforms, signalling (unpark) overhead time is noticeably
* long, and the time between signalling a thread and it actually
* making progress can be very noticeably long, so it is worth
* offloading these delays from critical paths as much as
* possible. Additionally, workers spin-down gradually, by staying
* alive so long as they see the ctl state changing. Similar
* stability-sensing techniques are also used before blocking in
* awaitJoin and helpComplete.
*
*
* Trimming workers. To release resources after periods of lack of
* Trimming workers. To release resources after periods of lack of
* use, a worker starting to wait when the pool is quiescent will
* use, a worker starting to wait when the pool is quiescent will
* time out and terminate if the pool has remained quiescent for a
* time out and terminate (see awaitWork) if the pool has remained
* given period -- a short period if there are more threads than
* quiescent for period IDLE_TIMEOUT, increasing the period as the
* parallelism, longer as the number of threads decreases. This
* number of threads decreases, eventually removing all workers.
* will slowly propagate, eventually terminating all workers after
* Also, when more than two spare threads exist, excess threads
* periods of non-use.
* are immediately terminated at the next quiescent point.
*
* (Padding by two avoids hysteresis.)
* Shutdown and Termination. A call to shutdownNow atomically sets
*
* a plock bit and then (non-atomically) sets each worker's
* Shutdown and Termination. A call to shutdownNow invokes
* qlock status, cancels all unprocessed tasks, and wakes up
* tryTerminate to atomically set a runState bit. The calling
* all waiting workers. Detecting whether termination should
* thread, as well as every other worker thereafter terminating,
* commence after a non-abrupt shutdown() call requires more work
* helps terminate others by setting their (qlock) status,
* and bookkeeping. We need consensus about quiescence (i.e., that
* cancelling their unprocessed tasks, and waking them up, doing
* there is no more work). The active count provides a primary
* so repeatedly until stable (but with a loop bounded by the
* indication but non-abrupt shutdown still requires a rechecking
* number of workers). Calls to non-abrupt shutdown() preface
* scan for any workers that are inactive but not queued.
* this by checking whether termination should commence. This
* relies primarily on the active count bits of "ctl" maintaining
* consensus -- tryTerminate is called from awaitWork whenever
* quiescent. However, external submitters do not take part in
* this consensus. So, tryTerminate sweeps through queues (until
* stable) to ensure lack of in-flight submissions and workers
* about to process them before triggering the "STOP" phase of
* termination. (Note: there is an intrinsic conflict if
* helpQuiescePool is called when shutdown is enabled. Both wait
* for quiescence, but tryTerminate is biased to not trigger until
* helpQuiescePool completes.)
*
*
*
* Joining Tasks
* Joining Tasks
* =============
* =============
...
@@ -403,9 +528,9 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -403,9 +528,9 @@ public class ForkJoinPool extends AbstractExecutorService {
* just let them block (as in Thread.join). We also cannot just
* just let them block (as in Thread.join). We also cannot just
* reassign the joiner's run-time stack with another and replace
* reassign the joiner's run-time stack with another and replace
* it later, which would be a form of "continuation", that even if
* it later, which would be a form of "continuation", that even if
* possible is not necessarily a good idea since we
sometimes need
* possible is not necessarily a good idea since we
may need both
*
both an unblocked task and its continuation to progress.
*
an unblocked task and its continuation to progress. Instead we
*
Instead we
combine two tactics:
* combine two tactics:
*
*
* Helping: Arranging for the joiner to execute some task that it
* Helping: Arranging for the joiner to execute some task that it
* would be running if the steal had not occurred.
* would be running if the steal had not occurred.
...
@@ -425,16 +550,16 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -425,16 +550,16 @@ public class ForkJoinPool extends AbstractExecutorService {
* The ManagedBlocker extension API can't use helping so relies
* The ManagedBlocker extension API can't use helping so relies
* only on compensation in method awaitBlocker.
* only on compensation in method awaitBlocker.
*
*
* The algorithm in
tryHelpStealer entails a form of "linear"
* The algorithm in
helpStealer entails a form of "linear
* helping
:
Each worker records (in field currentSteal) the most
* helping
".
Each worker records (in field currentSteal) the most
* recent task it stole from some other worker
. Plus, it records
* recent task it stole from some other worker
(or a submission).
*
(in field currentJoin) the task it is currently active
ly
*
It also records (in field currentJoin) the task it is current
ly
*
joining. Method tryHelpStealer uses these markers to try to
*
actively joining. Method helpStealer uses these markers to try
*
find a worker to help (i.e., steal back a task from and execute
*
to find a worker to help (i.e., steal back a task from and
*
it) that could hasten completion of the actively joined task.
*
execute it) that could hasten completion of the actively joined
*
In essence, the joiner executes a task that would be on its own
*
task. Thus, the joiner executes a task that would be on its
*
local deque had the to-be-joined task not been stolen. This may
*
own local deque had the to-be-joined task not been stolen. This
*
be seen as a conservative variant of the approach
in Wagner &
*
is a conservative variant of the approach described
in Wagner &
* Calder "Leapfrogging: a portable technique for implementing
* Calder "Leapfrogging: a portable technique for implementing
* efficient futures" SIGPLAN Notices, 1993
* efficient futures" SIGPLAN Notices, 1993
* (http://portal.acm.org/citation.cfm?id=155354). It differs in
* (http://portal.acm.org/citation.cfm?id=155354). It differs in
...
@@ -452,37 +577,40 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -452,37 +577,40 @@ public class ForkJoinPool extends AbstractExecutorService {
* which means that we miss links in the chain during long-lived
* which means that we miss links in the chain during long-lived
* tasks, GC stalls etc (which is OK since blocking in such cases
* tasks, GC stalls etc (which is OK since blocking in such cases
* is usually a good idea). (4) We bound the number of attempts
* is usually a good idea). (4) We bound the number of attempts
* to find work
(see MAX_HELP)
and fall back to suspending the
* to find work
using checksums
and fall back to suspending the
* worker and if necessary replacing it with another.
* worker and if necessary replacing it with another.
*
*
* Helping actions for CountedCompleters are much simpler: Method
* Helping actions for CountedCompleters do not require tracking
* helpComplete can take and execute any task with the same root
* currentJoins: Method helpComplete takes and executes any task
* as the task being waited on. However, this still entails some
* with the same root as the task being waited on (preferring
* traversal of completer chains, so is less efficient than using
* local pops to non-local polls). However, this still entails
* CountedCompleters without explicit joins.
* some traversal of completer chains, so is less efficient than
*
* using CountedCompleters without explicit joins.
* It is impossible to keep exactly the target parallelism number
*
* of threads running at any given time. Determining the
* Compensation does not aim to keep exactly the target
* existence of conservatively safe helping targets, the
* parallelism number of unblocked threads running at any given
* availability of already-created spares, and the apparent need
* time. Some previous versions of this class employed immediate
* to create new spares are all racy, so we rely on multiple
* compensations for any blocked join. However, in practice, the
* retries of each. Compensation in the apparent absence of
* vast majority of blockages are transient byproducts of GC and
* helping opportunities is challenging to control on JVMs, where
* other JVM or OS activities that are made worse by replacement.
* GC and other activities can stall progress of tasks that in
* Currently, compensation is attempted only after validating that
* turn stall out many other dependent tasks, without us being
* all purportedly active threads are processing tasks by checking
* able to determine whether they will ever require compensation.
* field WorkQueue.scanState, which eliminates most false
* Even though work-stealing otherwise encounters little
* positives. Also, compensation is bypassed (tolerating fewer
* degradation in the presence of more threads than cores,
* threads) in the most common case in which it is rarely
* aggressively adding new threads in such cases entails risk of
* beneficial: when a worker with an empty queue (thus no
* unwanted positive feedback control loops in which more threads
* continuation tasks) blocks on a join and there still remain
* cause more dependent stalls (as well as delayed progress of
* enough threads to ensure liveness.
* unblocked threads to the point that we know they are available)
*
* leading to more situations requiring more threads, and so
* The compensation mechanism may be bounded. Bounds for the
* on. This aspect of control can be seen as an (analytically
* commonPool (see commonMaxSpares) better enable JVMs to cope
* intractable) game with an opponent that may choose the worst
* with programming errors and abuse before running out of
* (for us) active thread to stall at any time. We take several
* resources to do so. In other cases, users may supply factories
* precautions to bound losses (and thus bound gains), mainly in
* that limit thread construction. The effects of bounding in this
* methods tryCompensate and awaitJoin.
* pool (like all others) is imprecise. Total worker counts are
* decremented when threads deregister, not when they exit and
* resources are reclaimed by the JVM and OS. So the number of
* simultaneously live threads may transiently exceed bounds.
*
*
* Common Pool
* Common Pool
* ===========
* ===========
...
@@ -492,34 +620,52 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -492,34 +620,52 @@ public class ForkJoinPool extends AbstractExecutorService {
* never be used, we minimize initial construction overhead and
* never be used, we minimize initial construction overhead and
* footprint to the setup of about a dozen fields, with no nested
* footprint to the setup of about a dozen fields, with no nested
* allocation. Most bootstrapping occurs within method
* allocation. Most bootstrapping occurs within method
*
fullExternalPush
during the first submission to the pool.
*
externalSubmit
during the first submission to the pool.
*
*
* When external threads submit to the common pool, they can
* When external threads submit to the common pool, they can
* perform subtask processing (see externalHelp
Join and relate
d
* perform subtask processing (see externalHelp
Complete an
d
*
methods). This caller-helps policy makes it sensible to se
t
*
related methods) upon joins. This caller-helps policy makes i
t
*
common pool parallelism level to one (or more) less than the
*
sensible to set common pool parallelism level to one (or more)
*
total number of available cores, or even zero for pure
*
less than the total number of available cores, or even zero for
* caller-runs. We do not need to record whether external
*
pure
caller-runs. We do not need to record whether external
* submissions are to the common pool -- if not, external
HelpJoin
* submissions are to the common pool -- if not, external
help
*
returns quickly (at the most helping to signal some common pool
*
methods return quickly. These submitters would otherwise be
*
workers). These submitters would otherwise be blocked waiting
*
blocked waiting for completion, so the extra effort (with
*
for completion, so the extra effort (with liberally sprinkled
*
liberally sprinkled task status checks) in inapplicable cases
*
task status checks) in inapplicable cases amounts to an odd
*
amounts to an odd form of limited spin-wait before blocking in
*
form of limited spin-wait before blocking in
ForkJoinTask.join.
* ForkJoinTask.join.
*
*
* As a more appropriate default in managed environments, unless
* As a more appropriate default in managed environments, unless
* overridden by system properties, we use workers of subclass
* overridden by system properties, we use workers of subclass
* InnocuousForkJoinWorkerThread when there is a SecurityManager
* InnocuousForkJoinWorkerThread when there is a SecurityManager
* present. These workers have no permissions set, do not belong
* present. These workers have no permissions set, do not belong
* to any user-defined ThreadGroup, and erase all ThreadLocals
* to any user-defined ThreadGroup, and erase all ThreadLocals
* after executing any top-level task (see WorkQueue.runTask).
The
* after executing any top-level task (see WorkQueue.runTask).
*
associated mechanics (mainly in ForkJoinWorkerThread) may be
*
The associated mechanics (mainly in ForkJoinWorkerThread) may
*
JVM-dependent and must access particular Thread class fields to
*
be JVM-dependent and must access particular Thread class fields
* achieve this effect.
*
to
achieve this effect.
*
*
* Style notes
* Style notes
* ===========
* ===========
*
*
* Memory ordering relies mainly on Unsafe intrinsics that carry
* the further responsibility of explicitly performing null- and
* bounds- checks otherwise carried out implicitly by JVMs. This
* can be awkward and ugly, but also reflects the need to control
* outcomes across the unusual cases that arise in very racy code
* with very few invariants. So these explicit checks would exist
* in some form anyway. All fields are read into locals before
* use, and null-checked if they are references. This is usually
* done in a "C"-like style of listing declarations at the heads
* of methods or blocks, and using inline assignments on first
* encounter. Array bounds-checks are usually performed by
* masking with array.length-1, which relies on the invariant that
* these arrays are created with positive lengths, which is itself
* paranoically checked. Nearly all explicit checks lead to
* bypass/return, not exception throws, because they may
* legitimately arise due to cancellation/revocation during
* shutdown.
*
* There is a lot of representation-level coupling among classes
* There is a lot of representation-level coupling among classes
* ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The
* ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The
* fields of WorkQueue maintain data structures managed by
* fields of WorkQueue maintain data structures managed by
...
@@ -527,22 +673,13 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -527,22 +673,13 @@ public class ForkJoinPool extends AbstractExecutorService {
* trying to reduce this, since any associated future changes in
* trying to reduce this, since any associated future changes in
* representations will need to be accompanied by algorithmic
* representations will need to be accompanied by algorithmic
* changes anyway. Several methods intrinsically sprawl because
* changes anyway. Several methods intrinsically sprawl because
* they must accumulate sets of consistent reads of volatiles held
* they must accumulate sets of consistent reads of fields held in
* in local variables. Methods signalWork() and scan() are the
* local variables. There are also other coding oddities
* main bottlenecks, so are especially heavily
* (including several unnecessary-looking hoisted null checks)
* micro-optimized/mangled. There are lots of inline assignments
* that help some methods perform reasonably even when interpreted
* (of form "while ((local = field) != 0)") which are usually the
* (not compiled).
* simplest way to ensure the required read orderings (which are
*
* sometimes critical). This leads to a "C"-like style of listing
* The order of declarations in this file is (with a few exceptions):
* declarations of these locals at the heads of methods or blocks.
* There are several occurrences of the unusual "do {} while
* (!cas...)" which is the simplest way to force an update of a
* CAS'ed variable. There are also other coding oddities (including
* several unnecessary-looking hoisted null checks) that help
* some methods perform reasonably even when interpreted (not
* compiled).
*
* The order of declarations in this file is:
* (1) Static utility functions
* (1) Static utility functions
* (2) Nested (static) classes
* (2) Nested (static) classes
* (3) Static fields
* (3) Static fields
...
@@ -609,56 +746,37 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -609,56 +746,37 @@ public class ForkJoinPool extends AbstractExecutorService {
public
final
boolean
exec
()
{
return
true
;
}
public
final
boolean
exec
()
{
return
true
;
}
}
}
// Constants shared across ForkJoinPool and WorkQueue
// Bounds
static
final
int
SMASK
=
0xffff
;
// short bits == max index
static
final
int
MAX_CAP
=
0x7fff
;
// max #workers - 1
static
final
int
EVENMASK
=
0xfffe
;
// even short bits
static
final
int
SQMASK
=
0x007e
;
// max 64 (even) slots
// Masks and units for WorkQueue.scanState and ctl sp subfield
static
final
int
SCANNING
=
1
;
// false when running tasks
static
final
int
INACTIVE
=
1
<<
31
;
// must be negative
static
final
int
SS_SEQ
=
1
<<
16
;
// version count
// Mode bits for ForkJoinPool.config and WorkQueue.config
static
final
int
MODE_MASK
=
0xffff
<<
16
;
// top half of int
static
final
int
LIFO_QUEUE
=
0
;
static
final
int
FIFO_QUEUE
=
1
<<
16
;
static
final
int
SHARED_QUEUE
=
1
<<
31
;
// must be negative
/**
/**
* Queues supporting work-stealing as well as external task
* Queues supporting work-stealing as well as external task
* submission. See above for main rationale and algorithms.
* submission. See above for descriptions and algorithms.
* Implementation relies heavily on "Unsafe" intrinsics
* and selective use of "volatile":
*
* Field "base" is the index (mod array.length) of the least valid
* queue slot, which is always the next position to steal (poll)
* from if nonempty. Reads and writes require volatile orderings
* but not CAS, because updates are only performed after slot
* CASes.
*
* Field "top" is the index (mod array.length) of the next queue
* slot to push to or pop from. It is written only by owner thread
* for push, or under lock for external/shared push, and accessed
* by other threads only after reading (volatile) base. Both top
* and base are allowed to wrap around on overflow, but (top -
* base) (or more commonly -(base - top) to force volatile read of
* base before top) still estimates size. The lock ("qlock") is
* forced to -1 on termination, causing all further lock attempts
* to fail. (Note: we don't need CAS for termination state because
* upon pool shutdown, all shared-queues will stop being used
* anyway.) Nearly all lock bodies are set up so that exceptions
* within lock bodies are "impossible" (modulo JVM errors that
* would cause failure anyway.)
*
* The array slots are read and written using the emulation of
* volatiles/atomics provided by Unsafe. Insertions must in
* general use putOrderedObject as a form of releasing store to
* ensure that all writes to the task object are ordered before
* its publication in the queue. All removals entail a CAS to
* null. The array is always a power of two. To ensure safety of
* Unsafe array operations, all accesses perform explicit null
* checks and implicit bounds checks via power-of-two masking.
*
* In addition to basic queuing support, this class contains
* fields described elsewhere to control execution. It turns out
* to work better memory-layout-wise to include them in this class
* rather than a separate class.
*
* Performance on most platforms is very sensitive to placement of
* Performance on most platforms is very sensitive to placement of
* instances of both WorkQueues and their arrays -- we absolutely
* instances of both WorkQueues and their arrays -- we absolutely
* do not want multiple WorkQueue instances or multiple queue
* do not want multiple WorkQueue instances or multiple queue
* arrays sharing cache lines. (It would be best for queue objects
* arrays sharing cache lines. The @Contended annotation alerts
* and their arrays to share, but there is nothing available to
* JVMs to try to keep instances apart.
* help arrange that). The @Contended annotation alerts JVMs to
* try to keep instances apart.
*/
*/
@sun
.
misc
.
Contended
@sun
.
misc
.
Contended
static
final
class
WorkQueue
{
static
final
class
WorkQueue
{
/**
/**
* Capacity of work-stealing queue array upon initialization.
* Capacity of work-stealing queue array upon initialization.
* Must be a power of two; at least 4, but should be larger to
* Must be a power of two; at least 4, but should be larger to
...
@@ -679,13 +797,13 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -679,13 +797,13 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
static
final
int
MAXIMUM_QUEUE_CAPACITY
=
1
<<
26
;
// 64M
static
final
int
MAXIMUM_QUEUE_CAPACITY
=
1
<<
26
;
// 64M
volatile
int
eventCount
;
// encoded inactivation count; < 0 if inactive
// Instance fields
int
nextWait
;
// encoded record of next event waiter
volatile
int
scanState
;
// versioned, <0: inactive; odd:scanning
int
stackPred
;
// pool stack (ctl) predecessor
int
nsteals
;
// number of steals
int
nsteals
;
// number of steals
int
hint
;
// steal index hint
int
hint
;
// randomization and stealer index hint
short
poolIndex
;
// index of this queue in pool
int
config
;
// pool index and mode
final
short
mode
;
// 0: lifo, > 0: fifo, < 0: shared
volatile
int
qlock
;
// 1: locked, < 0: terminate; else 0
volatile
int
qlock
;
// 1: locked, -1: terminate; else 0
volatile
int
base
;
// index of next slot for poll
volatile
int
base
;
// index of next slot for poll
int
top
;
// index of next slot for push
int
top
;
// index of next slot for push
ForkJoinTask
<?>[]
array
;
// the elements (initially unallocated)
ForkJoinTask
<?>[]
array
;
// the elements (initially unallocated)
...
@@ -693,18 +811,22 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -693,18 +811,22 @@ public class ForkJoinPool extends AbstractExecutorService {
final
ForkJoinWorkerThread
owner
;
// owning thread or null if shared
final
ForkJoinWorkerThread
owner
;
// owning thread or null if shared
volatile
Thread
parker
;
// == owner during call to park; else null
volatile
Thread
parker
;
// == owner during call to park; else null
volatile
ForkJoinTask
<?>
currentJoin
;
// task being joined in awaitJoin
volatile
ForkJoinTask
<?>
currentJoin
;
// task being joined in awaitJoin
ForkJoinTask
<?>
currentSteal
;
// current non-local task being executed
volatile
ForkJoinTask
<?>
currentSteal
;
// mainly used by helpStealer
WorkQueue
(
ForkJoinPool
pool
,
ForkJoinWorkerThread
owner
,
int
mode
,
WorkQueue
(
ForkJoinPool
pool
,
ForkJoinWorkerThread
owner
)
{
int
seed
)
{
this
.
pool
=
pool
;
this
.
pool
=
pool
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
this
.
mode
=
(
short
)
mode
;
this
.
hint
=
seed
;
// store initial seed for runWorker
// Place indices in the center of array (that is not yet allocated)
// Place indices in the center of array (that is not yet allocated)
base
=
top
=
INITIAL_QUEUE_CAPACITY
>>>
1
;
base
=
top
=
INITIAL_QUEUE_CAPACITY
>>>
1
;
}
}
/**
* Returns an exportable index (used by ForkJoinWorkerThread).
*/
final
int
getPoolIndex
()
{
return
(
config
&
0xffff
)
>>>
1
;
// ignore odd/even tag bit
}
/**
/**
* Returns the approximate number of tasks in the queue.
* Returns the approximate number of tasks in the queue.
*/
*/
...
@@ -719,12 +841,10 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -719,12 +841,10 @@ public class ForkJoinPool extends AbstractExecutorService {
* near-empty queue has at least one unclaimed task.
* near-empty queue has at least one unclaimed task.
*/
*/
final
boolean
isEmpty
()
{
final
boolean
isEmpty
()
{
ForkJoinTask
<?>[]
a
;
int
m
,
s
;
ForkJoinTask
<?>[]
a
;
int
n
,
m
,
s
;
int
n
=
base
-
(
s
=
top
);
return
((
n
=
base
-
(
s
=
top
))
>=
0
||
return
(
n
>=
0
||
(
n
==
-
1
&&
// possibly one task
(
n
==
-
1
&&
((
a
=
array
)
==
null
||
(
m
=
a
.
length
-
1
)
<
0
||
((
a
=
array
)
==
null
||
(
m
=
a
.
length
-
1
)
<
0
||
U
.
getObject
U
.
getObject
(
a
,
(
long
)((
m
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
)
==
null
)));
(
a
,
(
long
)((
m
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
)
==
null
)));
}
}
...
@@ -738,12 +858,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -738,12 +858,15 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
void
push
(
ForkJoinTask
<?>
task
)
{
final
void
push
(
ForkJoinTask
<?>
task
)
{
ForkJoinTask
<?>[]
a
;
ForkJoinPool
p
;
ForkJoinTask
<?>[]
a
;
ForkJoinPool
p
;
int
s
=
top
,
n
;
int
b
=
base
,
s
=
top
,
n
;
if
((
a
=
array
)
!=
null
)
{
// ignore if queue removed
if
((
a
=
array
)
!=
null
)
{
// ignore if queue removed
int
m
=
a
.
length
-
1
;
int
m
=
a
.
length
-
1
;
// fenced write for task visibility
U
.
putOrderedObject
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
task
);
U
.
putOrderedObject
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
task
);
if
((
n
=
(
top
=
s
+
1
)
-
base
)
<=
2
)
U
.
putOrderedInt
(
this
,
QTOP
,
s
+
1
);
(
p
=
pool
).
signalWork
(
p
.
workQueues
,
this
);
if
((
n
=
s
-
b
)
<=
1
)
{
if
((
p
=
pool
)
!=
null
)
p
.
signalWork
(
p
.
workQueues
,
this
);
}
else
if
(
n
>=
m
)
else
if
(
n
>=
m
)
growArray
();
growArray
();
}
}
...
@@ -764,7 +887,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -764,7 +887,7 @@ public class ForkJoinPool extends AbstractExecutorService {
if
(
oldA
!=
null
&&
(
oldMask
=
oldA
.
length
-
1
)
>=
0
&&
if
(
oldA
!=
null
&&
(
oldMask
=
oldA
.
length
-
1
)
>=
0
&&
(
t
=
top
)
-
(
b
=
base
)
>
0
)
{
(
t
=
top
)
-
(
b
=
base
)
>
0
)
{
int
mask
=
size
-
1
;
int
mask
=
size
-
1
;
do
{
do
{
// emulate poll from old array, push to new array
ForkJoinTask
<?>
x
;
ForkJoinTask
<?>
x
;
int
oldj
=
((
b
&
oldMask
)
<<
ASHIFT
)
+
ABASE
;
int
oldj
=
((
b
&
oldMask
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
((
b
&
mask
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
((
b
&
mask
)
<<
ASHIFT
)
+
ABASE
;
...
@@ -789,7 +912,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -789,7 +912,7 @@ public class ForkJoinPool extends AbstractExecutorService {
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
))
==
null
)
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
))
==
null
)
break
;
break
;
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
top
=
s
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
)
;
return
t
;
return
t
;
}
}
}
}
...
@@ -800,7 +923,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -800,7 +923,7 @@ public class ForkJoinPool extends AbstractExecutorService {
/**
/**
* Takes a task in FIFO order if b is base of queue and a task
* Takes a task in FIFO order if b is base of queue and a task
* can be claimed without contention. Specialized versions
* can be claimed without contention. Specialized versions
* appear in ForkJoinPool methods scan and
tryH
elpStealer.
* appear in ForkJoinPool methods scan and
h
elpStealer.
*/
*/
final
ForkJoinTask
<?>
pollAt
(
int
b
)
{
final
ForkJoinTask
<?>
pollAt
(
int
b
)
{
ForkJoinTask
<?>
t
;
ForkJoinTask
<?>[]
a
;
ForkJoinTask
<?>
t
;
ForkJoinTask
<?>[]
a
;
...
@@ -808,7 +931,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -808,7 +931,7 @@ public class ForkJoinPool extends AbstractExecutorService {
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
))
!=
null
&&
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
))
!=
null
&&
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
)
;
base
=
b
+
1
;
return
t
;
return
t
;
}
}
}
}
...
@@ -823,16 +946,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -823,16 +946,15 @@ public class ForkJoinPool extends AbstractExecutorService {
while
((
b
=
base
)
-
top
<
0
&&
(
a
=
array
)
!=
null
)
{
while
((
b
=
base
)
-
top
<
0
&&
(
a
=
array
)
!=
null
)
{
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
if
(
base
==
b
)
{
if
(
t
!=
null
)
{
if
(
t
!=
null
)
{
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
)
;
base
=
b
+
1
;
return
t
;
return
t
;
}
}
}
}
else
if
(
base
==
b
)
{
else
if
(
b
+
1
==
top
)
// now empty
if
(
b
+
1
==
top
)
break
;
break
;
Thread
.
yield
();
// wait for lagging update (very rare)
}
}
}
}
return
null
;
return
null
;
...
@@ -842,7 +964,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -842,7 +964,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* Takes next task, if one exists, in order specified by mode.
* Takes next task, if one exists, in order specified by mode.
*/
*/
final
ForkJoinTask
<?>
nextLocalTask
()
{
final
ForkJoinTask
<?>
nextLocalTask
()
{
return
mode
==
0
?
pop
()
:
poll
();
return
(
config
&
FIFO_QUEUE
)
==
0
?
pop
()
:
poll
();
}
}
/**
/**
...
@@ -852,7 +974,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -852,7 +974,7 @@ public class ForkJoinPool extends AbstractExecutorService {
ForkJoinTask
<?>[]
a
=
array
;
int
m
;
ForkJoinTask
<?>[]
a
=
array
;
int
m
;
if
(
a
==
null
||
(
m
=
a
.
length
-
1
)
<
0
)
if
(
a
==
null
||
(
m
=
a
.
length
-
1
)
<
0
)
return
null
;
return
null
;
int
i
=
mode
==
0
?
top
-
1
:
base
;
int
i
=
(
config
&
FIFO_QUEUE
)
==
0
?
top
-
1
:
base
;
int
j
=
((
i
&
m
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
((
i
&
m
)
<<
ASHIFT
)
+
ABASE
;
return
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
return
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
}
}
...
@@ -866,7 +988,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -866,7 +988,7 @@ public class ForkJoinPool extends AbstractExecutorService {
if
((
a
=
array
)
!=
null
&&
(
s
=
top
)
!=
base
&&
if
((
a
=
array
)
!=
null
&&
(
s
=
top
)
!=
base
&&
U
.
compareAndSwapObject
U
.
compareAndSwapObject
(
a
,
(((
a
.
length
-
1
)
&
--
s
)
<<
ASHIFT
)
+
ABASE
,
t
,
null
))
{
(
a
,
(((
a
.
length
-
1
)
&
--
s
)
<<
ASHIFT
)
+
ABASE
,
t
,
null
))
{
top
=
s
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
)
;
return
true
;
return
true
;
}
}
return
false
;
return
false
;
...
@@ -876,9 +998,16 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -876,9 +998,16 @@ public class ForkJoinPool extends AbstractExecutorService {
* Removes and cancels all known tasks, ignoring any exceptions.
* Removes and cancels all known tasks, ignoring any exceptions.
*/
*/
final
void
cancelAll
()
{
final
void
cancelAll
()
{
ForkJoinTask
.
cancelIgnoringExceptions
(
currentJoin
);
ForkJoinTask
<?>
t
;
ForkJoinTask
.
cancelIgnoringExceptions
(
currentSteal
);
if
((
t
=
currentJoin
)
!=
null
)
{
for
(
ForkJoinTask
<?>
t
;
(
t
=
poll
())
!=
null
;
)
currentJoin
=
null
;
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
}
if
((
t
=
currentSteal
)
!=
null
)
{
currentSteal
=
null
;
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
}
while
((
t
=
poll
())
!=
null
)
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
}
}
...
@@ -893,167 +1022,186 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -893,167 +1022,186 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
/**
/**
* Executes a top-level task and any local tasks remaining
* Removes and executes all local tasks. If LIFO, invokes
* after execution.
* pollAndExecAll. Otherwise implements a specialized pop loop
* to exec until empty.
*/
*/
final
void
runTask
(
ForkJoinTask
<?>
task
)
{
final
void
execLocalTasks
()
{
if
((
currentSteal
=
task
)
!=
null
)
{
int
b
=
base
,
m
,
s
;
ForkJoinWorkerThread
thread
;
task
.
doExec
();
ForkJoinTask
<?>[]
a
=
array
;
ForkJoinTask
<?>[]
a
=
array
;
int
md
=
mode
;
if
(
b
-
(
s
=
top
-
1
)
<=
0
&&
a
!=
null
&&
++
nsteals
;
(
m
=
a
.
length
-
1
)
>=
0
)
{
currentSteal
=
null
;
if
((
config
&
FIFO_QUEUE
)
==
0
)
{
if
(
md
!=
0
)
for
(
ForkJoinTask
<?>
t
;;)
{
pollAndExecAll
();
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getAndSetObject
else
if
(
a
!=
null
)
{
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
null
))
==
null
)
int
s
,
m
=
a
.
length
-
1
;
break
;
ForkJoinTask
<?>
t
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
);
while
((
s
=
top
-
1
)
-
base
>=
0
&&
(
t
=
(
ForkJoinTask
<?>)
U
.
getAndSetObject
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
null
))
!=
null
)
{
top
=
s
;
t
.
doExec
();
t
.
doExec
();
if
(
base
-
(
s
=
top
-
1
)
>
0
)
break
;
}
}
else
pollAndExecAll
();
}
}
}
}
if
((
thread
=
owner
)
!=
null
)
// no need to do in finally clause
/**
* Executes the given task and any remaining local tasks.
*/
final
void
runTask
(
ForkJoinTask
<?>
task
)
{
if
(
task
!=
null
)
{
scanState
&=
~
SCANNING
;
// mark as busy
(
currentSteal
=
task
).
doExec
();
U
.
putOrderedObject
(
this
,
QCURRENTSTEAL
,
null
);
// release for GC
execLocalTasks
();
ForkJoinWorkerThread
thread
=
owner
;
if
(++
nsteals
<
0
)
// collect on overflow
transferStealCount
(
pool
);
scanState
|=
SCANNING
;
if
(
thread
!=
null
)
thread
.
afterTopLevelExec
();
thread
.
afterTopLevelExec
();
}
}
}
}
/**
* Adds steal count to pool stealCounter if it exists, and resets.
*/
final
void
transferStealCount
(
ForkJoinPool
p
)
{
AtomicLong
sc
;
if
(
p
!=
null
&&
(
sc
=
p
.
stealCounter
)
!=
null
)
{
int
s
=
nsteals
;
nsteals
=
0
;
// if negative, correct for overflow
sc
.
getAndAdd
((
long
)(
s
<
0
?
Integer
.
MAX_VALUE
:
s
));
}
}
/**
/**
* If present, removes from queue and executes the given task,
* If present, removes from queue and executes the given task,
* or any other cancelled task. Returns (true) on any CAS
* or any other cancelled task. Used only by awaitJoin.
* or consistency check failure so caller can retry.
*
*
* @return
false if no progress can be made, else tru
e
* @return
true if queue empty and task not known to be don
e
*/
*/
final
boolean
tryRemoveAndExec
(
ForkJoinTask
<?>
task
)
{
final
boolean
tryRemoveAndExec
(
ForkJoinTask
<?>
task
)
{
boolean
stat
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
b
,
n
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
b
,
n
;
if
(
task
!=
null
&&
(
a
=
array
)
!=
null
&&
(
m
=
a
.
length
-
1
)
>=
0
&&
if
((
a
=
array
)
!=
null
&&
(
m
=
a
.
length
-
1
)
>=
0
&&
(
n
=
(
s
=
top
)
-
(
b
=
base
))
>
0
)
{
task
!=
null
)
{
boolean
removed
=
false
,
empty
=
true
;
while
((
n
=
(
s
=
top
)
-
(
b
=
base
))
>
0
)
{
stat
=
true
;
for
(
ForkJoinTask
<?>
t
;;)
{
// traverse from s to b
for
(
ForkJoinTask
<?>
t
;;)
{
// traverse from s to b
long
j
=
((--
s
&
m
)
<<
ASHIFT
)
+
ABASE
;
long
j
=
((--
s
&
m
)
<<
ASHIFT
)
+
ABASE
;
t
=
(
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
);
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
))
==
null
)
if
(
t
==
null
)
// inconsistent length
return
s
+
1
==
top
;
// shorter than expected
break
;
else
if
(
t
==
task
)
{
else
if
(
t
==
task
)
{
boolean
removed
=
false
;
if
(
s
+
1
==
top
)
{
// pop
if
(
s
+
1
==
top
)
{
// pop
if
(!
U
.
compareAndSwapObject
(
a
,
j
,
task
,
null
))
if
(
U
.
compareAndSwapObject
(
a
,
j
,
task
,
null
))
{
break
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
);
top
=
s
;
removed
=
true
;
removed
=
true
;
}
}
}
else
if
(
base
==
b
)
// replace with proxy
else
if
(
base
==
b
)
// replace with proxy
removed
=
U
.
compareAndSwapObject
(
a
,
j
,
task
,
removed
=
U
.
compareAndSwapObject
(
new
EmptyTask
());
a
,
j
,
task
,
new
EmptyTask
());
if
(
removed
)
task
.
doExec
();
break
;
break
;
}
}
else
if
(
t
.
status
>=
0
)
else
if
(
t
.
status
<
0
&&
s
+
1
==
top
)
{
empty
=
false
;
else
if
(
s
+
1
==
top
)
{
// pop and throw away
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
top
=
s
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
);
break
;
break
;
// was cancelled
}
if
(--
n
==
0
)
{
if
(!
empty
&&
base
==
b
)
stat
=
false
;
break
;
}
}
if
(--
n
==
0
)
return
false
;
}
}
if
(
removed
)
if
(
task
.
status
<
0
)
task
.
doExec
()
;
return
false
;
}
}
else
stat
=
false
;
return
stat
;
}
/**
* Tries to poll for and execute the given task or any other
* task in its CountedCompleter computation.
*/
final
boolean
pollAndExecCC
(
CountedCompleter
<?>
root
)
{
ForkJoinTask
<?>[]
a
;
int
b
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
if
((
b
=
base
)
-
top
<
0
&&
(
a
=
array
)
!=
null
)
{
long
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
((
o
=
U
.
getObjectVolatile
(
a
,
j
))
==
null
)
return
true
;
// retry
if
(
o
instanceof
CountedCompleter
)
{
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
if
(
r
==
root
)
{
if
(
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
);
t
.
doExec
();
}
}
return
true
;
return
true
;
}
}
else
if
((
r
=
r
.
completer
)
==
null
)
break
;
// not part of root computation
}
}
}
return
false
;
}
/**
/**
*
Tries to pop and execute the given task or any other task
*
Pops task if in the same CC computation as the given task,
* in
its CountedCompleter computation
.
* in
either shared or owned mode. Used only by helpComplete
.
*/
*/
final
boolean
externalPopAndExecCC
(
CountedCompleter
<?>
root
)
{
final
CountedCompleter
<?>
popCC
(
CountedCompleter
<?>
task
,
int
mode
)
{
ForkJoinTask
<?>[]
a
;
int
s
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
int
s
;
ForkJoinTask
<?>[]
a
;
Object
o
;
if
(
base
-
(
s
=
top
)
<
0
&&
(
a
=
array
)
!=
null
)
{
if
(
base
-
(
s
=
top
)
<
0
&&
(
a
=
array
)
!=
null
)
{
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
if
((
o
=
U
.
getObject
(
a
,
j
))
instanceof
CountedCompleter
)
{
if
((
o
=
U
.
getObjectVolatile
(
a
,
j
))
!=
null
&&
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
(
o
instanceof
CountedCompleter
))
{
if
(
r
==
root
)
{
CountedCompleter
<?>
t
=
(
CountedCompleter
<?>)
o
;
for
(
CountedCompleter
<?>
r
=
t
;;)
{
if
(
r
==
task
)
{
if
(
mode
<
0
)
{
// must lock
if
(
U
.
compareAndSwapInt
(
this
,
QLOCK
,
0
,
1
))
{
if
(
U
.
compareAndSwapInt
(
this
,
QLOCK
,
0
,
1
))
{
if
(
top
==
s
&&
array
==
a
&&
if
(
top
==
s
&&
array
==
a
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
top
=
s
-
1
;
U
.
putOrderedInt
(
this
,
QTOP
,
s
-
1
)
;
qlock
=
0
;
U
.
putOrderedInt
(
this
,
QLOCK
,
0
)
;
t
.
doExec
()
;
return
t
;
}
}
else
U
.
compareAndSwapInt
(
this
,
QLOCK
,
1
,
0
);
qlock
=
0
;
}
}
return
true
;
}
}
else
if
((
r
=
r
.
completer
)
==
null
)
else
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QTOP
,
s
-
1
);
return
t
;
}
break
;
break
;
}
}
else
if
((
r
=
r
.
completer
)
==
null
)
// try parent
break
;
}
}
}
}
return
false
;
}
return
null
;
}
}
/**
/**
* Internal version
* Steals and runs a task in the same CC computation as the
* given task if one exists and can be taken without
* contention. Otherwise returns a checksum/control value for
* use by method helpComplete.
*
* @return 1 if successful, 2 if retryable (lost to another
* stealer), -1 if non-empty but no matching task found, else
* the base index, forced negative.
*/
*/
final
boolean
internalPopAndExecCC
(
CountedCompleter
<?>
root
)
{
final
int
pollAndExecCC
(
CountedCompleter
<?>
task
)
{
ForkJoinTask
<?>[]
a
;
int
s
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
int
b
,
h
;
ForkJoinTask
<?>[]
a
;
Object
o
;
if
(
base
-
(
s
=
top
)
<
0
&&
(
a
=
array
)
!=
null
)
{
if
((
b
=
base
)
-
top
>=
0
||
(
a
=
array
)
==
null
)
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
h
=
b
|
Integer
.
MIN_VALUE
;
// to sense movement on re-poll
if
((
o
=
U
.
getObject
(
a
,
j
))
instanceof
CountedCompleter
)
{
else
{
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
long
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
(
r
==
root
)
{
if
((
o
=
U
.
getObjectVolatile
(
a
,
j
))
==
null
)
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
h
=
2
;
// retryable
top
=
s
-
1
;
else
if
(!(
o
instanceof
CountedCompleter
))
h
=
-
1
;
// unmatchable
else
{
CountedCompleter
<?>
t
=
(
CountedCompleter
<?>)
o
;
for
(
CountedCompleter
<?>
r
=
t
;;)
{
if
(
r
==
task
)
{
if
(
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
base
=
b
+
1
;
t
.
doExec
();
t
.
doExec
();
h
=
1
;
// success
}
}
return
true
;
else
h
=
2
;
// lost CAS
break
;
}
}
else
if
((
r
=
r
.
completer
)
==
null
)
else
if
((
r
=
r
.
completer
)
==
null
)
{
h
=
-
1
;
// unmatched
break
;
break
;
}
}
}
}
}
}
return
false
;
}
return
h
;
}
}
/**
/**
...
@@ -1061,28 +1209,31 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1061,28 +1209,31 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
boolean
isApparentlyUnblocked
()
{
final
boolean
isApparentlyUnblocked
()
{
Thread
wt
;
Thread
.
State
s
;
Thread
wt
;
Thread
.
State
s
;
return
(
eventCount
>=
0
&&
return
(
scanState
>=
0
&&
(
wt
=
owner
)
!=
null
&&
(
wt
=
owner
)
!=
null
&&
(
s
=
wt
.
getState
())
!=
Thread
.
State
.
BLOCKED
&&
(
s
=
wt
.
getState
())
!=
Thread
.
State
.
BLOCKED
&&
s
!=
Thread
.
State
.
WAITING
&&
s
!=
Thread
.
State
.
WAITING
&&
s
!=
Thread
.
State
.
TIMED_WAITING
);
s
!=
Thread
.
State
.
TIMED_WAITING
);
}
}
// Unsafe mechanics
// Unsafe mechanics
. Note that some are (and must be) the same as in FJP
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
long
QBASE
;
private
static
final
long
QLOCK
;
private
static
final
int
ABASE
;
private
static
final
int
ABASE
;
private
static
final
int
ASHIFT
;
private
static
final
int
ASHIFT
;
private
static
final
long
QTOP
;
private
static
final
long
QLOCK
;
private
static
final
long
QCURRENTSTEAL
;
static
{
static
{
try
{
try
{
U
=
sun
.
misc
.
Unsafe
.
getUnsafe
();
U
=
sun
.
misc
.
Unsafe
.
getUnsafe
();
Class
<?>
k
=
WorkQueue
.
class
;
Class
<?>
w
k
=
WorkQueue
.
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
Q
BASE
=
U
.
objectFieldOffset
Q
TOP
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"base
"
));
(
wk
.
getDeclaredField
(
"top
"
));
QLOCK
=
U
.
objectFieldOffset
QLOCK
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"qlock"
));
(
wk
.
getDeclaredField
(
"qlock"
));
QCURRENTSTEAL
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"currentSteal"
));
ABASE
=
U
.
arrayBaseOffset
(
ak
);
ABASE
=
U
.
arrayBaseOffset
(
ak
);
int
scale
=
U
.
arrayIndexScale
(
ak
);
int
scale
=
U
.
arrayIndexScale
(
ak
);
if
((
scale
&
(
scale
-
1
))
!=
0
)
if
((
scale
&
(
scale
-
1
))
!=
0
)
...
@@ -1125,6 +1276,11 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1125,6 +1276,11 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
static
final
int
commonParallelism
;
static
final
int
commonParallelism
;
/**
* Limit on spare thread construction in tryCompensate.
*/
private
static
int
commonMaxSpares
;
/**
/**
* Sequence number for creating workerNamePrefix.
* Sequence number for creating workerNamePrefix.
*/
*/
...
@@ -1138,7 +1294,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1138,7 +1294,7 @@ public class ForkJoinPool extends AbstractExecutorService {
return
++
poolNumberSequence
;
return
++
poolNumberSequence
;
}
}
// static constants
// static con
figuration con
stants
/**
/**
* Initial timeout value (in nanoseconds) for the thread
* Initial timeout value (in nanoseconds) for the thread
...
@@ -1151,24 +1307,29 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1151,24 +1307,29 @@ public class ForkJoinPool extends AbstractExecutorService {
private
static
final
long
IDLE_TIMEOUT
=
2000L
*
1000L
*
1000L
;
// 2sec
private
static
final
long
IDLE_TIMEOUT
=
2000L
*
1000L
*
1000L
;
// 2sec
/**
/**
* T
imeout value when there are more threads than parallelism level
* T
olerance for idle timeouts, to cope with timer undershoots
*/
*/
private
static
final
long
FAST_IDLE_TIMEOUT
=
200L
*
1000L
*
1000L
;
private
static
final
long
TIMEOUT_SLOP
=
20L
*
1000L
*
1000L
;
// 20ms
/**
/**
* Tolerance for idle timeouts, to cope with timer undershoots
* The initial value for commonMaxSpares during static
* initialization. The value is far in excess of normal
* requirements, but also far short of MAX_CAP and typical
* OS thread limits, so allows JVMs to catch misuse/abuse
* before running out of resources needed to do so.
*/
*/
private
static
final
long
TIMEOUT_SLOP
=
2000000L
;
private
static
final
int
DEFAULT_COMMON_MAX_SPARES
=
256
;
/**
/**
* The maximum stolen->joining link depth allowed in method
* Number of times to spin-wait before blocking. The spins (in
* tryHelpStealer. Must be a power of two. Depths for legitimate
* awaitRunStateLock and awaitWork) currently use randomized
* chains are unbounded, but we use a fixed constant to avoid
* spins. If/when MWAIT-like intrinsics becomes available, they
* (otherwise unchecked) cycles and to bound staleness of
* may allow quieter spinning. The value of SPINS must be a power
* traversal parameters at the expense of sometimes blocking when
* of two, at least 4. The current value causes spinning for a
* we could be helping.
* small fraction of typical context-switch times, well worthwhile
* given the typical likelihoods that blocking is not necessary.
*/
*/
private
static
final
int
MAX_HELP
=
64
;
private
static
final
int
SPINS
=
1
<<
11
;
/**
/**
* Increment for seed generators. See class ThreadLocal for
* Increment for seed generators. See class ThreadLocal for
...
@@ -1177,209 +1338,212 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1177,209 +1338,212 @@ public class ForkJoinPool extends AbstractExecutorService {
private
static
final
int
SEED_INCREMENT
=
0x9e3779b9
;
private
static
final
int
SEED_INCREMENT
=
0x9e3779b9
;
/*
/*
* Bits and masks for control variables
* Bits and masks for field ctl, packed with 4 16 bit subfields:
*
* AC: Number of active running workers minus target parallelism
* Field ctl is a long packed with:
* TC: Number of total workers minus target parallelism
* AC: Number of active running workers minus target parallelism (16 bits)
* SS: version count and status of top waiting thread
* TC: Number of total workers minus target parallelism (16 bits)
* ID: poolIndex of top of Treiber stack of waiters
* ST: true if pool is terminating (1 bit)
*
* EC: the wait count of top waiting thread (15 bits)
* When convenient, we can extract the lower 32 stack top bits
* ID: poolIndex of top of Treiber stack of waiters (16 bits)
* (including version bits) as sp=(int)ctl. The offsets of counts
*
* by the target parallelism and the positionings of fields makes
* When convenient, we can extract the upper 32 bits of counts and
* it possible to perform the most common checks via sign tests of
* the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
* fields: When ac is negative, there are not enough active
* (int)ctl. The ec field is never accessed alone, but always
* workers, when tc is negative, there are not enough total
* together with id and st. The offsets of counts by the target
* workers. When sp is non-zero, there are waiting workers. To
* parallelism and the positionings of fields makes it possible to
* deal with possibly negative fields, we use casts in and out of
* perform the most common checks via sign tests of fields: When
* "short" and/or signed shifts to maintain signedness.
* ac is negative, there are not enough active workers, when tc is
*
* negative, there are not enough total workers, and when e is
* Because it occupies uppermost bits, we can add one active count
* negative, the pool is terminating. To deal with these possibly
* using getAndAddLong of AC_UNIT, rather than CAS, when returning
* negative fields, we use casts in and out of "short" and/or
* from a blocked join. Other updates entail multiple subfields
* signed shifts to maintain signedness.
* and masking, requiring CAS.
*
*/
* When a thread is queued (inactivated), its eventCount field is
* set negative, which is the only way to tell if a worker is
// Lower and upper word masks
* prevented from executing tasks, even though it must continue to
private
static
final
long
SP_MASK
=
0xffffffff
L
;
* scan for them to avoid queuing races. Note however that
private
static
final
long
UC_MASK
=
~
SP_MASK
;
* eventCount updates lag releases so usage requires care.
*
// Active counts
* Field plock is an int packed with:
* SHUTDOWN: true if shutdown is enabled (1 bit)
* SEQ: a sequence lock, with PL_LOCK bit set if locked (30 bits)
* SIGNAL: set when threads may be waiting on the lock (1 bit)
*
* The sequence number enables simple consistency checks:
* Staleness of read-only operations on the workQueues array can
* be checked by comparing plock before vs after the reads.
*/
// bit positions/shifts for fields
private
static
final
int
AC_SHIFT
=
48
;
private
static
final
int
AC_SHIFT
=
48
;
private
static
final
long
AC_UNIT
=
0x0001
L
<<
AC_SHIFT
;
private
static
final
long
AC_MASK
=
0xffff
L
<<
AC_SHIFT
;
// Total counts
private
static
final
int
TC_SHIFT
=
32
;
private
static
final
int
TC_SHIFT
=
32
;
private
static
final
int
ST_SHIFT
=
31
;
private
static
final
long
TC_UNIT
=
0x0001
L
<<
TC_SHIFT
;
private
static
final
int
EC_SHIFT
=
16
;
private
static
final
long
TC_MASK
=
0xffff
L
<<
TC_SHIFT
;
private
static
final
long
ADD_WORKER
=
0x0001
L
<<
(
TC_SHIFT
+
15
);
// sign
// bounds
private
static
final
int
SMASK
=
0xffff
;
// short bits
// runState bits: SHUTDOWN must be negative, others arbitrary powers of two
private
static
final
int
MAX_CAP
=
0x7fff
;
// max #workers - 1
private
static
final
int
RSLOCK
=
1
;
private
static
final
int
EVENMASK
=
0xfffe
;
// even short bits
private
static
final
int
RSIGNAL
=
1
<<
1
;
private
static
final
int
SQMASK
=
0x007e
;
// max 64 (even) slots
private
static
final
int
STARTED
=
1
<<
2
;
private
static
final
int
SHORT_SIGN
=
1
<<
15
;
private
static
final
int
STOP
=
1
<<
29
;
private
static
final
int
INT_SIGN
=
1
<<
31
;
private
static
final
int
TERMINATED
=
1
<<
30
;
// masks
private
static
final
long
STOP_BIT
=
0x0001
L
<<
ST_SHIFT
;
private
static
final
long
AC_MASK
=
((
long
)
SMASK
)
<<
AC_SHIFT
;
private
static
final
long
TC_MASK
=
((
long
)
SMASK
)
<<
TC_SHIFT
;
// units for incrementing and decrementing
private
static
final
long
TC_UNIT
=
1L
<<
TC_SHIFT
;
private
static
final
long
AC_UNIT
=
1L
<<
AC_SHIFT
;
// masks and units for dealing with u = (int)(ctl >>> 32)
private
static
final
int
UAC_SHIFT
=
AC_SHIFT
-
32
;
private
static
final
int
UTC_SHIFT
=
TC_SHIFT
-
32
;
private
static
final
int
UAC_MASK
=
SMASK
<<
UAC_SHIFT
;
private
static
final
int
UTC_MASK
=
SMASK
<<
UTC_SHIFT
;
private
static
final
int
UAC_UNIT
=
1
<<
UAC_SHIFT
;
private
static
final
int
UTC_UNIT
=
1
<<
UTC_SHIFT
;
// masks and units for dealing with e = (int)ctl
private
static
final
int
E_MASK
=
0x7fffffff
;
// no STOP_BIT
private
static
final
int
E_SEQ
=
1
<<
EC_SHIFT
;
// plock bits
private
static
final
int
SHUTDOWN
=
1
<<
31
;
private
static
final
int
SHUTDOWN
=
1
<<
31
;
private
static
final
int
PL_LOCK
=
2
;
private
static
final
int
PL_SIGNAL
=
1
;
private
static
final
int
PL_SPINS
=
1
<<
8
;
// access mode for WorkQueue
static
final
int
LIFO_QUEUE
=
0
;
static
final
int
FIFO_QUEUE
=
1
;
static
final
int
SHARED_QUEUE
=
-
1
;
// Instance fields
// Instance fields
volatile
long
stealCount
;
// collects worker counts
volatile
long
ctl
;
// main pool control
volatile
long
ctl
;
// main pool control
volatile
int
plock
;
// shutdown status and seqLock
volatile
int
runState
;
// lockable status
volatile
int
indexSeed
;
// worker/submitter index seed
final
int
config
;
// parallelism, mode
final
short
parallelism
;
// parallelism level
int
indexSeed
;
// to generate worker index
final
short
mode
;
// LIFO/FIFO
volatile
WorkQueue
[]
workQueues
;
// main registry
WorkQueue
[]
workQueues
;
// main registry
final
ForkJoinWorkerThreadFactory
factory
;
final
ForkJoinWorkerThreadFactory
factory
;
final
UncaughtExceptionHandler
ueh
;
// per-worker UEH
final
UncaughtExceptionHandler
ueh
;
// per-worker UEH
final
String
workerNamePrefix
;
// to create worker name string
final
String
workerNamePrefix
;
// to create worker name string
volatile
AtomicLong
stealCounter
;
// also used as sync monitor
/**
/**
* Acquires the plock lock to protect worker array and related
* Acquires the runState lock; returns current (locked) runState.
* updates. This method is called only if an initial CAS on plock
* fails. This acts as a spinlock for normal cases, but falls back
* to builtin monitor to block when (rarely) needed. This would be
* a terrible idea for a highly contended lock, but works fine as
* a more conservative alternative to a pure spinlock.
*/
*/
private
int
acquirePlock
()
{
private
int
lockRunState
()
{
int
spins
=
PL_SPINS
,
ps
,
nps
;
int
rs
;
for
(;;)
{
return
((((
rs
=
runState
)
&
RSLOCK
)
!=
0
||
if
(((
ps
=
plock
)
&
PL_LOCK
)
==
0
&&
!
U
.
compareAndSwapInt
(
this
,
RUNSTATE
,
rs
,
rs
|=
RSLOCK
))
?
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
=
ps
+
PL_LOCK
))
awaitRunStateLock
()
:
rs
);
return
nps
;
else
if
(
spins
>=
0
)
{
if
(
ThreadLocalRandom
.
nextSecondarySeed
()
>=
0
)
--
spins
;
}
}
else
if
(
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
|
PL_SIGNAL
))
{
synchronized
(
this
)
{
/**
if
((
plock
&
PL_SIGNAL
)
!=
0
)
{
* Spins and/or blocks until runstate lock is available. See
try
{
* above for explanation.
wait
();
*/
}
catch
(
InterruptedException
ie
)
{
private
int
awaitRunStateLock
()
{
Object
lock
;
boolean
wasInterrupted
=
false
;
for
(
int
spins
=
SPINS
,
r
=
0
,
rs
,
ns
;;)
{
if
(((
rs
=
runState
)
&
RSLOCK
)
==
0
)
{
if
(
U
.
compareAndSwapInt
(
this
,
RUNSTATE
,
rs
,
ns
=
rs
|
RSLOCK
))
{
if
(
wasInterrupted
)
{
try
{
try
{
Thread
.
currentThread
().
interrupt
();
Thread
.
currentThread
().
interrupt
();
}
catch
(
SecurityException
ignore
)
{
}
catch
(
SecurityException
ignore
)
{
}
}
}
}
return
ns
;
}
}
else
if
(
r
==
0
)
r
=
ThreadLocalRandom
.
nextSecondarySeed
();
else
if
(
spins
>
0
)
{
r
^=
r
<<
6
;
r
^=
r
>>>
21
;
r
^=
r
<<
7
;
// xorshift
if
(
r
>=
0
)
--
spins
;
}
else
if
((
rs
&
STARTED
)
==
0
||
(
lock
=
stealCounter
)
==
null
)
Thread
.
yield
();
// initialization race
else
if
(
U
.
compareAndSwapInt
(
this
,
RUNSTATE
,
rs
,
rs
|
RSIGNAL
))
{
synchronized
(
lock
)
{
if
((
runState
&
RSIGNAL
)
!=
0
)
{
try
{
lock
.
wait
();
}
catch
(
InterruptedException
ie
)
{
if
(!(
Thread
.
currentThread
()
instanceof
ForkJoinWorkerThread
))
wasInterrupted
=
true
;
}
}
}
else
else
notifyAll
();
lock
.
notifyAll
();
}
}
}
}
}
}
}
}
/**
/**
* Unlocks and signals any thread waiting for plock. Called only
* Unlocks and sets runState to newRunState.
* when CAS of seq value for unlock fails.
*
* @param oldRunState a value returned from lockRunState
* @param newRunState the next value (must have lock bit clear).
*/
*/
private
void
releasePlock
(
int
ps
)
{
private
void
unlockRunState
(
int
oldRunState
,
int
newRunState
)
{
plock
=
ps
;
if
(!
U
.
compareAndSwapInt
(
this
,
RUNSTATE
,
oldRunState
,
newRunState
))
{
synchronized
(
this
)
{
notifyAll
();
}
Object
lock
=
stealCounter
;
runState
=
newRunState
;
// clears RSIGNAL bit
if
(
lock
!=
null
)
synchronized
(
lock
)
{
lock
.
notifyAll
();
}
}
}
}
// Creating, registering and deregistering workers
/**
/**
* Tries to create and start one worker if fewer than target
* Tries to construct and start one worker. Assumes that total
* parallelism level exist. Adjusts counts etc on failure.
* count has already been incremented as a reservation. Invokes
* deregisterWorker on any failure.
*
* @return true if successful
*/
*/
private
void
tryAddWorker
()
{
private
boolean
createWorker
()
{
long
c
;
int
u
,
e
;
ForkJoinWorkerThreadFactory
fac
=
factory
;
while
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
<
0
&&
(
u
&
SHORT_SIGN
)
!=
0
&&
(
e
=
(
int
)
c
)
>=
0
)
{
long
nc
=
((
long
)(((
u
+
UTC_UNIT
)
&
UTC_MASK
)
|
((
u
+
UAC_UNIT
)
&
UAC_MASK
))
<<
32
)
|
(
long
)
e
;
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
ForkJoinWorkerThreadFactory
fac
;
Throwable
ex
=
null
;
Throwable
ex
=
null
;
ForkJoinWorkerThread
wt
=
null
;
ForkJoinWorkerThread
wt
=
null
;
try
{
try
{
if
((
fac
=
factory
)
!=
null
&&
if
(
fac
!=
null
&&
(
wt
=
fac
.
newThread
(
this
))
!=
null
)
{
(
wt
=
fac
.
newThread
(
this
))
!=
null
)
{
wt
.
start
();
wt
.
start
();
break
;
return
true
;
}
}
}
catch
(
Throwable
rex
)
{
}
catch
(
Throwable
rex
)
{
ex
=
rex
;
ex
=
rex
;
}
}
deregisterWorker
(
wt
,
ex
);
deregisterWorker
(
wt
,
ex
);
return
false
;
}
/**
* Tries to add one worker, incrementing ctl counts before doing
* so, relying on createWorker to back out on failure.
*
* @param c incoming ctl value, with total count negative and no
* idle workers. On CAS failure, c is refreshed and retried if
* this holds (otherwise, a new worker is not needed).
*/
private
void
tryAddWorker
(
long
c
)
{
boolean
add
=
false
;
do
{
long
nc
=
((
AC_MASK
&
(
c
+
AC_UNIT
))
|
(
TC_MASK
&
(
c
+
TC_UNIT
)));
if
(
ctl
==
c
)
{
int
rs
,
stop
;
// check if terminating
if
((
stop
=
(
rs
=
lockRunState
())
&
STOP
)
==
0
)
add
=
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
);
unlockRunState
(
rs
,
rs
&
~
RSLOCK
);
if
(
stop
!=
0
)
break
;
if
(
add
)
{
createWorker
();
break
;
break
;
}
}
}
}
}
while
(((
c
=
ctl
)
&
ADD_WORKER
)
!=
0L
&&
(
int
)
c
==
0
);
}
}
// Registering and deregistering workers
/**
/**
* Callback from ForkJoinWorkerThread to establish and record its
* Callback from ForkJoinWorkerThread constructor to establish and
* WorkQueue. To avoid scanning bias due to packing entries in
* record its WorkQueue.
* front of the workQueues array, we treat the array as a simple
* power-of-two hash table using per-thread seed as hash,
* expanding as needed.
*
*
* @param wt the worker thread
* @param wt the worker thread
* @return the worker's queue
* @return the worker's queue
*/
*/
final
WorkQueue
registerWorker
(
ForkJoinWorkerThread
wt
)
{
final
WorkQueue
registerWorker
(
ForkJoinWorkerThread
wt
)
{
UncaughtExceptionHandler
handler
;
WorkQueue
[]
ws
;
int
s
,
ps
;
UncaughtExceptionHandler
handler
;
wt
.
setDaemon
(
true
);
wt
.
setDaemon
(
true
);
// configure thread
if
((
handler
=
ueh
)
!=
null
)
if
((
handler
=
ueh
)
!=
null
)
wt
.
setUncaughtExceptionHandler
(
handler
);
wt
.
setUncaughtExceptionHandler
(
handler
);
do
{}
while
(!
U
.
compareAndSwapInt
(
this
,
INDEXSEED
,
s
=
indexSeed
,
WorkQueue
w
=
new
WorkQueue
(
this
,
wt
);
s
+=
SEED_INCREMENT
)
||
int
i
=
0
;
// assign a pool index
s
==
0
);
// skip 0
int
mode
=
config
&
MODE_MASK
;
WorkQueue
w
=
new
WorkQueue
(
this
,
wt
,
mode
,
s
);
int
rs
=
lockRunState
();
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
int
nps
=
(
ps
&
SHUTDOWN
)
|
((
ps
+
PL_LOCK
)
&
~
SHUTDOWN
);
try
{
try
{
if
((
ws
=
workQueues
)
!=
null
)
{
// skip if shutting down
WorkQueue
[]
ws
;
int
n
;
// skip if no array
int
n
=
ws
.
length
,
m
=
n
-
1
;
if
((
ws
=
workQueues
)
!=
null
&&
(
n
=
ws
.
length
)
>
0
)
{
int
r
=
(
s
<<
1
)
|
1
;
// use odd-numbered indices
int
s
=
indexSeed
+=
SEED_INCREMENT
;
// unlikely to collide
if
(
ws
[
r
&=
m
]
!=
null
)
{
// collision
int
m
=
n
-
1
;
int
probes
=
0
;
// step by approx half size
i
=
((
s
<<
1
)
|
1
)
&
m
;
// odd-numbered indices
if
(
ws
[
i
]
!=
null
)
{
// collision
int
probes
=
0
;
// step by approx half n
int
step
=
(
n
<=
4
)
?
2
:
((
n
>>>
1
)
&
EVENMASK
)
+
2
;
int
step
=
(
n
<=
4
)
?
2
:
((
n
>>>
1
)
&
EVENMASK
)
+
2
;
while
(
ws
[
r
=
(
r
+
step
)
&
m
]
!=
null
)
{
while
(
ws
[
i
=
(
i
+
step
)
&
m
]
!=
null
)
{
if
(++
probes
>=
n
)
{
if
(++
probes
>=
n
)
{
workQueues
=
ws
=
Arrays
.
copyOf
(
ws
,
n
<<=
1
);
workQueues
=
ws
=
Arrays
.
copyOf
(
ws
,
n
<<=
1
);
m
=
n
-
1
;
m
=
n
-
1
;
...
@@ -1387,15 +1551,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1387,15 +1551,15 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
}
}
}
}
w
.
poolIndex
=
(
short
)
r
;
w
.
hint
=
s
;
// use as random seed
w
.
eventCount
=
r
;
// volatile write orders
w
.
config
=
i
|
mode
;
ws
[
r
]
=
w
;
w
.
scanState
=
i
;
// publication fence
ws
[
i
]
=
w
;
}
}
}
finally
{
}
finally
{
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
unlockRunState
(
rs
,
rs
&
~
RSLOCK
);
releasePlock
(
nps
);
}
}
wt
.
setName
(
workerNamePrefix
.
concat
(
Integer
.
toString
(
w
.
poolIndex
>>>
1
)));
wt
.
setName
(
workerNamePrefix
.
concat
(
Integer
.
toString
(
i
>>>
1
)));
return
w
;
return
w
;
}
}
...
@@ -1411,229 +1575,106 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1411,229 +1575,106 @@ public class ForkJoinPool extends AbstractExecutorService {
final
void
deregisterWorker
(
ForkJoinWorkerThread
wt
,
Throwable
ex
)
{
final
void
deregisterWorker
(
ForkJoinWorkerThread
wt
,
Throwable
ex
)
{
WorkQueue
w
=
null
;
WorkQueue
w
=
null
;
if
(
wt
!=
null
&&
(
w
=
wt
.
workQueue
)
!=
null
)
{
if
(
wt
!=
null
&&
(
w
=
wt
.
workQueue
)
!=
null
)
{
int
ps
;
WorkQueue
[]
ws
;
// remove index from array
w
.
qlock
=
-
1
;
// ensure set
int
idx
=
w
.
config
&
SMASK
;
U
.
getAndAddLong
(
this
,
STEALCOUNT
,
w
.
nsteals
);
// collect steals
int
rs
=
lockRunState
();
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
if
((
ws
=
workQueues
)
!=
null
&&
ws
.
length
>
idx
&&
ws
[
idx
]
==
w
)
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
int
nps
=
(
ps
&
SHUTDOWN
)
|
((
ps
+
PL_LOCK
)
&
~
SHUTDOWN
);
try
{
int
idx
=
w
.
poolIndex
;
WorkQueue
[]
ws
=
workQueues
;
if
(
ws
!=
null
&&
idx
>=
0
&&
idx
<
ws
.
length
&&
ws
[
idx
]
==
w
)
ws
[
idx
]
=
null
;
ws
[
idx
]
=
null
;
}
finally
{
unlockRunState
(
rs
,
rs
&
~
RSLOCK
);
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
releasePlock
(
nps
);
}
}
}
long
c
;
// decrement counts
long
c
;
// adjust ctl counts
do
{}
while
(!
U
.
compareAndSwapLong
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
(((
c
-
AC_UNIT
)
&
AC_MASK
)
|
(
this
,
CTL
,
c
=
ctl
,
((
AC_MASK
&
(
c
-
AC_UNIT
))
|
((
c
-
TC_UNIT
)
&
TC_MASK
)
|
(
TC_MASK
&
(
c
-
TC_UNIT
))
|
(
c
&
~(
AC_MASK
|
TC_MASK
)))));
(
SP_MASK
&
c
))));
if
(
w
!=
null
)
{
if
(!
tryTerminate
(
false
,
false
)
&&
w
!=
null
&&
w
.
array
!=
null
)
{
w
.
qlock
=
-
1
;
// ensure set
w
.
transferStealCount
(
this
);
w
.
cancelAll
();
// cancel remaining tasks
w
.
cancelAll
();
// cancel remaining tasks
WorkQueue
[]
ws
;
WorkQueue
v
;
Thread
p
;
int
u
,
i
,
e
;
}
while
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
<
0
&&
(
e
=
(
int
)
c
)
>=
0
)
{
for
(;;)
{
// possibly replace
if
(
e
>
0
)
{
// activate or create replacement
WorkQueue
[]
ws
;
int
m
,
sp
;
if
((
ws
=
workQueues
)
==
null
||
if
(
tryTerminate
(
false
,
false
)
||
w
==
null
||
w
.
array
==
null
||
(
i
=
e
&
SMASK
)
>=
ws
.
length
||
(
runState
&
STOP
)
!=
0
||
(
ws
=
workQueues
)
==
null
||
(
v
=
ws
[
i
])
==
null
)
(
m
=
ws
.
length
-
1
)
<
0
)
// already terminating
break
;
long
nc
=
(((
long
)(
v
.
nextWait
&
E_MASK
))
|
((
long
)(
u
+
UAC_UNIT
)
<<
32
));
if
(
v
.
eventCount
!=
(
e
|
INT_SIGN
))
break
;
break
;
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
if
((
sp
=
(
int
)(
c
=
ctl
))
!=
0
)
{
// wake up replacement
v
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
(
tryRelease
(
c
,
ws
[
sp
&
m
],
AC_UNIT
))
if
((
p
=
v
.
parker
)
!=
null
)
U
.
unpark
(
p
);
break
;
break
;
}
}
}
else
if
(
ex
!=
null
&&
(
c
&
ADD_WORKER
)
!=
0L
)
{
else
{
tryAddWorker
(
c
);
// create replacement
if
((
short
)
u
<
0
)
tryAddWorker
();
break
;
break
;
}
}
else
// don't need replacement
break
;
}
}
}
if
(
ex
==
null
)
// help clean on way out
if
(
ex
==
null
)
// help clean refs on way out
ForkJoinTask
.
helpExpungeStaleExceptions
();
ForkJoinTask
.
helpExpungeStaleExceptions
();
else
// rethrow
else
// rethrow
ForkJoinTask
.
rethrow
(
ex
);
ForkJoinTask
.
rethrow
(
ex
);
}
}
// Submissions
// Signalling
/**
* Unless shutting down, adds the given task to a submission queue
* at submitter's current queue index (modulo submission
* range). Only the most common path is directly handled in this
* method. All others are relayed to fullExternalPush.
*
* @param task the task. Caller must ensure non-null.
*/
final
void
externalPush
(
ForkJoinTask
<?>
task
)
{
WorkQueue
q
;
int
m
,
s
,
n
,
am
;
ForkJoinTask
<?>[]
a
;
int
r
=
ThreadLocalRandom
.
getProbe
();
int
ps
=
plock
;
WorkQueue
[]
ws
=
workQueues
;
if
(
ps
>
0
&&
ws
!=
null
&&
(
m
=
(
ws
.
length
-
1
))
>=
0
&&
(
q
=
ws
[
m
&
r
&
SQMASK
])
!=
null
&&
r
!=
0
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
// lock
if
((
a
=
q
.
array
)
!=
null
&&
(
am
=
a
.
length
-
1
)
>
(
n
=
(
s
=
q
.
top
)
-
q
.
base
))
{
int
j
=
((
am
&
s
)
<<
ASHIFT
)
+
ABASE
;
U
.
putOrderedObject
(
a
,
j
,
task
);
q
.
top
=
s
+
1
;
// push on to deque
q
.
qlock
=
0
;
if
(
n
<=
1
)
signalWork
(
ws
,
q
);
return
;
}
q
.
qlock
=
0
;
}
fullExternalPush
(
task
);
}
/**
* Full version of externalPush. This method is called, among
* other times, upon the first submission of the first task to the
* pool, so must perform secondary initialization. It also
* detects first submission by an external thread by looking up
* its ThreadLocal, and creates a new shared queue if the one at
* index if empty or contended. The plock lock body must be
* exception-free (so no try/finally) so we optimistically
* allocate new queues outside the lock and throw them away if
* (very rarely) not needed.
*
* Secondary initialization occurs when plock is zero, to create
* workQueue array and set plock to a valid value. This lock body
* must also be exception-free. Because the plock seq value can
* eventually wrap around zero, this method harmlessly fails to
* reinitialize if workQueues exists, while still advancing plock.
*/
private
void
fullExternalPush
(
ForkJoinTask
<?>
task
)
{
int
r
;
if
((
r
=
ThreadLocalRandom
.
getProbe
())
==
0
)
{
ThreadLocalRandom
.
localInit
();
r
=
ThreadLocalRandom
.
getProbe
();
}
for
(;;)
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
ps
,
m
,
k
;
boolean
move
=
false
;
if
((
ps
=
plock
)
<
0
)
throw
new
RejectedExecutionException
();
else
if
(
ps
==
0
||
(
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<
0
)
{
// initialize workQueues
int
p
=
parallelism
;
// find power of two table size
int
n
=
(
p
>
1
)
?
p
-
1
:
1
;
// ensure at least 2 slots
n
|=
n
>>>
1
;
n
|=
n
>>>
2
;
n
|=
n
>>>
4
;
n
|=
n
>>>
8
;
n
|=
n
>>>
16
;
n
=
(
n
+
1
)
<<
1
;
WorkQueue
[]
nws
=
((
ws
=
workQueues
)
==
null
||
ws
.
length
==
0
?
new
WorkQueue
[
n
]
:
null
);
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
if
(((
ws
=
workQueues
)
==
null
||
ws
.
length
==
0
)
&&
nws
!=
null
)
workQueues
=
nws
;
int
nps
=
(
ps
&
SHUTDOWN
)
|
((
ps
+
PL_LOCK
)
&
~
SHUTDOWN
);
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
releasePlock
(
nps
);
}
else
if
((
q
=
ws
[
k
=
r
&
m
&
SQMASK
])
!=
null
)
{
if
(
q
.
qlock
==
0
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
ForkJoinTask
<?>[]
a
=
q
.
array
;
int
s
=
q
.
top
;
boolean
submitted
=
false
;
try
{
// locked version of push
if
((
a
!=
null
&&
a
.
length
>
s
+
1
-
q
.
base
)
||
(
a
=
q
.
growArray
())
!=
null
)
{
// must presize
int
j
=
(((
a
.
length
-
1
)
&
s
)
<<
ASHIFT
)
+
ABASE
;
U
.
putOrderedObject
(
a
,
j
,
task
);
q
.
top
=
s
+
1
;
submitted
=
true
;
}
}
finally
{
q
.
qlock
=
0
;
// unlock
}
if
(
submitted
)
{
signalWork
(
ws
,
q
);
return
;
}
}
move
=
true
;
// move on failure
}
else
if
(((
ps
=
plock
)
&
PL_LOCK
)
==
0
)
{
// create new queue
q
=
new
WorkQueue
(
this
,
null
,
SHARED_QUEUE
,
r
);
q
.
poolIndex
=
(
short
)
k
;
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
if
((
ws
=
workQueues
)
!=
null
&&
k
<
ws
.
length
&&
ws
[
k
]
==
null
)
ws
[
k
]
=
q
;
int
nps
=
(
ps
&
SHUTDOWN
)
|
((
ps
+
PL_LOCK
)
&
~
SHUTDOWN
);
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
releasePlock
(
nps
);
}
else
move
=
true
;
// move if busy
if
(
move
)
r
=
ThreadLocalRandom
.
advanceProbe
(
r
);
}
}
// Maintaining ctl counts
/**
* Increments active count; mainly called upon return from blocking.
*/
final
void
incrementActiveCount
()
{
long
c
;
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))));
}
/**
/**
* Tries to create or activate a worker if too few are active.
* Tries to create or activate a worker if too few are active.
*
*
* @param ws the worker array to use to find signallees
* @param ws the worker array to use to find signallees
* @param q
if non-null, the queue holding tasks to be processed
* @param q
a WorkQueue --if non-null, don't retry if now empty
*/
*/
final
void
signalWork
(
WorkQueue
[]
ws
,
WorkQueue
q
)
{
final
void
signalWork
(
WorkQueue
[]
ws
,
WorkQueue
q
)
{
for
(;;)
{
long
c
;
int
sp
,
i
;
WorkQueue
v
;
Thread
p
;
long
c
;
int
e
,
u
,
i
;
WorkQueue
w
;
Thread
p
;
while
((
c
=
ctl
)
<
0L
)
{
// too few active
if
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
>=
0
)
if
((
sp
=
(
int
)
c
)
==
0
)
{
// no idle workers
break
;
if
((
c
&
ADD_WORKER
)
!=
0L
)
// too few workers
if
((
e
=
(
int
)
c
)
<=
0
)
{
tryAddWorker
(
c
);
if
((
short
)
u
<
0
)
tryAddWorker
();
break
;
break
;
}
}
if
(
ws
==
null
||
ws
.
length
<=
(
i
=
e
&
SMASK
)
||
if
(
ws
==
null
)
// unstarted/terminated
(
w
=
ws
[
i
])
==
null
)
break
;
break
;
long
nc
=
(((
long
)(
w
.
nextWait
&
E_MASK
))
|
if
(
ws
.
length
<=
(
i
=
sp
&
SMASK
))
// terminated
((
long
)(
u
+
UAC_UNIT
))
<<
32
);
break
;
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
((
v
=
ws
[
i
])
==
null
)
// terminating
if
(
w
.
eventCount
==
(
e
|
INT_SIGN
)
&&
break
;
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
int
vs
=
(
sp
+
SS_SEQ
)
&
~
INACTIVE
;
// next scanState
w
.
eventCount
=
ne
;
int
d
=
sp
-
v
.
scanState
;
// screen CAS
if
((
p
=
w
.
parker
)
!=
null
)
long
nc
=
(
UC_MASK
&
(
c
+
AC_UNIT
))
|
(
SP_MASK
&
v
.
stackPred
);
if
(
d
==
0
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
v
.
scanState
=
vs
;
// activate v
if
((
p
=
v
.
parker
)
!=
null
)
U
.
unpark
(
p
);
U
.
unpark
(
p
);
break
;
break
;
}
}
if
(
q
!=
null
&&
q
.
base
>=
q
.
top
)
if
(
q
!=
null
&&
q
.
base
==
q
.
top
)
// no more work
break
;
break
;
}
}
}
}
/**
* Signals and releases worker v if it is top of idle worker
* stack. This performs a one-shot version of signalWork only if
* there is (apparently) at least one idle worker.
*
* @param c incoming ctl value
* @param v if non-null, a worker
* @param inc the increment to active count (zero when compensating)
* @return true if successful
*/
private
boolean
tryRelease
(
long
c
,
WorkQueue
v
,
long
inc
)
{
int
sp
=
(
int
)
c
,
vs
=
(
sp
+
SS_SEQ
)
&
~
INACTIVE
;
Thread
p
;
if
(
v
!=
null
&&
v
.
scanState
==
sp
)
{
// v is at top of stack
long
nc
=
(
UC_MASK
&
(
c
+
inc
))
|
(
SP_MASK
&
v
.
stackPred
);
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
v
.
scanState
=
vs
;
if
((
p
=
v
.
parker
)
!=
null
)
U
.
unpark
(
p
);
return
true
;
}
}
return
false
;
}
// Scanning for tasks
// Scanning for tasks
/**
/**
...
@@ -1641,155 +1682,216 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1641,155 +1682,216 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
void
runWorker
(
WorkQueue
w
)
{
final
void
runWorker
(
WorkQueue
w
)
{
w
.
growArray
();
// allocate queue
w
.
growArray
();
// allocate queue
for
(
int
r
=
w
.
hint
;
scan
(
w
,
r
)
==
0
;
)
{
int
seed
=
w
.
hint
;
// initially holds randomization hint
int
r
=
(
seed
==
0
)
?
1
:
seed
;
// avoid 0 for xorShift
for
(
ForkJoinTask
<?>
t
;;)
{
if
((
t
=
scan
(
w
,
r
))
!=
null
)
w
.
runTask
(
t
);
else
if
(!
awaitWork
(
w
,
r
))
break
;
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
r
^=
r
<<
5
;
// xorshift
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
r
^=
r
<<
5
;
// xorshift
}
}
}
}
/**
/**
* Scans for and, if found, runs one task, else possibly
* Scans for and tries to steal a top-level task. Scans start at a
* inactivates the worker. This method operates on single reads of
* random location, randomly moving on apparent contention,
* volatile state and is designed to be re-invoked continuously,
* otherwise continuing linearly until reaching two consecutive
* in part because it returns upon detecting inconsistencies,
* empty passes over all queues with the same checksum (summing
* contention, or state changes that indicate possible success on
* each base index of each queue, that moves on each steal), at
* re-invocation.
* which point the worker tries to inactivate and then re-scans,
*
* attempting to re-activate (itself or some other worker) if
* The scan searches for tasks across queues starting at a random
* finding a task; otherwise returning null to await work. Scans
* index, checking each at least twice. The scan terminates upon
* otherwise touch as little memory as possible, to reduce
* either finding a non-empty queue, or completing the sweep. If
* disruption on other scanning threads.
* the worker is not inactivated, it takes and runs a task from
* this queue. Otherwise, if not activated, it tries to activate
* itself or some other worker by signalling. On failure to find a
* task, returns (for retry) if pool state may have changed during
* an empty scan, or tries to inactivate if active, else possibly
* blocks or terminates via method awaitWork.
*
*
* @param w the worker (via its WorkQueue)
* @param w the worker (via its WorkQueue)
* @param r a random seed
* @param r a random seed
* @return
worker qlock status if would have waited, else 0
* @return
a task, or null if none found
*/
*/
private
final
int
scan
(
WorkQueue
w
,
int
r
)
{
private
ForkJoinTask
<?>
scan
(
WorkQueue
w
,
int
r
)
{
WorkQueue
[]
ws
;
int
m
;
WorkQueue
[]
ws
;
int
m
;
long
c
=
ctl
;
// for consistency check
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>
0
&&
w
!=
null
)
{
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
w
!=
null
)
{
int
ss
=
w
.
scanState
;
// initially non-negative
for
(
int
j
=
m
+
m
+
1
,
ec
=
w
.
eventCount
;;)
{
for
(
int
origin
=
r
&
m
,
k
=
origin
,
oldSum
=
0
,
checkSum
=
0
;;)
{
WorkQueue
q
;
int
b
,
e
;
ForkJoinTask
<?>[]
a
;
ForkJoinTask
<?>
t
;
WorkQueue
q
;
ForkJoinTask
<?>[]
a
;
ForkJoinTask
<?>
t
;
if
((
q
=
ws
[(
r
-
j
)
&
m
])
!=
null
&&
int
b
,
n
;
long
c
;
(
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
a
=
q
.
array
)
!=
null
)
{
if
((
q
=
ws
[
k
])
!=
null
)
{
if
((
n
=
(
b
=
q
.
base
)
-
q
.
top
)
<
0
&&
(
a
=
q
.
array
)
!=
null
)
{
// non-empty
long
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
long
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
((
t
=
((
ForkJoinTask
<?>)
if
((
t
=
((
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
i
)))
!=
null
)
{
U
.
getObjectVolatile
(
a
,
i
)))
!=
null
&&
if
(
ec
<
0
)
q
.
base
==
b
)
{
helpRelease
(
c
,
ws
,
w
,
q
,
b
);
if
(
ss
>=
0
)
{
else
if
(
q
.
base
==
b
&&
if
(
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
q
.
base
=
b
+
1
;
U
.
putOrderedInt
(
q
,
QBASE
,
b
+
1
);
if
(
n
<
-
1
)
// signal others
if
((
b
+
1
)
-
q
.
top
<
0
)
signalWork
(
ws
,
q
);
signalWork
(
ws
,
q
);
w
.
runTask
(
t
)
;
return
t
;
}
}
}
}
break
;
else
if
(
oldSum
==
0
&&
// try to activate
w
.
scanState
<
0
)
tryRelease
(
c
=
ctl
,
ws
[
m
&
(
int
)
c
],
AC_UNIT
);
}
}
else
if
(--
j
<
0
)
{
if
(
ss
<
0
)
// refresh
if
((
ec
|
(
e
=
(
int
)
c
))
<
0
)
// inactive or terminating
ss
=
w
.
scanState
;
return
awaitWork
(
w
,
c
,
ec
);
r
^=
r
<<
1
;
r
^=
r
>>>
3
;
r
^=
r
<<
10
;
else
if
(
ctl
==
c
)
{
// try to inactivate and enqueue
origin
=
k
=
r
&
m
;
// move and rescan
long
nc
=
(
long
)
ec
|
((
c
-
AC_UNIT
)
&
(
AC_MASK
|
TC_MASK
));
oldSum
=
checkSum
=
0
;
w
.
nextWait
=
e
;
continue
;
w
.
eventCount
=
ec
|
INT_SIGN
;
if
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
w
.
eventCount
=
ec
;
// back out
}
}
checkSum
+=
b
;
}
if
((
k
=
(
k
+
1
)
&
m
)
==
origin
)
{
// continue until stable
if
((
ss
>=
0
||
(
ss
==
(
ss
=
w
.
scanState
)))
&&
oldSum
==
(
oldSum
=
checkSum
))
{
if
(
ss
<
0
||
w
.
qlock
<
0
)
// already inactive
break
;
break
;
int
ns
=
ss
|
INACTIVE
;
// try to inactivate
long
nc
=
((
SP_MASK
&
ns
)
|
(
UC_MASK
&
((
c
=
ctl
)
-
AC_UNIT
)));
w
.
stackPred
=
(
int
)
c
;
// hold prev stack top
U
.
putInt
(
w
,
QSCANSTATE
,
ns
);
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
ss
=
ns
;
else
w
.
scanState
=
ss
;
// back out
}
}
checkSum
=
0
;
}
}
}
}
return
0
;
}
return
null
;
}
}
/**
/**
* A continuation of scan(), possibly blocking or terminating
* Possibly blocks worker w waiting for a task to steal, or
* worker w. Returns without blocking if pool state has apparently
* returns false if the worker should terminate. If inactivating
* changed since last invocation. Also, if inactivating w has
* w has caused the pool to become quiescent, checks for pool
* caused the pool to become quiescent, checks for pool
* termination, and, so long as this is not the only worker, waits
* termination, and, so long as this is not the only worker, waits
* for
event for up to a given duration. On timeout, if ctl has
* for
up to a given duration. On timeout, if ctl has not
*
not
changed, terminates the worker, which will in turn wake up
* changed, terminates the worker, which will in turn wake up
* another worker to possibly repeat this process.
* another worker to possibly repeat this process.
*
*
* @param w the calling worker
* @param w the calling worker
* @param c the ctl value on entry to scan
* @param r a random seed (for spins)
* @param ec the worker's eventCount on entry to scan
* @return false if the worker should terminate
*/
*/
private
final
int
awaitWork
(
WorkQueue
w
,
long
c
,
int
ec
)
{
private
boolean
awaitWork
(
WorkQueue
w
,
int
r
)
{
int
stat
,
ns
;
long
parkTime
,
deadline
;
if
(
w
==
null
||
w
.
qlock
<
0
)
// w is terminating
if
((
stat
=
w
.
qlock
)
>=
0
&&
w
.
eventCount
==
ec
&&
ctl
==
c
&&
return
false
;
!
Thread
.
interrupted
())
{
for
(
int
pred
=
w
.
stackPred
,
spins
=
SPINS
,
ss
;;)
{
int
e
=
(
int
)
c
;
if
((
ss
=
w
.
scanState
)
>=
0
)
int
u
=
(
int
)(
c
>>>
32
);
break
;
int
d
=
(
u
>>
UAC_SHIFT
)
+
parallelism
;
// active count
else
if
(
spins
>
0
)
{
r
^=
r
<<
6
;
r
^=
r
>>>
21
;
r
^=
r
<<
7
;
if
(
e
<
0
||
(
d
<=
0
&&
tryTerminate
(
false
,
false
)))
if
(
r
>=
0
&&
--
spins
==
0
)
{
// randomize spins
stat
=
w
.
qlock
=
-
1
;
// pool is terminating
WorkQueue
v
;
WorkQueue
[]
ws
;
int
s
,
j
;
AtomicLong
sc
;
else
if
((
ns
=
w
.
nsteals
)
!=
0
)
{
// collect steals and retry
if
(
pred
!=
0
&&
(
ws
=
workQueues
)
!=
null
&&
w
.
nsteals
=
0
;
(
j
=
pred
&
SMASK
)
<
ws
.
length
&&
U
.
getAndAddLong
(
this
,
STEALCOUNT
,
(
long
)
ns
);
(
v
=
ws
[
j
])
!=
null
&&
// see if pred parking
}
(
v
.
parker
==
null
||
v
.
scanState
>=
0
))
else
{
spins
=
SPINS
;
// continue spinning
long
pc
=
((
d
>
0
||
ec
!=
(
e
|
INT_SIGN
))
?
0L
:
}
((
long
)(
w
.
nextWait
&
E_MASK
))
|
// ctl to restore
}
((
long
)(
u
+
UAC_UNIT
))
<<
32
);
else
if
(
w
.
qlock
<
0
)
// recheck after spins
if
(
pc
!=
0L
)
{
// timed wait if last waiter
return
false
;
int
dc
=
-(
short
)(
c
>>>
TC_SHIFT
);
else
if
(!
Thread
.
interrupted
())
{
parkTime
=
(
dc
<
0
?
FAST_IDLE_TIMEOUT:
long
c
,
prevctl
,
parkTime
,
deadline
;
(
dc
+
1
)
*
IDLE_TIMEOUT
);
int
ac
=
(
int
)((
c
=
ctl
)
>>
AC_SHIFT
)
+
(
config
&
SMASK
);
if
((
ac
<=
0
&&
tryTerminate
(
false
,
false
))
||
(
runState
&
STOP
)
!=
0
)
// pool terminating
return
false
;
if
(
ac
<=
0
&&
ss
==
(
int
)
c
)
{
// is last waiter
prevctl
=
(
UC_MASK
&
(
c
+
AC_UNIT
))
|
(
SP_MASK
&
pred
);
int
t
=
(
short
)(
c
>>>
TC_SHIFT
);
// shrink excess spares
if
(
t
>
2
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
prevctl
))
return
false
;
// else use timed wait
parkTime
=
IDLE_TIMEOUT
*
((
t
>=
0
)
?
1
:
1
-
t
);
deadline
=
System
.
nanoTime
()
+
parkTime
-
TIMEOUT_SLOP
;
deadline
=
System
.
nanoTime
()
+
parkTime
-
TIMEOUT_SLOP
;
}
}
else
else
parkTime
=
deadline
=
0L
;
prevctl
=
parkTime
=
deadline
=
0L
;
if
(
w
.
eventCount
==
ec
&&
ctl
==
c
)
{
Thread
wt
=
Thread
.
currentThread
();
Thread
wt
=
Thread
.
currentThread
();
U
.
putObject
(
wt
,
PARKBLOCKER
,
this
);
U
.
putObject
(
wt
,
PARKBLOCKER
,
this
);
// emulate LockSupport
w
.
parker
=
wt
;
// emulate LockSupport.park
w
.
parker
=
wt
;
if
(
w
.
eventCount
==
ec
&&
ctl
==
c
)
if
(
w
.
scanState
<
0
&&
ctl
==
c
)
// recheck before park
U
.
park
(
false
,
parkTime
);
// must recheck before park
U
.
park
(
false
,
parkTime
);
w
.
parker
=
null
;
U
.
putOrderedObject
(
w
,
QPARKER
,
null
)
;
U
.
putObject
(
wt
,
PARKBLOCKER
,
null
);
U
.
putObject
(
wt
,
PARKBLOCKER
,
null
);
if
(
w
.
scanState
>=
0
)
break
;
if
(
parkTime
!=
0L
&&
ctl
==
c
&&
if
(
parkTime
!=
0L
&&
ctl
==
c
&&
deadline
-
System
.
nanoTime
()
<=
0L
&&
deadline
-
System
.
nanoTime
()
<=
0L
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
pc
))
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
prevctl
))
stat
=
w
.
qlock
=
-
1
;
// shrink pool
return
false
;
// shrink pool
}
}
}
}
}
return
true
;
return
stat
;
}
}
// Joining tasks
/**
/**
* Possibly releases (signals) a worker. Called only from scan()
* Tries to steal and run tasks within the target's computation.
* when a worker with apparently inactive status finds a non-empty
* Uses a variant of the top-level algorithm, restricted to tasks
* queue. This requires revalidating all of the associated state
* with the given task as ancestor: It prefers taking and running
* from caller.
* eligible tasks popped from the worker's own queue (via
* popCC). Otherwise it scans others, randomly moving on
* contention or execution, deciding to give up based on a
* checksum (via return codes frob pollAndExecCC). The maxTasks
* argument supports external usages; internal calls use zero,
* allowing unbounded steps (external calls trap non-positive
* values).
*
* @param w caller
* @param maxTasks if non-zero, the maximum number of other tasks to run
* @return task status on exit
*/
*/
private
final
void
helpRelease
(
long
c
,
WorkQueue
[]
ws
,
WorkQueue
w
,
final
int
helpComplete
(
WorkQueue
w
,
CountedCompleter
<?>
task
,
WorkQueue
q
,
int
b
)
{
int
maxTasks
)
{
WorkQueue
v
;
int
e
,
i
;
Thread
p
;
WorkQueue
[]
ws
;
int
s
=
0
,
m
;
if
(
w
!=
null
&&
w
.
eventCount
<
0
&&
(
e
=
(
int
)
c
)
>
0
&&
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
ws
!=
null
&&
ws
.
length
>
(
i
=
e
&
SMASK
)
&&
task
!=
null
&&
w
!=
null
)
{
(
v
=
ws
[
i
])
!=
null
&&
ctl
==
c
)
{
int
mode
=
w
.
config
;
// for popCC
long
nc
=
(((
long
)(
v
.
nextWait
&
E_MASK
))
|
int
r
=
w
.
hint
^
w
.
top
;
// arbitrary seed for origin
((
long
)((
int
)(
c
>>>
32
)
+
UAC_UNIT
))
<<
32
);
int
origin
=
r
&
m
;
// first queue to scan
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
int
h
=
1
;
// 1:ran, >1:contended, <0:hash
if
(
q
!=
null
&&
q
.
base
==
b
&&
w
.
eventCount
<
0
&&
for
(
int
k
=
origin
,
oldSum
=
0
,
checkSum
=
0
;;)
{
v
.
eventCount
==
(
e
|
INT_SIGN
)
&&
CountedCompleter
<?>
p
;
WorkQueue
q
;
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
if
((
s
=
task
.
status
)
<
0
)
v
.
eventCount
=
ne
;
break
;
if
((
p
=
v
.
parker
)
!=
null
)
if
(
h
==
1
&&
(
p
=
w
.
popCC
(
task
,
mode
))
!=
null
)
{
U
.
unpark
(
p
);
p
.
doExec
();
// run local task
if
(
maxTasks
!=
0
&&
--
maxTasks
==
0
)
break
;
origin
=
k
;
// reset
oldSum
=
checkSum
=
0
;
}
else
{
// poll other queues
if
((
q
=
ws
[
k
])
==
null
)
h
=
0
;
else
if
((
h
=
q
.
pollAndExecCC
(
task
))
<
0
)
checkSum
+=
h
;
if
(
h
>
0
)
{
if
(
h
==
1
&&
maxTasks
!=
0
&&
--
maxTasks
==
0
)
break
;
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
r
^=
r
<<
5
;
// xorshift
origin
=
k
=
r
&
m
;
// move and restart
oldSum
=
checkSum
=
0
;
}
else
if
((
k
=
(
k
+
1
)
&
m
)
==
origin
)
{
if
(
oldSum
==
(
oldSum
=
checkSum
))
break
;
checkSum
=
0
;
}
}
}
}
}
}
}
return
s
;
}
/**
/**
* Tries to locate and execute tasks for a stealer of the given
* Tries to locate and execute tasks for a stealer of the given
...
@@ -1799,268 +1901,167 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1799,268 +1901,167 @@ public class ForkJoinPool extends AbstractExecutorService {
* execute tasks from. The first call to this method upon a
* execute tasks from. The first call to this method upon a
* waiting join will often entail scanning/search, (which is OK
* waiting join will often entail scanning/search, (which is OK
* because the joiner has nothing better to do), but this method
* because the joiner has nothing better to do), but this method
* leaves hints in workers to speed up subsequent calls. The
* leaves hints in workers to speed up subsequent calls.
* implementation is very branchy to cope with potential
* inconsistencies or loops encountering chains that are stale,
* unknown, or so long that they are likely cyclic.
*
*
* @param
joiner the joining work
er
* @param
w call
er
* @param task the task to join
* @param task the task to join
* @return 0 if no progress can be made, negative if task
*/
* known complete, else positive
private
void
helpStealer
(
WorkQueue
w
,
ForkJoinTask
<?>
task
)
{
*/
WorkQueue
[]
ws
=
workQueues
;
private
int
tryHelpStealer
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
int
oldSum
=
0
,
checkSum
,
m
;
int
stat
=
0
,
steps
=
0
;
// bound to avoid cycles
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
w
!=
null
&&
if
(
task
!=
null
&&
joiner
!=
null
&&
task
!=
null
)
{
joiner
.
base
-
joiner
.
top
>=
0
)
{
// hoist checks
do
{
// restart point
restart:
for
(;;)
{
checkSum
=
0
;
// for stability check
ForkJoinTask
<?>
subtask
=
task
;
// current target
ForkJoinTask
<?>
subtask
;
for
(
WorkQueue
j
=
joiner
,
v
;;)
{
// v is stealer of subtask
WorkQueue
j
=
w
,
v
;
// v is subtask stealer
WorkQueue
[]
ws
;
int
m
,
s
,
h
;
descent:
for
(
subtask
=
task
;
subtask
.
status
>=
0
;
)
{
if
((
s
=
task
.
status
)
<
0
)
{
for
(
int
h
=
j
.
hint
|
1
,
k
=
0
,
i
;
;
k
+=
2
)
{
stat
=
s
;
if
(
k
>
m
)
// can't find stealer
break
restart
;
break
descent
;
}
if
((
v
=
ws
[
i
=
(
h
+
k
)
&
m
])
!=
null
)
{
if
((
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<=
0
)
if
(
v
.
currentSteal
==
subtask
)
{
break
restart
;
// shutting down
j
.
hint
=
i
;
if
((
v
=
ws
[
h
=
(
j
.
hint
|
1
)
&
m
])
==
null
||
v
.
currentSteal
!=
subtask
)
{
for
(
int
origin
=
h
;;)
{
// find stealer
if
(((
h
=
(
h
+
2
)
&
m
)
&
15
)
==
1
&&
(
subtask
.
status
<
0
||
j
.
currentJoin
!=
subtask
))
continue
restart
;
// occasional staleness check
if
((
v
=
ws
[
h
])
!=
null
&&
v
.
currentSteal
==
subtask
)
{
j
.
hint
=
h
;
// save hint
break
;
break
;
}
}
if
(
h
==
origin
)
checkSum
+=
v
.
base
;
break
restart
;
// cannot find stealer
}
}
}
}
for
(;;)
{
// help stealer or descend to its stealer
for
(;;)
{
// help v or descend
ForkJoinTask
<?>[]
a
;
int
b
;
ForkJoinTask
<?>[]
a
;
int
b
;
if
(
subtask
.
status
<
0
)
// surround probes with
checkSum
+=
(
b
=
v
.
base
);
continue
restart
;
// consistency checks
ForkJoinTask
<?>
next
=
v
.
currentJoin
;
if
((
b
=
v
.
base
)
-
v
.
top
<
0
&&
(
a
=
v
.
array
)
!=
null
)
{
int
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
ForkJoinTask
<?>
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
i
);
if
(
subtask
.
status
<
0
||
j
.
currentJoin
!=
subtask
||
if
(
subtask
.
status
<
0
||
j
.
currentJoin
!=
subtask
||
v
.
currentSteal
!=
subtask
)
v
.
currentSteal
!=
subtask
)
// stale
continue
restart
;
// stale
break
descent
;
stat
=
1
;
// apparent progress
if
(
b
-
v
.
top
>=
0
||
(
a
=
v
.
array
)
==
null
)
{
if
((
subtask
=
next
)
==
null
)
break
descent
;
j
=
v
;
break
;
}
int
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
ForkJoinTask
<?>
t
=
((
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
i
));
if
(
v
.
base
==
b
)
{
if
(
v
.
base
==
b
)
{
if
(
t
==
null
)
if
(
t
==
null
)
// stale
break
restar
t
;
break
descen
t
;
if
(
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
if
(
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
U
.
putOrderedInt
(
v
,
QBASE
,
b
+
1
)
;
v
.
base
=
b
+
1
;
ForkJoinTask
<?>
ps
=
joiner
.
currentSteal
;
ForkJoinTask
<?>
ps
=
w
.
currentSteal
;
int
jt
=
joiner
.
top
;
int
top
=
w
.
top
;
do
{
do
{
joiner
.
currentSteal
=
t
;
U
.
putOrderedObject
(
w
,
QCURRENTSTEAL
,
t
)
;
t
.
doExec
();
// clear local tasks too
t
.
doExec
();
// clear local tasks too
}
while
(
task
.
status
>=
0
&&
}
while
(
task
.
status
>=
0
&&
joiner
.
top
!=
jt
&&
w
.
top
!=
top
&&
(
t
=
joiner
.
pop
())
!=
null
);
(
t
=
w
.
pop
())
!=
null
);
joiner
.
currentSteal
=
ps
;
U
.
putOrderedObject
(
w
,
QCURRENTSTEAL
,
ps
);
break
restart
;
if
(
w
.
base
!=
w
.
top
)
}
return
;
// can't further help
}
}
else
{
// empty -- try to descend
ForkJoinTask
<?>
next
=
v
.
currentJoin
;
if
(
subtask
.
status
<
0
||
j
.
currentJoin
!=
subtask
||
v
.
currentSteal
!=
subtask
)
continue
restart
;
// stale
else
if
(
next
==
null
||
++
steps
==
MAX_HELP
)
break
restart
;
// dead-end or maybe cyclic
else
{
subtask
=
next
;
j
=
v
;
break
;
}
}
}
}
}
}
}
}
}
while
(
task
.
status
>=
0
&&
oldSum
!=
(
oldSum
=
checkSum
));
}
}
}
}
return
stat
;
}
/**
* Analog of tryHelpStealer for CountedCompleters. Tries to steal
* and run tasks within the target's computation.
*
* @param task the task to join
* @param maxTasks the maximum number of other tasks to run
*/
final
int
helpComplete
(
WorkQueue
joiner
,
CountedCompleter
<?>
task
,
int
maxTasks
)
{
WorkQueue
[]
ws
;
int
m
;
int
s
=
0
;
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
joiner
!=
null
&&
task
!=
null
)
{
int
j
=
joiner
.
poolIndex
;
int
scans
=
m
+
m
+
1
;
long
c
=
0L
;
// for stability check
for
(
int
k
=
scans
;
;
j
+=
2
)
{
WorkQueue
q
;
if
((
s
=
task
.
status
)
<
0
)
break
;
else
if
(
joiner
.
internalPopAndExecCC
(
task
))
{
if
(--
maxTasks
<=
0
)
{
s
=
task
.
status
;
break
;
}
k
=
scans
;
}
else
if
((
s
=
task
.
status
)
<
0
)
break
;
else
if
((
q
=
ws
[
j
&
m
])
!=
null
&&
q
.
pollAndExecCC
(
task
))
{
if
(--
maxTasks
<=
0
)
{
s
=
task
.
status
;
break
;
}
k
=
scans
;
}
else
if
(--
k
<
0
)
{
if
(
c
==
(
c
=
ctl
))
break
;
k
=
scans
;
}
}
}
return
s
;
}
/**
/**
* Tries to decrement active count (sometimes implicitly) and
* Tries to decrement active count (sometimes implicitly) and
* possibly release or create a compensating worker in preparation
* possibly release or create a compensating worker in preparation
* for blocking. Fails on contention or termination. Otherwise,
* for blocking. Returns false (retryable by caller), on
* adds a new thread if no idle workers are available and pool
* contention, detected staleness, instability, or termination.
* may become starved.
*
*
* @param w caller
* @param c the assumed ctl value
*/
*/
private
boolean
tryCompensate
(
WorkQueue
w
)
{
final
boolean
tryCompensate
(
long
c
)
{
boolean
canBlock
;
WorkQueue
[]
ws
=
workQueues
;
WorkQueue
[]
ws
;
long
c
;
int
m
,
pc
,
sp
;
int
pc
=
parallelism
,
e
=
(
int
)
c
,
m
,
tc
;
if
(
w
==
null
||
w
.
qlock
<
0
||
// caller terminating
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
e
>=
0
&&
ctl
==
c
)
{
(
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<=
0
||
WorkQueue
w
=
ws
[
e
&
m
];
(
pc
=
config
&
SMASK
)
==
0
)
// parallelism disabled
if
(
e
!=
0
&&
w
!=
null
)
{
canBlock
=
false
;
Thread
p
;
else
if
((
sp
=
(
int
)(
c
=
ctl
))
!=
0
)
// release idle worker
long
nc
=
((
long
)(
w
.
nextWait
&
E_MASK
)
|
canBlock
=
tryRelease
(
c
,
ws
[
sp
&
m
],
0L
);
(
c
&
(
AC_MASK
|
TC_MASK
)));
else
{
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
int
ac
=
(
int
)(
c
>>
AC_SHIFT
)
+
pc
;
if
(
w
.
eventCount
==
(
e
|
INT_SIGN
)
&&
int
tc
=
(
short
)(
c
>>
TC_SHIFT
)
+
pc
;
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
int
nbusy
=
0
;
// validate saturation
w
.
eventCount
=
ne
;
for
(
int
i
=
0
;
i
<=
m
;
++
i
)
{
// two passes of odd indices
if
((
p
=
w
.
parker
)
!=
null
)
WorkQueue
v
;
U
.
unpark
(
p
);
if
((
v
=
ws
[((
i
<<
1
)
|
1
)
&
m
])
!=
null
)
{
return
true
;
// replace with idle worker
if
((
v
.
scanState
&
SCANNING
)
!=
0
)
}
break
;
}
++
nbusy
;
else
if
((
tc
=
(
short
)(
c
>>>
TC_SHIFT
))
>=
0
&&
(
int
)(
c
>>
AC_SHIFT
)
+
pc
>
1
)
{
long
nc
=
((
c
-
AC_UNIT
)
&
AC_MASK
)
|
(
c
&
~
AC_MASK
);
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
return
true
;
// no compensation
}
else
if
(
tc
+
pc
<
MAX_CAP
)
{
long
nc
=
((
c
+
TC_UNIT
)
&
TC_MASK
)
|
(
c
&
~
TC_MASK
);
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
ForkJoinWorkerThreadFactory
fac
;
Throwable
ex
=
null
;
ForkJoinWorkerThread
wt
=
null
;
try
{
if
((
fac
=
factory
)
!=
null
&&
(
wt
=
fac
.
newThread
(
this
))
!=
null
)
{
wt
.
start
();
return
true
;
}
}
}
catch
(
Throwable
rex
)
{
ex
=
rex
;
}
}
deregisterWorker
(
wt
,
ex
);
// clean up and return false
if
(
nbusy
!=
(
tc
<<
1
)
||
ctl
!=
c
)
canBlock
=
false
;
// unstable or stale
else
if
(
tc
>=
pc
&&
ac
>
1
&&
w
.
isEmpty
())
{
long
nc
=
((
AC_MASK
&
(
c
-
AC_UNIT
))
|
(~
AC_MASK
&
c
));
// uncompensated
canBlock
=
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
);
}
}
else
if
(
tc
>=
MAX_CAP
||
(
this
==
common
&&
tc
>=
pc
+
commonMaxSpares
))
throw
new
RejectedExecutionException
(
"Thread limit exceeded replacing blocked worker"
);
else
{
// similar to tryAddWorker
boolean
add
=
false
;
int
rs
;
// CAS within lock
long
nc
=
((
AC_MASK
&
c
)
|
(
TC_MASK
&
(
c
+
TC_UNIT
)));
if
(((
rs
=
lockRunState
())
&
STOP
)
==
0
)
add
=
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
);
unlockRunState
(
rs
,
rs
&
~
RSLOCK
);
canBlock
=
add
&&
createWorker
();
// throws on exception
}
}
}
}
return
false
;
return
canBlock
;
}
}
/**
/**
* Helps and/or blocks until the given task is done.
* Helps and/or blocks until the given task is done
or timeout
.
*
*
* @param
joiner the joining work
er
* @param
w call
er
* @param task the task
* @param task the task
* @param deadline for timed waits, if nonzero
* @return task status on exit
* @return task status on exit
*/
*/
final
int
awaitJoin
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
final
int
awaitJoin
(
WorkQueue
w
,
ForkJoinTask
<?>
task
,
long
deadline
)
{
int
s
=
0
;
int
s
=
0
;
if
(
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
&&
joiner
!=
null
)
{
if
(
task
!=
null
&&
w
!=
null
)
{
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
ForkJoinTask
<?>
prevJoin
=
w
.
currentJoin
;
joiner
.
currentJoin
=
task
;
U
.
putOrderedObject
(
w
,
QCURRENTJOIN
,
task
);
do
{}
while
(
joiner
.
tryRemoveAndExec
(
task
)
&&
// process local tasks
CountedCompleter
<?>
cc
=
(
task
instanceof
CountedCompleter
)
?
(
s
=
task
.
status
)
>=
0
);
(
CountedCompleter
<?>)
task
:
null
;
if
(
s
>=
0
&&
(
task
instanceof
CountedCompleter
))
for
(;;)
{
s
=
helpComplete
(
joiner
,
(
CountedCompleter
<?>)
task
,
Integer
.
MAX_VALUE
);
if
((
s
=
task
.
status
)
<
0
)
long
cc
=
0
;
// for stability checks
break
;
while
(
s
>=
0
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
cc
!=
null
)
if
((
s
=
tryHelpStealer
(
joiner
,
task
))
==
0
&&
helpComplete
(
w
,
cc
,
0
);
(
s
=
task
.
status
)
>=
0
)
{
else
if
(
w
.
base
==
w
.
top
||
w
.
tryRemoveAndExec
(
task
))
if
(!
tryCompensate
(
cc
))
helpStealer
(
w
,
task
);
cc
=
ctl
;
if
((
s
=
task
.
status
)
<
0
)
else
{
break
;
if
(
task
.
trySetSignal
()
&&
(
s
=
task
.
status
)
>=
0
)
{
long
ms
,
ns
;
synchronized
(
task
)
{
if
(
deadline
==
0L
)
if
(
task
.
status
>=
0
)
{
ms
=
0L
;
try
{
// see ForkJoinTask
else
if
((
ns
=
deadline
-
System
.
nanoTime
())
<=
0L
)
task
.
wait
();
// for explanation
break
;
}
catch
(
InterruptedException
ie
)
{
else
if
((
ms
=
TimeUnit
.
NANOSECONDS
.
toMillis
(
ns
))
<=
0L
)
}
ms
=
1L
;
}
if
(
tryCompensate
(
w
))
{
else
task
.
internalWait
(
ms
);
task
.
notifyAll
();
U
.
getAndAddLong
(
this
,
CTL
,
AC_UNIT
);
}
}
long
c
;
// reactivate
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))));
}
}
}
}
}
joiner
.
currentJoin
=
prevJoin
;
U
.
putOrderedObject
(
w
,
QCURRENTJOIN
,
prevJoin
)
;
}
}
return
s
;
return
s
;
}
}
/**
// Specialized scanning
* Stripped-down variant of awaitJoin used by timed joins. Tries
* to help join only while there is continuous progress. (Caller
* will then enter a timed wait.)
*
* @param joiner the joining worker
* @param task the task
*/
final
void
helpJoinOnce
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
int
s
;
if
(
joiner
!=
null
&&
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
)
{
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
joiner
.
currentJoin
=
task
;
do
{}
while
(
joiner
.
tryRemoveAndExec
(
task
)
&&
// process local tasks
(
s
=
task
.
status
)
>=
0
);
if
(
s
>=
0
)
{
if
(
task
instanceof
CountedCompleter
)
helpComplete
(
joiner
,
(
CountedCompleter
<?>)
task
,
Integer
.
MAX_VALUE
);
do
{}
while
(
task
.
status
>=
0
&&
tryHelpStealer
(
joiner
,
task
)
>
0
);
}
joiner
.
currentJoin
=
prevJoin
;
}
}
/**
/**
* Returns a (probably) non-empty steal queue, if one is found
* Returns a (probably) non-empty steal queue, if one is found
...
@@ -2068,19 +2069,24 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2068,19 +2069,24 @@ public class ForkJoinPool extends AbstractExecutorService {
* caller if, by the time it tries to use the queue, it is empty.
* caller if, by the time it tries to use the queue, it is empty.
*/
*/
private
WorkQueue
findNonEmptyStealQueue
()
{
private
WorkQueue
findNonEmptyStealQueue
()
{
WorkQueue
[]
ws
;
int
m
;
// one-shot version of scan loop
int
r
=
ThreadLocalRandom
.
nextSecondarySeed
();
int
r
=
ThreadLocalRandom
.
nextSecondarySeed
();
for
(;;)
{
int
ps
=
plock
,
m
;
WorkQueue
[]
ws
;
WorkQueue
q
;
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
for
(
int
j
=
(
m
+
1
)
<<
2
;
j
>=
0
;
--
j
)
{
for
(
int
origin
=
r
&
m
,
k
=
origin
,
oldSum
=
0
,
checkSum
=
0
;;)
{
if
((
q
=
ws
[(((
r
-
j
)
<<
1
)
|
1
)
&
m
])
!=
null
&&
WorkQueue
q
;
int
b
;
q
.
base
-
q
.
top
<
0
)
if
((
q
=
ws
[
k
])
!=
null
)
{
if
((
b
=
q
.
base
)
-
q
.
top
<
0
)
return
q
;
return
q
;
checkSum
+=
b
;
}
if
((
k
=
(
k
+
1
)
&
m
)
==
origin
)
{
if
(
oldSum
==
(
oldSum
=
checkSum
))
break
;
checkSum
=
0
;
}
}
}
}
if
(
plock
==
ps
)
return
null
;
}
}
return
null
;
}
}
/**
/**
...
@@ -2090,35 +2096,34 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2090,35 +2096,34 @@ public class ForkJoinPool extends AbstractExecutorService {
* find tasks either.
* find tasks either.
*/
*/
final
void
helpQuiescePool
(
WorkQueue
w
)
{
final
void
helpQuiescePool
(
WorkQueue
w
)
{
ForkJoinTask
<?>
ps
=
w
.
currentSteal
;
ForkJoinTask
<?>
ps
=
w
.
currentSteal
;
// save context
for
(
boolean
active
=
true
;;)
{
for
(
boolean
active
=
true
;;)
{
long
c
;
WorkQueue
q
;
ForkJoinTask
<?>
t
;
int
b
;
long
c
;
WorkQueue
q
;
ForkJoinTask
<?>
t
;
int
b
;
while
((
t
=
w
.
nextLocalTask
())
!=
null
)
w
.
execLocalTasks
();
// run locals before each scan
t
.
doExec
();
if
((
q
=
findNonEmptyStealQueue
())
!=
null
)
{
if
((
q
=
findNonEmptyStealQueue
())
!=
null
)
{
if
(!
active
)
{
// re-establish active count
if
(!
active
)
{
// re-establish active count
active
=
true
;
active
=
true
;
do
{}
while
(!
U
.
compareAndSwapLong
U
.
getAndAddLong
(
this
,
CTL
,
AC_UNIT
);
(
this
,
CTL
,
c
=
ctl
,
}
((
c
&
~
AC_MASK
)
|
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
{
((
c
&
AC_MASK
)
+
AC_UNIT
))));
U
.
putOrderedObject
(
w
,
QCURRENTSTEAL
,
t
);
t
.
doExec
();
if
(++
w
.
nsteals
<
0
)
w
.
transferStealCount
(
this
);
}
}
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
w
.
runTask
(
t
);
}
}
else
if
(
active
)
{
// decrement active count without queuing
else
if
(
active
)
{
// decrement active count without queuing
long
nc
=
(
(
c
=
ctl
)
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
-
AC_UNIT
);
long
nc
=
(
AC_MASK
&
((
c
=
ctl
)
-
AC_UNIT
))
|
(~
AC_MASK
&
c
);
if
((
int
)(
nc
>>
AC_SHIFT
)
+
parallelism
=
=
0
)
if
((
int
)(
nc
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
<
=
0
)
break
;
// bypass decrement-then-increment
break
;
// bypass decrement-then-increment
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
active
=
false
;
active
=
false
;
}
}
else
if
((
int
)((
c
=
ctl
)
>>
AC_SHIFT
)
+
parallelism
<=
0
&&
else
if
((
int
)((
c
=
ctl
)
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
<=
0
&&
U
.
compareAndSwapLong
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
c
+
AC_UNIT
))
(
this
,
CTL
,
c
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))))
break
;
break
;
}
}
U
.
putOrderedObject
(
w
,
QCURRENTSTEAL
,
ps
);
}
}
/**
/**
...
@@ -2141,7 +2146,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2141,7 +2146,7 @@ public class ForkJoinPool extends AbstractExecutorService {
/**
/**
* Returns a cheap heuristic guide for task partitioning when
* Returns a cheap heuristic guide for task partitioning when
* programmers, frameworks, tools, or languages have little or no
* programmers, frameworks, tools, or languages have little or no
* idea about task granularity. In essence by offering this
* idea about task granularity. In essence
,
by offering this
* method, we ask users only about tradeoffs in overhead vs
* method, we ask users only about tradeoffs in overhead vs
* expected throughput and its variance, rather than how finely to
* expected throughput and its variance, rather than how finely to
* partition tasks.
* partition tasks.
...
@@ -2179,15 +2184,12 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2179,15 +2184,12 @@ public class ForkJoinPool extends AbstractExecutorService {
* many of these by further considering the number of "idle"
* many of these by further considering the number of "idle"
* threads, that are known to have zero queued tasks, so
* threads, that are known to have zero queued tasks, so
* compensate by a factor of (#idle/#active) threads.
* compensate by a factor of (#idle/#active) threads.
*
* Note: The approximation of #busy workers as #active workers is
* not very good under current signalling scheme, and should be
* improved.
*/
*/
static
int
getSurplusQueuedTaskCount
()
{
static
int
getSurplusQueuedTaskCount
()
{
Thread
t
;
ForkJoinWorkerThread
wt
;
ForkJoinPool
pool
;
WorkQueue
q
;
Thread
t
;
ForkJoinWorkerThread
wt
;
ForkJoinPool
pool
;
WorkQueue
q
;
if
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
))
{
if
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
))
{
int
p
=
(
pool
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
).
parallelism
;
int
p
=
(
pool
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
).
config
&
SMASK
;
int
n
=
(
q
=
wt
.
workQueue
).
top
-
q
.
base
;
int
n
=
(
q
=
wt
.
workQueue
).
top
-
q
.
base
;
int
a
=
(
int
)(
pool
.
ctl
>>
AC_SHIFT
)
+
p
;
int
a
=
(
int
)(
pool
.
ctl
>>
AC_SHIFT
)
+
p
;
return
n
-
(
a
>
(
p
>>>=
1
)
?
0
:
return
n
-
(
a
>
(
p
>>>=
1
)
?
0
:
...
@@ -2202,13 +2204,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2202,13 +2204,7 @@ public class ForkJoinPool extends AbstractExecutorService {
// Termination
// Termination
/**
/**
* Possibly initiates and/or completes termination. The caller
* Possibly initiates and/or completes termination.
* triggering termination runs three passes through workQueues:
* (0) Setting termination status, followed by wakeups of queued
* workers; (1) cancelling all tasks; (2) interrupting lagging
* threads (likely in external tasks, but possibly also blocked in
* joins). Each pass repeats previous steps because of potential
* lagging thread creation.
*
*
* @param now if true, unconditionally terminate, else only
* @param now if true, unconditionally terminate, else only
* if no work and no active workers
* if no work and no active workers
...
@@ -2216,166 +2212,256 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2216,166 +2212,256 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return true if now terminating or terminated
* @return true if now terminating or terminated
*/
*/
private
boolean
tryTerminate
(
boolean
now
,
boolean
enable
)
{
private
boolean
tryTerminate
(
boolean
now
,
boolean
enable
)
{
int
p
s
;
int
r
s
;
if
(
this
==
common
)
// cannot shut down
if
(
this
==
common
)
// cannot shut down
return
false
;
return
false
;
if
((
ps
=
plock
)
>=
0
)
{
// enable by setting plock
if
((
rs
=
runState
)
>=
0
)
{
if
(!
enable
)
if
(!
enable
)
return
false
;
return
false
;
if
((
ps
&
PL_LOCK
)
!=
0
||
rs
=
lockRunState
();
// enter SHUTDOWN phase
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
unlockRunState
(
rs
,
(
rs
&
~
RSLOCK
)
|
SHUTDOWN
);
ps
=
acquirePlock
();
int
nps
=
((
ps
+
PL_LOCK
)
&
~
SHUTDOWN
)
|
SHUTDOWN
;
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
releasePlock
(
nps
);
}
for
(
long
c
;;)
{
if
(((
c
=
ctl
)
&
STOP_BIT
)
!=
0
)
{
// already terminating
if
((
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
<=
0
)
{
synchronized
(
this
)
{
notifyAll
();
// signal when 0 workers
}
}
if
((
rs
&
STOP
)
==
0
)
{
if
(!
now
)
{
// check quiescence
for
(
long
oldSum
=
0L
;;)
{
// repeat until stable
WorkQueue
[]
ws
;
WorkQueue
w
;
int
m
,
b
;
long
c
;
long
checkSum
=
ctl
;
if
((
int
)(
checkSum
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
>
0
)
return
false
;
// still active workers
if
((
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<=
0
)
break
;
// check queues
for
(
int
i
=
0
;
i
<=
m
;
++
i
)
{
if
((
w
=
ws
[
i
])
!=
null
)
{
if
((
b
=
w
.
base
)
!=
w
.
top
||
w
.
scanState
>=
0
||
w
.
currentSteal
!=
null
)
{
tryRelease
(
c
=
ctl
,
ws
[
m
&
(
int
)
c
],
AC_UNIT
);
return
false
;
// arrange for recheck
}
}
return
true
;
checkSum
+=
b
;
if
((
i
&
1
)
==
0
)
w
.
qlock
=
-
1
;
// try to disable external
}
}
if
(!
now
)
{
// check if idle & no tasks
}
WorkQueue
[]
ws
;
WorkQueue
w
;
if
(
oldSum
==
(
oldSum
=
checkSum
))
if
((
int
)(
c
>>
AC_SHIFT
)
+
parallelism
>
0
)
break
;
return
false
;
if
((
ws
=
workQueues
)
!=
null
)
{
for
(
int
i
=
0
;
i
<
ws
.
length
;
++
i
)
{
if
((
w
=
ws
[
i
])
!=
null
&&
(!
w
.
isEmpty
()
||
((
i
&
1
)
!=
0
&&
w
.
eventCount
>=
0
)))
{
signalWork
(
ws
,
w
);
return
false
;
}
}
}
}
if
((
runState
&
STOP
)
==
0
)
{
rs
=
lockRunState
();
// enter STOP phase
unlockRunState
(
rs
,
(
rs
&
~
RSLOCK
)
|
STOP
);
}
}
}
}
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
c
|
STOP_BIT
))
{
for
(
int
pass
=
0
;
pass
<
3
;
++
pass
)
{
int
pass
=
0
;
// 3 passes to help terminate
WorkQueue
[]
ws
;
WorkQueue
w
;
Thread
wt
;
for
(
long
oldSum
=
0L
;;)
{
// or until done or stable
if
((
ws
=
workQueues
)
!=
null
)
{
WorkQueue
[]
ws
;
WorkQueue
w
;
ForkJoinWorkerThread
wt
;
int
m
;
int
n
=
ws
.
length
;
long
checkSum
=
ctl
;
for
(
int
i
=
0
;
i
<
n
;
++
i
)
{
if
((
short
)(
checkSum
>>>
TC_SHIFT
)
+
(
config
&
SMASK
)
<=
0
||
(
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<=
0
)
{
if
((
runState
&
TERMINATED
)
==
0
)
{
rs
=
lockRunState
();
// done
unlockRunState
(
rs
,
(
rs
&
~
RSLOCK
)
|
TERMINATED
);
synchronized
(
this
)
{
notifyAll
();
}
// for awaitTermination
}
break
;
}
for
(
int
i
=
0
;
i
<=
m
;
++
i
)
{
if
((
w
=
ws
[
i
])
!=
null
)
{
if
((
w
=
ws
[
i
])
!=
null
)
{
w
.
qlock
=
-
1
;
checkSum
+=
w
.
base
;
w
.
qlock
=
-
1
;
// try to disable
if
(
pass
>
0
)
{
if
(
pass
>
0
)
{
w
.
cancelAll
();
w
.
cancelAll
();
// clear queue
if
(
pass
>
1
&&
(
wt
=
w
.
owner
)
!=
null
)
{
if
(
pass
>
1
&&
(
wt
=
w
.
owner
)
!=
null
)
{
if
(!
wt
.
isInterrupted
())
{
if
(!
wt
.
isInterrupted
())
{
try
{
try
{
// unblock join
wt
.
interrupt
();
wt
.
interrupt
();
}
catch
(
Throwable
ignore
)
{
}
catch
(
Throwable
ignore
)
{
}
}
}
}
U
.
unpark
(
wt
);
if
(
w
.
scanState
<
0
)
U
.
unpark
(
wt
);
// wake up
}
}
}
}
}
}
}
}
// Wake up workers parked on event queue
if
(
checkSum
!=
oldSum
)
{
// unstable
int
i
,
e
;
long
cc
;
Thread
p
;
oldSum
=
checkSum
;
while
((
e
=
(
int
)(
cc
=
ctl
)
&
E_MASK
)
!=
0
&&
pass
=
0
;
(
i
=
e
&
SMASK
)
<
n
&&
i
>=
0
&&
(
w
=
ws
[
i
])
!=
null
)
{
long
nc
=
((
long
)(
w
.
nextWait
&
E_MASK
)
|
((
cc
+
AC_UNIT
)
&
AC_MASK
)
|
(
cc
&
(
TC_MASK
|
STOP_BIT
)));
if
(
w
.
eventCount
==
(
e
|
INT_SIGN
)
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
cc
,
nc
))
{
w
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
w
.
qlock
=
-
1
;
if
((
p
=
w
.
parker
)
!=
null
)
U
.
unpark
(
p
);
}
}
else
if
(
pass
>
3
&&
pass
>
m
)
// can't further help
break
;
else
if
(++
pass
>
1
)
{
// try to dequeue
long
c
;
int
j
=
0
,
sp
;
// bound attempts
while
(
j
++
<=
m
&&
(
sp
=
(
int
)(
c
=
ctl
))
!=
0
)
tryRelease
(
c
,
ws
[
sp
&
m
],
AC_UNIT
);
}
}
}
}
return
true
;
}
}
// External operations
/**
* Full version of externalPush, handling uncommon cases, as well
* as performing secondary initialization upon the first
* submission of the first task to the pool. It also detects
* first submission by an external thread and creates a new shared
* queue if the one at index if empty or contended.
*
* @param task the task. Caller must ensure non-null.
*/
private
void
externalSubmit
(
ForkJoinTask
<?>
task
)
{
int
r
;
// initialize caller's probe
if
((
r
=
ThreadLocalRandom
.
getProbe
())
==
0
)
{
ThreadLocalRandom
.
localInit
();
r
=
ThreadLocalRandom
.
getProbe
();
}
for
(;;)
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
rs
,
m
,
k
;
boolean
move
=
false
;
if
((
rs
=
runState
)
<
0
)
{
tryTerminate
(
false
,
false
);
// help terminate
throw
new
RejectedExecutionException
();
}
else
if
((
rs
&
STARTED
)
==
0
||
// initialize
((
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<
0
))
{
int
ns
=
0
;
rs
=
lockRunState
();
try
{
if
((
rs
&
STARTED
)
==
0
)
{
U
.
compareAndSwapObject
(
this
,
STEALCOUNTER
,
null
,
new
AtomicLong
());
// create workQueues array with size a power of two
int
p
=
config
&
SMASK
;
// ensure at least 2 slots
int
n
=
(
p
>
1
)
?
p
-
1
:
1
;
n
|=
n
>>>
1
;
n
|=
n
>>>
2
;
n
|=
n
>>>
4
;
n
|=
n
>>>
8
;
n
|=
n
>>>
16
;
n
=
(
n
+
1
)
<<
1
;
workQueues
=
new
WorkQueue
[
n
];
ns
=
STARTED
;
}
}
}
finally
{
unlockRunState
(
rs
,
(
rs
&
~
RSLOCK
)
|
ns
);
}
}
else
if
((
q
=
ws
[
k
=
r
&
m
&
SQMASK
])
!=
null
)
{
if
(
q
.
qlock
==
0
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
ForkJoinTask
<?>[]
a
=
q
.
array
;
int
s
=
q
.
top
;
boolean
submitted
=
false
;
// initial submission or resizing
try
{
// locked version of push
if
((
a
!=
null
&&
a
.
length
>
s
+
1
-
q
.
base
)
||
(
a
=
q
.
growArray
())
!=
null
)
{
int
j
=
(((
a
.
length
-
1
)
&
s
)
<<
ASHIFT
)
+
ABASE
;
U
.
putOrderedObject
(
a
,
j
,
task
);
U
.
putOrderedInt
(
q
,
QTOP
,
s
+
1
);
submitted
=
true
;
}
}
finally
{
U
.
compareAndSwapInt
(
q
,
QLOCK
,
1
,
0
);
}
if
(
submitted
)
{
signalWork
(
ws
,
q
);
return
;
}
}
move
=
true
;
// move on failure
}
else
if
(((
rs
=
runState
)
&
RSLOCK
)
==
0
)
{
// create new queue
q
=
new
WorkQueue
(
this
,
null
);
q
.
hint
=
r
;
q
.
config
=
k
|
SHARED_QUEUE
;
q
.
scanState
=
INACTIVE
;
rs
=
lockRunState
();
// publish index
if
(
rs
>
0
&&
(
ws
=
workQueues
)
!=
null
&&
k
<
ws
.
length
&&
ws
[
k
]
==
null
)
ws
[
k
]
=
q
;
// else terminated
unlockRunState
(
rs
,
rs
&
~
RSLOCK
);
}
else
move
=
true
;
// move if busy
if
(
move
)
r
=
ThreadLocalRandom
.
advanceProbe
(
r
);
}
}
}
}
// external operations on common pool
/**
* Tries to add the given task to a submission queue at
* submitter's current queue. Only the (vastly) most common path
* is directly handled in this method, while screening for need
* for externalSubmit.
*
* @param task the task. Caller must ensure non-null.
*/
final
void
externalPush
(
ForkJoinTask
<?>
task
)
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
m
;
int
r
=
ThreadLocalRandom
.
getProbe
();
int
rs
=
runState
;
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
(
ws
.
length
-
1
))
>=
0
&&
(
q
=
ws
[
m
&
r
&
SQMASK
])
!=
null
&&
r
!=
0
&&
rs
>
0
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
ForkJoinTask
<?>[]
a
;
int
am
,
n
,
s
;
if
((
a
=
q
.
array
)
!=
null
&&
(
am
=
a
.
length
-
1
)
>
(
n
=
(
s
=
q
.
top
)
-
q
.
base
))
{
int
j
=
((
am
&
s
)
<<
ASHIFT
)
+
ABASE
;
U
.
putOrderedObject
(
a
,
j
,
task
);
U
.
putOrderedInt
(
q
,
QTOP
,
s
+
1
);
U
.
putOrderedInt
(
q
,
QLOCK
,
0
);
if
(
n
<=
1
)
signalWork
(
ws
,
q
);
return
;
}
U
.
compareAndSwapInt
(
q
,
QLOCK
,
1
,
0
);
}
externalSubmit
(
task
);
}
/**
/**
* Returns common pool queue for a thread that has submitted at
* Returns common pool queue for an external thread.
* least one task.
*/
*/
static
WorkQueue
commonSubmitterQueue
()
{
static
WorkQueue
commonSubmitterQueue
()
{
ForkJoinPool
p
;
WorkQueue
[]
ws
;
int
m
,
z
;
ForkJoinPool
p
=
common
;
return
((
z
=
ThreadLocalRandom
.
getProbe
())
!=
0
&&
int
r
=
ThreadLocalRandom
.
getProbe
();
(
p
=
common
)
!=
null
&&
WorkQueue
[]
ws
;
int
m
;
(
ws
=
p
.
workQueues
)
!=
null
&&
return
(
p
!=
null
&&
(
ws
=
p
.
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
?
(
m
=
ws
.
length
-
1
)
>=
0
)
?
ws
[
m
&
z
&
SQMASK
]
:
null
;
ws
[
m
&
r
&
SQMASK
]
:
null
;
}
}
/**
/**
* Tries to pop the given task from submitter's queue in common pool.
* Performs tryUnpush for an external submitter: Finds queue,
* locks if apparently non-empty, validates upon locking, and
* adjusts top. Each check can fail but rarely does.
*/
*/
final
boolean
tryExternalUnpush
(
ForkJoinTask
<?>
task
)
{
final
boolean
tryExternalUnpush
(
ForkJoinTask
<?>
task
)
{
WorkQueue
joiner
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
;
WorkQueue
[]
ws
;
WorkQueue
w
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
;
WorkQueue
[]
ws
=
workQueues
;
int
r
=
ThreadLocalRandom
.
getProbe
();
int
z
=
ThreadLocalRandom
.
getProbe
();
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
boolean
popped
=
false
;
(
w
=
ws
[
m
&
r
&
SQMASK
])
!=
null
&&
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
(
a
=
w
.
array
)
!=
null
&&
(
s
=
w
.
top
)
!=
w
.
base
)
{
(
joiner
=
ws
[
z
&
m
&
SQMASK
])
!=
null
&&
joiner
.
base
!=
(
s
=
joiner
.
top
)
&&
(
a
=
joiner
.
array
)
!=
null
)
{
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
if
(
U
.
getObject
(
a
,
j
)
==
task
&&
if
(
U
.
compareAndSwapInt
(
w
,
QLOCK
,
0
,
1
))
{
U
.
compareAndSwapInt
(
joiner
,
QLOCK
,
0
,
1
))
{
if
(
w
.
top
==
s
&&
w
.
array
==
a
&&
if
(
joiner
.
top
==
s
&&
joiner
.
array
==
a
&&
U
.
getObject
(
a
,
j
)
==
task
&&
U
.
compareAndSwapObject
(
a
,
j
,
task
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
task
,
null
))
{
joiner
.
top
=
s
-
1
;
U
.
putOrderedInt
(
w
,
QTOP
,
s
-
1
);
popped
=
true
;
U
.
putOrderedInt
(
w
,
QLOCK
,
0
);
return
true
;
}
}
joiner
.
qlock
=
0
;
U
.
compareAndSwapInt
(
w
,
QLOCK
,
1
,
0
)
;
}
}
}
}
return
popped
;
return
false
;
}
}
/**
* Performs helpComplete for an external submitter.
*/
final
int
externalHelpComplete
(
CountedCompleter
<?>
task
,
int
maxTasks
)
{
final
int
externalHelpComplete
(
CountedCompleter
<?>
task
,
int
maxTasks
)
{
WorkQueue
joiner
;
int
m
;
WorkQueue
[]
ws
;
int
n
;
WorkQueue
[]
ws
=
workQueues
;
int
r
=
ThreadLocalRandom
.
getProbe
();
int
j
=
ThreadLocalRandom
.
getProbe
();
return
((
ws
=
workQueues
)
==
null
||
(
n
=
ws
.
length
)
==
0
)
?
0
:
int
s
=
0
;
helpComplete
(
ws
[(
n
-
1
)
&
r
&
SQMASK
],
task
,
maxTasks
);
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
(
joiner
=
ws
[
j
&
m
&
SQMASK
])
!=
null
&&
task
!=
null
)
{
int
scans
=
m
+
m
+
1
;
long
c
=
0L
;
// for stability check
j
|=
1
;
// poll odd queues
for
(
int
k
=
scans
;
;
j
+=
2
)
{
WorkQueue
q
;
if
((
s
=
task
.
status
)
<
0
)
break
;
else
if
(
joiner
.
externalPopAndExecCC
(
task
))
{
if
(--
maxTasks
<=
0
)
{
s
=
task
.
status
;
break
;
}
k
=
scans
;
}
else
if
((
s
=
task
.
status
)
<
0
)
break
;
else
if
((
q
=
ws
[
j
&
m
])
!=
null
&&
q
.
pollAndExecCC
(
task
))
{
if
(--
maxTasks
<=
0
)
{
s
=
task
.
status
;
break
;
}
k
=
scans
;
}
else
if
(--
k
<
0
)
{
if
(
c
==
(
c
=
ctl
))
break
;
k
=
scans
;
}
}
}
return
s
;
}
}
// Exported methods
// Exported methods
...
@@ -2447,7 +2533,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2447,7 +2533,7 @@ public class ForkJoinPool extends AbstractExecutorService {
this
(
checkParallelism
(
parallelism
),
this
(
checkParallelism
(
parallelism
),
checkFactory
(
factory
),
checkFactory
(
factory
),
handler
,
handler
,
(
asyncMode
?
FIFO_QUEUE
:
LIFO_QUEUE
)
,
asyncMode
?
FIFO_QUEUE
:
LIFO_QUEUE
,
"ForkJoinPool-"
+
nextPoolId
()
+
"-worker-"
);
"ForkJoinPool-"
+
nextPoolId
()
+
"-worker-"
);
checkPermission
();
checkPermission
();
}
}
...
@@ -2478,8 +2564,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2478,8 +2564,7 @@ public class ForkJoinPool extends AbstractExecutorService {
this
.
workerNamePrefix
=
workerNamePrefix
;
this
.
workerNamePrefix
=
workerNamePrefix
;
this
.
factory
=
factory
;
this
.
factory
=
factory
;
this
.
ueh
=
handler
;
this
.
ueh
=
handler
;
this
.
mode
=
(
short
)
mode
;
this
.
config
=
(
parallelism
&
SMASK
)
|
mode
;
this
.
parallelism
=
(
short
)
parallelism
;
long
np
=
(
long
)(-
parallelism
);
// offset ctl counts
long
np
=
(
long
)(-
parallelism
);
// offset ctl counts
this
.
ctl
=
((
np
<<
AC_SHIFT
)
&
AC_MASK
)
|
((
np
<<
TC_SHIFT
)
&
TC_MASK
);
this
.
ctl
=
((
np
<<
AC_SHIFT
)
&
AC_MASK
)
|
((
np
<<
TC_SHIFT
)
&
TC_MASK
);
}
}
...
@@ -2624,7 +2709,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2624,7 +2709,7 @@ public class ForkJoinPool extends AbstractExecutorService {
// In previous versions of this class, this method constructed
// In previous versions of this class, this method constructed
// a task to run ForkJoinTask.invokeAll, but now external
// a task to run ForkJoinTask.invokeAll, but now external
// invocation of multiple tasks is at least as efficient.
// invocation of multiple tasks is at least as efficient.
ArrayList
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>
>(
tasks
.
size
());
ArrayList
<
Future
<
T
>>
futures
=
new
ArrayList
<>(
tasks
.
size
());
boolean
done
=
false
;
boolean
done
=
false
;
try
{
try
{
...
@@ -2670,7 +2755,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2670,7 +2755,7 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
public
int
getParallelism
()
{
public
int
getParallelism
()
{
int
par
;
int
par
;
return
((
par
=
parallelism
)
>
0
)
?
par
:
1
;
return
((
par
=
config
&
SMASK
)
>
0
)
?
par
:
1
;
}
}
/**
/**
...
@@ -2692,7 +2777,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2692,7 +2777,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of worker threads
* @return the number of worker threads
*/
*/
public
int
getPoolSize
()
{
public
int
getPoolSize
()
{
return
parallelism
+
(
short
)(
ctl
>>>
TC_SHIFT
);
return
(
config
&
SMASK
)
+
(
short
)(
ctl
>>>
TC_SHIFT
);
}
}
/**
/**
...
@@ -2702,7 +2787,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2702,7 +2787,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if this pool uses async mode
* @return {@code true} if this pool uses async mode
*/
*/
public
boolean
getAsyncMode
()
{
public
boolean
getAsyncMode
()
{
return
mode
==
FIFO_QUEUE
;
return
(
config
&
FIFO_QUEUE
)
!=
0
;
}
}
/**
/**
...
@@ -2733,7 +2818,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2733,7 +2818,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of active threads
* @return the number of active threads
*/
*/
public
int
getActiveThreadCount
()
{
public
int
getActiveThreadCount
()
{
int
r
=
parallelism
+
(
int
)(
ctl
>>
AC_SHIFT
);
int
r
=
(
config
&
SMASK
)
+
(
int
)(
ctl
>>
AC_SHIFT
);
return
(
r
<=
0
)
?
0
:
r
;
// suppress momentarily negative values
return
(
r
<=
0
)
?
0
:
r
;
// suppress momentarily negative values
}
}
...
@@ -2749,7 +2834,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2749,7 +2834,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if all threads are currently idle
* @return {@code true} if all threads are currently idle
*/
*/
public
boolean
isQuiescent
()
{
public
boolean
isQuiescent
()
{
return
parallelism
+
(
int
)(
ctl
>>
AC_SHIFT
)
<=
0
;
return
(
config
&
SMASK
)
+
(
int
)(
ctl
>>
AC_SHIFT
)
<=
0
;
}
}
/**
/**
...
@@ -2764,7 +2849,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2764,7 +2849,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of steals
* @return the number of steals
*/
*/
public
long
getStealCount
()
{
public
long
getStealCount
()
{
long
count
=
stealCount
;
AtomicLong
sc
=
stealCounter
;
long
count
=
(
sc
==
null
)
?
0L
:
sc
.
get
();
WorkQueue
[]
ws
;
WorkQueue
w
;
WorkQueue
[]
ws
;
WorkQueue
w
;
if
((
ws
=
workQueues
)
!=
null
)
{
if
((
ws
=
workQueues
)
!=
null
)
{
for
(
int
i
=
1
;
i
<
ws
.
length
;
i
+=
2
)
{
for
(
int
i
=
1
;
i
<
ws
.
length
;
i
+=
2
)
{
...
@@ -2894,7 +2980,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2894,7 +2980,8 @@ public class ForkJoinPool extends AbstractExecutorService {
public
String
toString
()
{
public
String
toString
()
{
// Use a single pass through workQueues to collect counts
// Use a single pass through workQueues to collect counts
long
qt
=
0L
,
qs
=
0L
;
int
rc
=
0
;
long
qt
=
0L
,
qs
=
0L
;
int
rc
=
0
;
long
st
=
stealCount
;
AtomicLong
sc
=
stealCounter
;
long
st
=
(
sc
==
null
)
?
0L
:
sc
.
get
();
long
c
=
ctl
;
long
c
=
ctl
;
WorkQueue
[]
ws
;
WorkQueue
w
;
WorkQueue
[]
ws
;
WorkQueue
w
;
if
((
ws
=
workQueues
)
!=
null
)
{
if
((
ws
=
workQueues
)
!=
null
)
{
...
@@ -2912,16 +2999,16 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2912,16 +2999,16 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
}
}
}
}
int
pc
=
parallelism
;
int
pc
=
(
config
&
SMASK
)
;
int
tc
=
pc
+
(
short
)(
c
>>>
TC_SHIFT
);
int
tc
=
pc
+
(
short
)(
c
>>>
TC_SHIFT
);
int
ac
=
pc
+
(
int
)(
c
>>
AC_SHIFT
);
int
ac
=
pc
+
(
int
)(
c
>>
AC_SHIFT
);
if
(
ac
<
0
)
// ignore transient negative
if
(
ac
<
0
)
// ignore transient negative
ac
=
0
;
ac
=
0
;
String
level
;
int
rs
=
runState
;
if
((
c
&
STOP_BIT
)
!=
0
)
String
level
=
((
rs
&
TERMINATED
)
!=
0
?
"Terminated"
:
level
=
(
tc
==
0
)
?
"Terminated"
:
"Terminating"
;
(
rs
&
STOP
)
!=
0
?
"Terminating"
:
else
(
rs
&
SHUTDOWN
)
!=
0
?
"Shutting down"
:
level
=
plock
<
0
?
"Shutting down"
:
"Running"
;
"Running"
)
;
return
super
.
toString
()
+
return
super
.
toString
()
+
"["
+
level
+
"["
+
level
+
", parallelism = "
+
pc
+
", parallelism = "
+
pc
+
...
@@ -2983,9 +3070,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2983,9 +3070,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if all tasks have completed following shut down
* @return {@code true} if all tasks have completed following shut down
*/
*/
public
boolean
isTerminated
()
{
public
boolean
isTerminated
()
{
long
c
=
ctl
;
return
(
runState
&
TERMINATED
)
!=
0
;
return
((
c
&
STOP_BIT
)
!=
0L
&&
(
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
<=
0
);
}
}
/**
/**
...
@@ -3002,9 +3087,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3002,9 +3087,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if terminating but not yet terminated
* @return {@code true} if terminating but not yet terminated
*/
*/
public
boolean
isTerminating
()
{
public
boolean
isTerminating
()
{
long
c
=
ctl
;
int
rs
=
runState
;
return
((
c
&
STOP_BIT
)
!=
0L
&&
return
(
rs
&
STOP
)
!=
0
&&
(
rs
&
TERMINATED
)
==
0
;
(
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
>
0
);
}
}
/**
/**
...
@@ -3013,7 +3097,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3013,7 +3097,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if this pool has been shut down
* @return {@code true} if this pool has been shut down
*/
*/
public
boolean
isShutdown
()
{
public
boolean
isShutdown
()
{
return
plock
<
0
;
return
(
runState
&
SHUTDOWN
)
!=
0
;
}
}
/**
/**
...
@@ -3090,8 +3174,9 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3090,8 +3174,9 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
found
=
false
;
found
=
false
;
for
(
int
j
=
(
m
+
1
)
<<
2
;
j
>=
0
;
--
j
)
{
for
(
int
j
=
(
m
+
1
)
<<
2
;
j
>=
0
;
--
j
)
{
ForkJoinTask
<?>
t
;
WorkQueue
q
;
int
b
;
ForkJoinTask
<?>
t
;
WorkQueue
q
;
int
b
,
k
;
if
((
q
=
ws
[
r
++
&
m
])
!=
null
&&
(
b
=
q
.
base
)
-
q
.
top
<
0
)
{
if
((
k
=
r
++
&
m
)
<=
m
&&
k
>=
0
&&
(
q
=
ws
[
k
])
!=
null
&&
(
b
=
q
.
base
)
-
q
.
top
<
0
)
{
found
=
true
;
found
=
true
;
if
((
t
=
q
.
pollAt
(
b
))
!=
null
)
if
((
t
=
q
.
pollAt
(
b
))
!=
null
)
t
.
doExec
();
t
.
doExec
();
...
@@ -3115,8 +3200,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3115,8 +3200,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* in {@link ForkJoinPool}s.
* in {@link ForkJoinPool}s.
*
*
* <p>A {@code ManagedBlocker} provides two methods. Method
* <p>A {@code ManagedBlocker} provides two methods. Method
* {@
code
isReleasable} must return {@code true} if blocking is
* {@
link #
isReleasable} must return {@code true} if blocking is
* not necessary. Method {@
code
block} blocks the current thread
* not necessary. Method {@
link #
block} blocks the current thread
* if necessary (perhaps internally invoking {@code isReleasable}
* if necessary (perhaps internally invoking {@code isReleasable}
* before actually blocking). These actions are performed by any
* before actually blocking). These actions are performed by any
* thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}.
* thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}.
...
@@ -3185,37 +3270,46 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3185,37 +3270,46 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
/**
/**
* Blocks in accord with the given blocker. If the current thread
* Runs the given possibly blocking task. When {@linkplain
* is a {@link ForkJoinWorkerThread}, this method possibly
* ForkJoinTask#inForkJoinPool() running in a ForkJoinPool}, this
* arranges for a spare thread to be activated if necessary to
* method possibly arranges for a spare thread to be activated if
* ensure sufficient parallelism while the current thread is blocked.
* necessary to ensure sufficient parallelism while the current
* thread is blocked in {@link ManagedBlocker#block blocker.block()}.
*
* <p>This method repeatedly calls {@code blocker.isReleasable()} and
* {@code blocker.block()} until either method returns {@code true}.
* Every call to {@code blocker.block()} is preceded by a call to
* {@code blocker.isReleasable()} that returned {@code false}.
*
*
* <p>If
the caller is not a {@link ForkJoinTask}
, this method is
* <p>If
not running in a ForkJoinPool
, this method is
* behaviorally equivalent to
* behaviorally equivalent to
* <pre> {@code
* <pre> {@code
* while (!blocker.isReleasable())
* while (!blocker.isReleasable())
* if (blocker.block())
* if (blocker.block())
* return;
* break;}</pre>
* }</pre>
*
*
* If the caller is a {@code ForkJoinTask}, then the pool may
* If running in a ForkJoinPool, the pool may first be expanded to
* first be expanded to ensure parallelism, and later adjusted.
* ensure sufficient parallelism available during the call to
* {@code blocker.block()}.
*
*
* @param blocker the blocker
* @param blocker the blocker
task
* @throws InterruptedException if
blocker.block
did so
* @throws InterruptedException if
{@code blocker.block()}
did so
*/
*/
public
static
void
managedBlock
(
ManagedBlocker
blocker
)
public
static
void
managedBlock
(
ManagedBlocker
blocker
)
throws
InterruptedException
{
throws
InterruptedException
{
ForkJoinPool
p
;
ForkJoinWorkerThread
wt
;
Thread
t
=
Thread
.
currentThread
();
Thread
t
=
Thread
.
currentThread
();
if
(
t
instanceof
ForkJoinWorkerThread
)
{
if
((
t
instanceof
ForkJoinWorkerThread
)
&&
ForkJoinPool
p
=
((
ForkJoinWorkerThread
)
t
).
pool
;
(
p
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
)
!=
null
)
{
WorkQueue
w
=
wt
.
workQueue
;
while
(!
blocker
.
isReleasable
())
{
while
(!
blocker
.
isReleasable
())
{
if
(
p
.
tryCompensate
(
p
.
ctl
))
{
if
(
p
.
tryCompensate
(
w
))
{
try
{
try
{
do
{}
while
(!
blocker
.
isReleasable
()
&&
do
{}
while
(!
blocker
.
isReleasable
()
&&
!
blocker
.
block
());
!
blocker
.
block
());
}
finally
{
}
finally
{
p
.
incrementActiveCount
(
);
U
.
getAndAddLong
(
p
,
CTL
,
AC_UNIT
);
}
}
break
;
break
;
}
}
...
@@ -3241,15 +3335,18 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3241,15 +3335,18 @@ public class ForkJoinPool extends AbstractExecutorService {
// Unsafe mechanics
// Unsafe mechanics
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
long
CTL
;
private
static
final
long
PARKBLOCKER
;
private
static
final
int
ABASE
;
private
static
final
int
ABASE
;
private
static
final
int
ASHIFT
;
private
static
final
int
ASHIFT
;
private
static
final
long
STEALCOUNT
;
private
static
final
long
CTL
;
private
static
final
long
PLOCK
;
private
static
final
long
RUNSTATE
;
private
static
final
long
INDEXSEED
;
private
static
final
long
STEALCOUNTER
;
private
static
final
long
QBASE
;
private
static
final
long
PARKBLOCKER
;
private
static
final
long
QTOP
;
private
static
final
long
QLOCK
;
private
static
final
long
QLOCK
;
private
static
final
long
QSCANSTATE
;
private
static
final
long
QPARKER
;
private
static
final
long
QCURRENTSTEAL
;
private
static
final
long
QCURRENTJOIN
;
static
{
static
{
// initialize field offsets for CAS etc
// initialize field offsets for CAS etc
...
@@ -3258,20 +3355,26 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3258,20 +3355,26 @@ public class ForkJoinPool extends AbstractExecutorService {
Class
<?>
k
=
ForkJoinPool
.
class
;
Class
<?>
k
=
ForkJoinPool
.
class
;
CTL
=
U
.
objectFieldOffset
CTL
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"ctl"
));
(
k
.
getDeclaredField
(
"ctl"
));
STEALCOUNT
=
U
.
objectFieldOffset
RUNSTATE
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"stealCount"
));
(
k
.
getDeclaredField
(
"runState"
));
PLOCK
=
U
.
objectFieldOffset
STEALCOUNTER
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"plock"
));
(
k
.
getDeclaredField
(
"stealCounter"
));
INDEXSEED
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"indexSeed"
));
Class
<?>
tk
=
Thread
.
class
;
Class
<?>
tk
=
Thread
.
class
;
PARKBLOCKER
=
U
.
objectFieldOffset
PARKBLOCKER
=
U
.
objectFieldOffset
(
tk
.
getDeclaredField
(
"parkBlocker"
));
(
tk
.
getDeclaredField
(
"parkBlocker"
));
Class
<?>
wk
=
WorkQueue
.
class
;
Class
<?>
wk
=
WorkQueue
.
class
;
Q
BASE
=
U
.
objectFieldOffset
Q
TOP
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"
base
"
));
(
wk
.
getDeclaredField
(
"
top
"
));
QLOCK
=
U
.
objectFieldOffset
QLOCK
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"qlock"
));
(
wk
.
getDeclaredField
(
"qlock"
));
QSCANSTATE
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"scanState"
));
QPARKER
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"parker"
));
QCURRENTSTEAL
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"currentSteal"
));
QCURRENTJOIN
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"currentJoin"
));
Class
<?>
ak
=
ForkJoinTask
[].
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
ABASE
=
U
.
arrayBaseOffset
(
ak
);
ABASE
=
U
.
arrayBaseOffset
(
ak
);
int
scale
=
U
.
arrayIndexScale
(
ak
);
int
scale
=
U
.
arrayIndexScale
(
ak
);
...
@@ -3282,6 +3385,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3282,6 +3385,7 @@ public class ForkJoinPool extends AbstractExecutorService {
throw
new
Error
(
e
);
throw
new
Error
(
e
);
}
}
commonMaxSpares
=
DEFAULT_COMMON_MAX_SPARES
;
defaultForkJoinWorkerThreadFactory
=
defaultForkJoinWorkerThreadFactory
=
new
DefaultForkJoinWorkerThreadFactory
();
new
DefaultForkJoinWorkerThreadFactory
();
modifyThreadPermission
=
new
RuntimePermission
(
"modifyThread"
);
modifyThreadPermission
=
new
RuntimePermission
(
"modifyThread"
);
...
@@ -3289,7 +3393,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3289,7 +3393,7 @@ public class ForkJoinPool extends AbstractExecutorService {
common
=
java
.
security
.
AccessController
.
doPrivileged
common
=
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
<
ForkJoinPool
>()
{
(
new
java
.
security
.
PrivilegedAction
<
ForkJoinPool
>()
{
public
ForkJoinPool
run
()
{
return
makeCommonPool
();
}});
public
ForkJoinPool
run
()
{
return
makeCommonPool
();
}});
int
par
=
common
.
parallelism
;
// report 1 even if threads disabled
int
par
=
common
.
config
&
SMASK
;
// report 1 even if threads disabled
commonParallelism
=
par
>
0
?
par
:
1
;
commonParallelism
=
par
>
0
?
par
:
1
;
}
}
...
...
src/share/classes/java/util/concurrent/ForkJoinTask.java
浏览文件 @
5606a2cd
...
@@ -297,15 +297,22 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -297,15 +297,22 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
}
/**
/**
* Tries to set SIGNAL status unless already completed. Used by
* If not done, sets SIGNAL status and performs Object.wait(timeout).
* ForkJoinPool. Other variants are directly incorporated into
* This task may or may not be done on exit. Ignores interrupts.
* externalAwaitDone etc.
*
*
* @
return true if successful
* @
param timeout using Object.wait conventions.
*/
*/
final
boolean
trySetSignal
()
{
final
void
internalWait
(
long
timeout
)
{
int
s
=
status
;
int
s
;
return
s
>=
0
&&
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
);
if
((
s
=
status
)
>=
0
&&
// force completer to issue notify
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
synchronized
(
this
)
{
if
(
status
>=
0
)
try
{
wait
(
timeout
);
}
catch
(
InterruptedException
ie
)
{
}
else
notifyAll
();
}
}
}
}
/**
/**
...
@@ -313,15 +320,10 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -313,15 +320,10 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return status upon completion
* @return status upon completion
*/
*/
private
int
externalAwaitDone
()
{
private
int
externalAwaitDone
()
{
int
s
;
int
s
=
((
this
instanceof
CountedCompleter
)
?
// try helping
ForkJoinPool
cp
=
ForkJoinPool
.
common
;
ForkJoinPool
.
common
.
externalHelpComplete
(
if
((
s
=
status
)
>=
0
)
{
(
CountedCompleter
<?>)
this
,
0
)
:
if
(
cp
!=
null
)
{
ForkJoinPool
.
common
.
tryExternalUnpush
(
this
)
?
doExec
()
:
0
);
if
(
this
instanceof
CountedCompleter
)
s
=
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
else
if
(
cp
.
tryExternalUnpush
(
this
))
s
=
doExec
();
}
if
(
s
>=
0
&&
(
s
=
status
)
>=
0
)
{
if
(
s
>=
0
&&
(
s
=
status
)
>=
0
)
{
boolean
interrupted
=
false
;
boolean
interrupted
=
false
;
do
{
do
{
...
@@ -329,7 +331,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -329,7 +331,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
synchronized
(
this
)
{
synchronized
(
this
)
{
if
(
status
>=
0
)
{
if
(
status
>=
0
)
{
try
{
try
{
wait
(
);
wait
(
0L
);
}
catch
(
InterruptedException
ie
)
{
}
catch
(
InterruptedException
ie
)
{
interrupted
=
true
;
interrupted
=
true
;
}
}
...
@@ -342,7 +344,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -342,7 +344,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
if
(
interrupted
)
if
(
interrupted
)
Thread
.
currentThread
().
interrupt
();
Thread
.
currentThread
().
interrupt
();
}
}
}
return
s
;
return
s
;
}
}
...
@@ -351,25 +352,25 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -351,25 +352,25 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
*/
private
int
externalInterruptibleAwaitDone
()
throws
InterruptedException
{
private
int
externalInterruptibleAwaitDone
()
throws
InterruptedException
{
int
s
;
int
s
;
ForkJoinPool
cp
=
ForkJoinPool
.
common
;
if
(
Thread
.
interrupted
())
if
(
Thread
.
interrupted
())
throw
new
InterruptedException
();
throw
new
InterruptedException
();
if
((
s
=
status
)
>=
0
&&
cp
!=
null
)
{
if
((
s
=
status
)
>=
0
&&
if
(
this
instanceof
CountedCompleter
)
(
s
=
((
this
instanceof
CountedCompleter
)
?
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
ForkJoinPool
.
common
.
externalHelpComplete
(
else
if
(
cp
.
tryExternalUnpush
(
this
))
(
CountedCompleter
<?>)
this
,
0
)
:
doExec
();
ForkJoinPool
.
common
.
tryExternalUnpush
(
this
)
?
doExec
()
:
}
0
))
>=
0
)
{
while
((
s
=
status
)
>=
0
)
{
while
((
s
=
status
)
>=
0
)
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
synchronized
(
this
)
{
synchronized
(
this
)
{
if
(
status
>=
0
)
if
(
status
>=
0
)
wait
(
);
wait
(
0L
);
else
else
notifyAll
();
notifyAll
();
}
}
}
}
}
}
}
return
s
;
return
s
;
}
}
...
@@ -386,7 +387,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -386,7 +387,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
(
w
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
workQueue
).
(
w
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
workQueue
).
tryUnpush
(
this
)
&&
(
s
=
doExec
())
<
0
?
s
:
tryUnpush
(
this
)
&&
(
s
=
doExec
())
<
0
?
s
:
wt
.
pool
.
awaitJoin
(
w
,
this
)
:
wt
.
pool
.
awaitJoin
(
w
,
this
,
0L
)
:
externalAwaitDone
();
externalAwaitDone
();
}
}
...
@@ -399,7 +400,8 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -399,7 +400,8 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
int
s
;
Thread
t
;
ForkJoinWorkerThread
wt
;
int
s
;
Thread
t
;
ForkJoinWorkerThread
wt
;
return
(
s
=
doExec
())
<
0
?
s
:
return
(
s
=
doExec
())
<
0
?
s
:
((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
.
awaitJoin
(
wt
.
workQueue
,
this
)
:
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
.
awaitJoin
(
wt
.
workQueue
,
this
,
0L
)
:
externalAwaitDone
();
externalAwaitDone
();
}
}
...
@@ -577,7 +579,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -577,7 +579,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Throwable
ex
;
Throwable
ex
;
if
(
e
==
null
||
(
ex
=
e
.
ex
)
==
null
)
if
(
e
==
null
||
(
ex
=
e
.
ex
)
==
null
)
return
null
;
return
null
;
if
(
false
&&
e
.
thrower
!=
Thread
.
currentThread
().
getId
())
{
if
(
e
.
thrower
!=
Thread
.
currentThread
().
getId
())
{
Class
<?
extends
Throwable
>
ec
=
ex
.
getClass
();
Class
<?
extends
Throwable
>
ec
=
ex
.
getClass
();
try
{
try
{
Constructor
<?>
noArgCtor
=
null
;
Constructor
<?>
noArgCtor
=
null
;
...
@@ -587,14 +589,18 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -587,14 +589,18 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Class
<?>[]
ps
=
c
.
getParameterTypes
();
Class
<?>[]
ps
=
c
.
getParameterTypes
();
if
(
ps
.
length
==
0
)
if
(
ps
.
length
==
0
)
noArgCtor
=
c
;
noArgCtor
=
c
;
else
if
(
ps
.
length
==
1
&&
ps
[
0
]
==
Throwable
.
class
)
else
if
(
ps
.
length
==
1
&&
ps
[
0
]
==
Throwable
.
class
)
{
return
(
Throwable
)(
c
.
newInstance
(
ex
));
Throwable
wx
=
(
Throwable
)
c
.
newInstance
(
ex
);
return
(
wx
==
null
)
?
ex
:
wx
;
}
}
}
if
(
noArgCtor
!=
null
)
{
if
(
noArgCtor
!=
null
)
{
Throwable
wx
=
(
Throwable
)(
noArgCtor
.
newInstance
());
Throwable
wx
=
(
Throwable
)(
noArgCtor
.
newInstance
());
if
(
wx
!=
null
)
{
wx
.
initCause
(
ex
);
wx
.
initCause
(
ex
);
return
wx
;
return
wx
;
}
}
}
}
catch
(
Exception
ignore
)
{
}
catch
(
Exception
ignore
)
{
}
}
}
}
...
@@ -1017,67 +1023,40 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1017,67 +1023,40 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
*/
public
final
V
get
(
long
timeout
,
TimeUnit
unit
)
public
final
V
get
(
long
timeout
,
TimeUnit
unit
)
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
int
s
;
long
nanos
=
unit
.
toNanos
(
timeout
);
if
(
Thread
.
interrupted
())
if
(
Thread
.
interrupted
())
throw
new
InterruptedException
();
throw
new
InterruptedException
();
// Messy in part because we measure in nanosecs, but wait in millisecs
if
((
s
=
status
)
>=
0
&&
nanos
>
0L
)
{
int
s
;
long
ms
;
long
d
=
System
.
nanoTime
()
+
nanos
;
long
ns
=
unit
.
toNanos
(
timeout
);
long
deadline
=
(
d
==
0L
)
?
1L
:
d
;
// avoid 0
ForkJoinPool
cp
;
if
((
s
=
status
)
>=
0
&&
ns
>
0L
)
{
long
deadline
=
System
.
nanoTime
()
+
ns
;
ForkJoinPool
p
=
null
;
ForkJoinPool
.
WorkQueue
w
=
null
;
Thread
t
=
Thread
.
currentThread
();
Thread
t
=
Thread
.
currentThread
();
if
(
t
instanceof
ForkJoinWorkerThread
)
{
if
(
t
instanceof
ForkJoinWorkerThread
)
{
ForkJoinWorkerThread
wt
=
(
ForkJoinWorkerThread
)
t
;
ForkJoinWorkerThread
wt
=
(
ForkJoinWorkerThread
)
t
;
p
=
wt
.
pool
;
s
=
wt
.
pool
.
awaitJoin
(
wt
.
workQueue
,
this
,
deadline
);
w
=
wt
.
workQueue
;
}
p
.
helpJoinOnce
(
w
,
this
);
// no retries on failure
else
if
((
s
=
((
this
instanceof
CountedCompleter
)
?
}
ForkJoinPool
.
common
.
externalHelpComplete
(
else
if
((
cp
=
ForkJoinPool
.
common
)
!=
null
)
{
(
CountedCompleter
<?>)
this
,
0
)
:
if
(
this
instanceof
CountedCompleter
)
ForkJoinPool
.
common
.
tryExternalUnpush
(
this
)
?
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
doExec
()
:
0
))
>=
0
)
{
else
if
(
cp
.
tryExternalUnpush
(
this
))
long
ns
,
ms
;
// measure in nanosecs, but wait in millisecs
doExec
();
while
((
s
=
status
)
>=
0
&&
}
(
ns
=
deadline
-
System
.
nanoTime
())
>
0L
)
{
boolean
canBlock
=
false
;
boolean
interrupted
=
false
;
try
{
while
((
s
=
status
)
>=
0
)
{
if
(
w
!=
null
&&
w
.
qlock
<
0
)
cancelIgnoringExceptions
(
this
);
else
if
(!
canBlock
)
{
if
(
p
==
null
||
p
.
tryCompensate
(
p
.
ctl
))
canBlock
=
true
;
}
else
{
if
((
ms
=
TimeUnit
.
NANOSECONDS
.
toMillis
(
ns
))
>
0L
&&
if
((
ms
=
TimeUnit
.
NANOSECONDS
.
toMillis
(
ns
))
>
0L
&&
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
synchronized
(
this
)
{
synchronized
(
this
)
{
if
(
status
>=
0
)
{
if
(
status
>=
0
)
try
{
wait
(
ms
);
// OK to throw InterruptedException
wait
(
ms
);
}
catch
(
InterruptedException
ie
)
{
if
(
p
==
null
)
interrupted
=
true
;
}
}
else
else
notifyAll
();
notifyAll
();
}
}
}
}
if
((
s
=
status
)
<
0
||
interrupted
||
(
ns
=
deadline
-
System
.
nanoTime
())
<=
0L
)
break
;
}
}
}
}
finally
{
if
(
p
!=
null
&&
canBlock
)
p
.
incrementActiveCount
();
}
}
if
(
interrupted
)
throw
new
InterruptedException
();
}
}
if
(
s
>=
0
)
s
=
status
;
if
((
s
&=
DONE_MASK
)
!=
NORMAL
)
{
if
((
s
&=
DONE_MASK
)
!=
NORMAL
)
{
Throwable
ex
;
Throwable
ex
;
if
(
s
==
CANCELLED
)
if
(
s
==
CANCELLED
)
...
...
src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
浏览文件 @
5606a2cd
...
@@ -66,7 +66,7 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -66,7 +66,7 @@ public class ForkJoinWorkerThread extends Thread {
* owning thread.
* owning thread.
*
*
* Support for (non-public) subclass InnocuousForkJoinWorkerThread
* Support for (non-public) subclass InnocuousForkJoinWorkerThread
* requires that we break quite a lot of encapulation (via Unsafe)
* requires that we break quite a lot of encap
s
ulation (via Unsafe)
* both here and in the subclass to access and set Thread fields.
* both here and in the subclass to access and set Thread fields.
*/
*/
...
@@ -118,7 +118,7 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -118,7 +118,7 @@ public class ForkJoinWorkerThread extends Thread {
* @return the index number
* @return the index number
*/
*/
public
int
getPoolIndex
()
{
public
int
getPoolIndex
()
{
return
workQueue
.
poolIndex
>>>
1
;
// ignore odd/even tag bit
return
workQueue
.
getPoolIndex
();
}
}
/**
/**
...
@@ -171,7 +171,7 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -171,7 +171,7 @@ public class ForkJoinWorkerThread extends Thread {
}
}
/**
/**
* Erases ThreadLocals by nulling out Thread maps
* Erases ThreadLocals by nulling out Thread maps
.
*/
*/
final
void
eraseThreadLocals
()
{
final
void
eraseThreadLocals
()
{
U
.
putObject
(
this
,
THREADLOCALS
,
null
);
U
.
putObject
(
this
,
THREADLOCALS
,
null
);
...
@@ -246,8 +246,8 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -246,8 +246,8 @@ public class ForkJoinWorkerThread extends Thread {
/**
/**
* Returns a new group with the system ThreadGroup (the
* Returns a new group with the system ThreadGroup (the
* topmost, parentless group) as parent. Uses Unsafe to
* topmost, parent
-
less group) as parent. Uses Unsafe to
* traverse Thread
group and ThreadGroup
parent fields.
* traverse Thread
.group and ThreadGroup.
parent fields.
*/
*/
private
static
ThreadGroup
createThreadGroup
()
{
private
static
ThreadGroup
createThreadGroup
()
{
try
{
try
{
...
@@ -274,4 +274,3 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -274,4 +274,3 @@ public class ForkJoinWorkerThread extends Thread {
}
}
}
}
src/share/classes/java/util/logging/FileHandler.java
浏览文件 @
5606a2cd
...
@@ -402,6 +402,14 @@ public class FileHandler extends StreamHandler {
...
@@ -402,6 +402,14 @@ public class FileHandler extends StreamHandler {
openFiles
();
openFiles
();
}
}
private
boolean
isParentWritable
(
Path
path
)
{
Path
parent
=
path
.
getParent
();
if
(
parent
==
null
)
{
parent
=
path
.
toAbsolutePath
().
getParent
();
}
return
parent
!=
null
&&
Files
.
isWritable
(
parent
);
}
/**
/**
* Open the set of output files, based on the configured
* Open the set of output files, based on the configured
* instance variables.
* instance variables.
...
@@ -458,7 +466,7 @@ public class FileHandler extends StreamHandler {
...
@@ -458,7 +466,7 @@ public class FileHandler extends StreamHandler {
// Note that this is a situation that may happen,
// Note that this is a situation that may happen,
// but not too frequently.
// but not too frequently.
if
(
Files
.
isRegularFile
(
lockFilePath
,
LinkOption
.
NOFOLLOW_LINKS
)
if
(
Files
.
isRegularFile
(
lockFilePath
,
LinkOption
.
NOFOLLOW_LINKS
)
&&
Files
.
isWritable
(
lockFilePath
.
getParent
()
))
{
&&
isParentWritable
(
lockFilePath
))
{
try
{
try
{
channel
=
FileChannel
.
open
(
lockFilePath
,
channel
=
FileChannel
.
open
(
lockFilePath
,
WRITE
,
APPEND
);
WRITE
,
APPEND
);
...
...
src/share/classes/javax/crypto/Cipher.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -167,6 +167,11 @@ public class Cipher {
...
@@ -167,6 +167,11 @@ public class Cipher {
private
static
final
Debug
debug
=
private
static
final
Debug
debug
=
Debug
.
getInstance
(
"jca"
,
"Cipher"
);
Debug
.
getInstance
(
"jca"
,
"Cipher"
);
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"cipher"
);
/**
/**
* Constant used to initialize cipher to encryption mode.
* Constant used to initialize cipher to encryption mode.
*/
*/
...
@@ -1110,6 +1115,21 @@ public class Cipher {
...
@@ -1110,6 +1115,21 @@ public class Cipher {
}
}
}
}
private
static
String
getOpmodeString
(
int
opmode
)
{
switch
(
opmode
)
{
case
ENCRYPT_MODE:
return
"encryption"
;
case
DECRYPT_MODE:
return
"decryption"
;
case
WRAP_MODE:
return
"key wrapping"
;
case
UNWRAP_MODE:
return
"key unwrapping"
;
default
:
return
""
;
}
}
/**
/**
* Initializes this cipher with a key.
* Initializes this cipher with a key.
*
*
...
@@ -1235,6 +1255,12 @@ public class Cipher {
...
@@ -1235,6 +1255,12 @@ public class Cipher {
initialized
=
true
;
initialized
=
true
;
this
.
opmode
=
opmode
;
this
.
opmode
=
opmode
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Cipher."
+
transformation
+
" "
+
getOpmodeString
(
opmode
)
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -1372,6 +1398,12 @@ public class Cipher {
...
@@ -1372,6 +1398,12 @@ public class Cipher {
initialized
=
true
;
initialized
=
true
;
this
.
opmode
=
opmode
;
this
.
opmode
=
opmode
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Cipher."
+
transformation
+
" "
+
getOpmodeString
(
opmode
)
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -1509,6 +1541,12 @@ public class Cipher {
...
@@ -1509,6 +1541,12 @@ public class Cipher {
initialized
=
true
;
initialized
=
true
;
this
.
opmode
=
opmode
;
this
.
opmode
=
opmode
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Cipher."
+
transformation
+
" "
+
getOpmodeString
(
opmode
)
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -1693,6 +1731,12 @@ public class Cipher {
...
@@ -1693,6 +1731,12 @@ public class Cipher {
initialized
=
true
;
initialized
=
true
;
this
.
opmode
=
opmode
;
this
.
opmode
=
opmode
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Cipher."
+
transformation
+
" "
+
getOpmodeString
(
opmode
)
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/javax/crypto/KeyAgreement.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -78,6 +78,11 @@ public class KeyAgreement {
...
@@ -78,6 +78,11 @@ public class KeyAgreement {
private
static
final
Debug
debug
=
private
static
final
Debug
debug
=
Debug
.
getInstance
(
"jca"
,
"KeyAgreement"
);
Debug
.
getInstance
(
"jca"
,
"KeyAgreement"
);
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"keyagreement"
);
// The provider
// The provider
private
Provider
provider
;
private
Provider
provider
;
...
@@ -468,6 +473,11 @@ public class KeyAgreement {
...
@@ -468,6 +473,11 @@ public class KeyAgreement {
throw
new
InvalidKeyException
(
e
);
throw
new
InvalidKeyException
(
e
);
}
}
}
}
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyAgreement."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -524,6 +534,11 @@ public class KeyAgreement {
...
@@ -524,6 +534,11 @@ public class KeyAgreement {
}
else
{
}
else
{
chooseProvider
(
I_PARAMS
,
key
,
params
,
random
);
chooseProvider
(
I_PARAMS
,
key
,
params
,
random
);
}
}
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyAgreement."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/javax/crypto/KeyGenerator.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -33,6 +33,7 @@ import java.security.spec.*;
...
@@ -33,6 +33,7 @@ import java.security.spec.*;
import
sun.security.jca.*
;
import
sun.security.jca.*
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.jca.GetInstance.Instance
;
import
sun.security.util.Debug
;
/**
/**
* This class provides the functionality of a secret (symmetric) key generator.
* This class provides the functionality of a secret (symmetric) key generator.
...
@@ -108,6 +109,11 @@ import sun.security.jca.GetInstance.Instance;
...
@@ -108,6 +109,11 @@ import sun.security.jca.GetInstance.Instance;
public
class
KeyGenerator
{
public
class
KeyGenerator
{
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"keygenerator"
);
// see java.security.KeyPairGenerator for failover notes
// see java.security.KeyPairGenerator for failover notes
private
final
static
int
I_NONE
=
1
;
private
final
static
int
I_NONE
=
1
;
...
@@ -145,6 +151,11 @@ public class KeyGenerator {
...
@@ -145,6 +151,11 @@ public class KeyGenerator {
this
.
spi
=
keyGenSpi
;
this
.
spi
=
keyGenSpi
;
this
.
provider
=
provider
;
this
.
provider
=
provider
;
this
.
algorithm
=
algorithm
;
this
.
algorithm
=
algorithm
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyGenerator."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
private
KeyGenerator
(
String
algorithm
)
throws
NoSuchAlgorithmException
{
private
KeyGenerator
(
String
algorithm
)
throws
NoSuchAlgorithmException
{
...
@@ -158,6 +169,11 @@ public class KeyGenerator {
...
@@ -158,6 +169,11 @@ public class KeyGenerator {
throw
new
NoSuchAlgorithmException
throw
new
NoSuchAlgorithmException
(
algorithm
+
" KeyGenerator not available"
);
(
algorithm
+
" KeyGenerator not available"
);
}
}
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"KeyGenerator."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/javax/crypto/Mac.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1998, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -77,6 +77,11 @@ public class Mac implements Cloneable {
...
@@ -77,6 +77,11 @@ public class Mac implements Cloneable {
private
static
final
Debug
debug
=
private
static
final
Debug
debug
=
Debug
.
getInstance
(
"jca"
,
"Mac"
);
Debug
.
getInstance
(
"jca"
,
"Mac"
);
private
static
final
Debug
pdebug
=
Debug
.
getInstance
(
"provider"
,
"Provider"
);
private
static
final
boolean
skipDebug
=
Debug
.
isOn
(
"engine="
)
&&
!
Debug
.
isOn
(
"mac"
);
// The provider
// The provider
private
Provider
provider
;
private
Provider
provider
;
...
@@ -413,6 +418,11 @@ public class Mac implements Cloneable {
...
@@ -413,6 +418,11 @@ public class Mac implements Cloneable {
throw
new
InvalidKeyException
(
"init() failed"
,
e
);
throw
new
InvalidKeyException
(
"init() failed"
,
e
);
}
}
initialized
=
true
;
initialized
=
true
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Mac."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
@@ -435,6 +445,11 @@ public class Mac implements Cloneable {
...
@@ -435,6 +445,11 @@ public class Mac implements Cloneable {
chooseProvider
(
key
,
params
);
chooseProvider
(
key
,
params
);
}
}
initialized
=
true
;
initialized
=
true
;
if
(!
skipDebug
&&
pdebug
!=
null
)
{
pdebug
.
println
(
"Mac."
+
algorithm
+
" algorithm from: "
+
this
.
provider
.
getName
());
}
}
}
/**
/**
...
...
src/share/classes/sun/awt/datatransfer/DataTransferer.java
浏览文件 @
5606a2cd
...
@@ -2895,6 +2895,14 @@ search:
...
@@ -2895,6 +2895,14 @@ search:
return
comp
;
return
comp
;
}
}
if
(
flavor1
.
isFlavorTextType
())
{
return
1
;
}
if
(
flavor2
.
isFlavorTextType
())
{
return
-
1
;
}
// Next, look for application/x-java-* types. Prefer unknown
// Next, look for application/x-java-* types. Prefer unknown
// MIME types because if the user provides his own data flavor,
// MIME types because if the user provides his own data flavor,
// it will likely be the most descriptive one.
// it will likely be the most descriptive one.
...
...
src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
浏览文件 @
5606a2cd
...
@@ -523,13 +523,6 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -523,13 +523,6 @@ public class SpNegoContext implements GSSContextSpi {
valid
=
false
;
valid
=
false
;
}
}
// get the mechanism token
byte
[]
mechToken
=
initToken
.
getMechToken
();
if
(
mechToken
==
null
)
{
throw
new
GSSException
(
GSSException
.
FAILURE
,
-
1
,
"mechToken is missing"
);
}
/*
/*
* Select the best match between the list of mechs
* Select the best match between the list of mechs
* that the initiator requested and the list that
* that the initiator requested and the list that
...
@@ -545,7 +538,19 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -545,7 +538,19 @@ public class SpNegoContext implements GSSContextSpi {
internal_mech
=
mech_wanted
;
internal_mech
=
mech_wanted
;
// get the token for mechanism
// get the token for mechanism
byte
[]
accept_token
=
GSS_acceptSecContext
(
mechToken
);
byte
[]
accept_token
;
if
(
mechList
[
0
].
equals
(
mech_wanted
))
{
// get the mechanism token
byte
[]
mechToken
=
initToken
.
getMechToken
();
if
(
mechToken
==
null
)
{
throw
new
GSSException
(
GSSException
.
FAILURE
,
-
1
,
"mechToken is missing"
);
}
accept_token
=
GSS_acceptSecContext
(
mechToken
);
}
else
{
accept_token
=
null
;
}
// verify MIC
// verify MIC
if
(!
GSSUtil
.
useMSInterop
()
&&
valid
)
{
if
(!
GSSUtil
.
useMSInterop
()
&&
valid
)
{
...
@@ -594,9 +599,27 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -594,9 +599,27 @@ public class SpNegoContext implements GSSContextSpi {
retVal
=
targToken
.
getEncoded
();
retVal
=
targToken
.
getEncoded
();
}
else
if
(
state
==
STATE_IN_PROCESS
)
{
}
else
if
(
state
==
STATE_IN_PROCESS
)
{
// read data
byte
[]
token
=
new
byte
[
is
.
available
()];
SpNegoToken
.
readFully
(
is
,
token
);
if
(
DEBUG
)
{
System
.
out
.
println
(
"SpNegoContext.acceptSecContext: "
+
"receiving token = "
+
SpNegoToken
.
getHexBytes
(
token
));
}
// read the SPNEGO token
// token will be validated when parsing
NegTokenTarg
inputToken
=
new
NegTokenTarg
(
token
);
if
(
DEBUG
)
{
System
.
out
.
println
(
"SpNegoContext.acceptSecContext: "
+
"received token of type = "
+
SpNegoToken
.
getTokenName
(
inputToken
.
getType
()));
}
// read the token
// read the token
byte
[]
client_token
=
new
byte
[
is
.
available
()];
byte
[]
client_token
=
inputToken
.
getResponseToken
();
SpNegoToken
.
readFully
(
is
,
client_token
);
byte
[]
accept_token
=
GSS_acceptSecContext
(
client_token
);
byte
[]
accept_token
=
GSS_acceptSecContext
(
client_token
);
if
(
accept_token
==
null
)
{
if
(
accept_token
==
null
)
{
valid
=
false
;
valid
=
false
;
...
@@ -1055,7 +1078,7 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -1055,7 +1078,7 @@ public class SpNegoContext implements GSSContextSpi {
* This is only valid on the acceptor side of the context.
* This is only valid on the acceptor side of the context.
* @return GSSCredentialSpi object for the delegated credential
* @return GSSCredentialSpi object for the delegated credential
* @exception GSSException
* @exception GSSException
* @see GSSContext#get
DelegCred
State
* @see GSSContext#get
CredDeleg
State
*/
*/
public
final
GSSCredentialSpi
getDelegCred
()
throws
GSSException
{
public
final
GSSCredentialSpi
getDelegCred
()
throws
GSSException
{
if
(
state
!=
STATE_IN_PROCESS
&&
state
!=
STATE_DONE
)
if
(
state
!=
STATE_IN_PROCESS
&&
state
!=
STATE_DONE
)
...
...
src/share/classes/sun/security/tools/keytool/Resources.java
浏览文件 @
5606a2cd
...
@@ -336,7 +336,7 @@ public class Resources extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources extends java.util.ListResourceBundle {
{
"New.prompt."
,
"New {0}: "
},
{
"New.prompt."
,
"New {0}: "
},
{
"Passwords.must.differ"
,
"Passwords must differ"
},
{
"Passwords.must.differ"
,
"Passwords must differ"
},
{
"Re.enter.new.prompt."
,
"Re-enter new {0}: "
},
{
"Re.enter.new.prompt."
,
"Re-enter new {0}: "
},
{
"Re.enter.pass
p
word."
,
"Re-enter password: "
},
{
"Re.enter.password."
,
"Re-enter password: "
},
{
"Re.enter.new.password."
,
"Re-enter new password: "
},
{
"Re.enter.new.password."
,
"Re-enter new password: "
},
{
"They.don.t.match.Try.again"
,
"They don't match. Try again"
},
{
"They.don.t.match.Try.again"
,
"They don't match. Try again"
},
{
"Enter.prompt.alias.name."
,
"Enter {0} alias name: "
},
{
"Enter.prompt.alias.name."
,
"Enter {0} alias name: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_de.java
浏览文件 @
5606a2cd
...
@@ -336,7 +336,7 @@ public class Resources_de extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_de extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Neues {0}: "
},
{
"New.prompt."
,
"Neues {0}: "
},
{
"Passwords.must.differ"
,
"Kennw\u00F6rter m\u00FCssen sich unterscheiden"
},
{
"Passwords.must.differ"
,
"Kennw\u00F6rter m\u00FCssen sich unterscheiden"
},
{
"Re.enter.new.prompt."
,
"Neues {0} erneut eingeben: "
},
{
"Re.enter.new.prompt."
,
"Neues {0} erneut eingeben: "
},
{
"Re.enter.pass
p
word."
,
"Geben Sie das Kennwort erneut ein: "
},
{
"Re.enter.password."
,
"Geben Sie das Kennwort erneut ein: "
},
{
"Re.enter.new.password."
,
"Neues Kennwort erneut eingeben: "
},
{
"Re.enter.new.password."
,
"Neues Kennwort erneut eingeben: "
},
{
"They.don.t.match.Try.again"
,
"Keine \u00DCbereinstimmung. Wiederholen Sie den Vorgang"
},
{
"They.don.t.match.Try.again"
,
"Keine \u00DCbereinstimmung. Wiederholen Sie den Vorgang"
},
{
"Enter.prompt.alias.name."
,
"{0}-Aliasnamen eingeben: "
},
{
"Enter.prompt.alias.name."
,
"{0}-Aliasnamen eingeben: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_es.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_es extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_es extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Nuevo {0}: "
},
{
"New.prompt."
,
"Nuevo {0}: "
},
{
"Passwords.must.differ"
,
"Las contrase\u00F1as deben ser distintas"
},
{
"Passwords.must.differ"
,
"Las contrase\u00F1as deben ser distintas"
},
{
"Re.enter.new.prompt."
,
"Vuelva a escribir el nuevo {0}: "
},
{
"Re.enter.new.prompt."
,
"Vuelva a escribir el nuevo {0}: "
},
{
"Re.enter.pass
p
word."
,
"Vuelva a introducir la contrase\u00F1a: "
},
{
"Re.enter.password."
,
"Vuelva a introducir la contrase\u00F1a: "
},
{
"Re.enter.new.password."
,
"Volver a escribir la contrase\u00F1a nueva: "
},
{
"Re.enter.new.password."
,
"Volver a escribir la contrase\u00F1a nueva: "
},
{
"They.don.t.match.Try.again"
,
"No coinciden. Int\u00E9ntelo de nuevo"
},
{
"They.don.t.match.Try.again"
,
"No coinciden. Int\u00E9ntelo de nuevo"
},
{
"Enter.prompt.alias.name."
,
"Escriba el nombre de alias de {0}: "
},
{
"Enter.prompt.alias.name."
,
"Escriba el nombre de alias de {0}: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_fr.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_fr extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_fr extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Nouveau {0} : "
},
{
"New.prompt."
,
"Nouveau {0} : "
},
{
"Passwords.must.differ"
,
"Les mots de passe doivent diff\u00E9rer"
},
{
"Passwords.must.differ"
,
"Les mots de passe doivent diff\u00E9rer"
},
{
"Re.enter.new.prompt."
,
"Indiquez encore le nouveau {0} : "
},
{
"Re.enter.new.prompt."
,
"Indiquez encore le nouveau {0} : "
},
{
"Re.enter.pass
p
word."
,
"R\u00E9p\u00E9tez le mot de passe : "
},
{
"Re.enter.password."
,
"R\u00E9p\u00E9tez le mot de passe : "
},
{
"Re.enter.new.password."
,
"Ressaisissez le nouveau mot de passe : "
},
{
"Re.enter.new.password."
,
"Ressaisissez le nouveau mot de passe : "
},
{
"They.don.t.match.Try.again"
,
"Ils sont diff\u00E9rents. R\u00E9essayez."
},
{
"They.don.t.match.Try.again"
,
"Ils sont diff\u00E9rents. R\u00E9essayez."
},
{
"Enter.prompt.alias.name."
,
"Indiquez le nom d''alias {0} : "
},
{
"Enter.prompt.alias.name."
,
"Indiquez le nom d''alias {0} : "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_it.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_it extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_it extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Nuova {0}: "
},
{
"New.prompt."
,
"Nuova {0}: "
},
{
"Passwords.must.differ"
,
"Le password non devono coincidere"
},
{
"Passwords.must.differ"
,
"Le password non devono coincidere"
},
{
"Re.enter.new.prompt."
,
"Reimmettere un nuovo valore per {0}: "
},
{
"Re.enter.new.prompt."
,
"Reimmettere un nuovo valore per {0}: "
},
{
"Re.enter.pass
p
word."
,
"Reimmettere la password: "
},
{
"Re.enter.password."
,
"Reimmettere la password: "
},
{
"Re.enter.new.password."
,
"Immettere nuovamente la nuova password: "
},
{
"Re.enter.new.password."
,
"Immettere nuovamente la nuova password: "
},
{
"They.don.t.match.Try.again"
,
"Non corrispondono. Riprovare."
},
{
"They.don.t.match.Try.again"
,
"Non corrispondono. Riprovare."
},
{
"Enter.prompt.alias.name."
,
"Immettere nome alias {0}: "
},
{
"Enter.prompt.alias.name."
,
"Immettere nome alias {0}: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_ja.java
浏览文件 @
5606a2cd
...
@@ -248,7 +248,7 @@ public class Resources_ja extends java.util.ListResourceBundle {
...
@@ -248,7 +248,7 @@ public class Resources_ja extends java.util.ListResourceBundle {
"\u65E2\u5B58\u306E\u30A8\u30F3\u30C8\u30EA\u306E\u5225\u540D{0}\u304C\u5B58\u5728\u3057\u3066\u3044\u307E\u3059\u3002\u4E0A\u66F8\u304D\u3057\u307E\u3059\u304B\u3002[\u3044\u3044\u3048]: "
},
"\u65E2\u5B58\u306E\u30A8\u30F3\u30C8\u30EA\u306E\u5225\u540D{0}\u304C\u5B58\u5728\u3057\u3066\u3044\u307E\u3059\u3002\u4E0A\u66F8\u304D\u3057\u307E\u3059\u304B\u3002[\u3044\u3044\u3048]: "
},
{
"Too.many.failures.try.later"
,
"\u969C\u5BB3\u304C\u591A\u3059\u304E\u307E\u3059 - \u5F8C\u3067\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"Too.many.failures.try.later"
,
"\u969C\u5BB3\u304C\u591A\u3059\u304E\u307E\u3059 - \u5F8C\u3067\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"Certification.request.stored.in.file.filename."
,
{
"Certification.request.stored.in.file.filename."
,
"\u8A
3C\u660E\u66F8
\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30D5\u30A1\u30A4\u30EB<{0}>\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F"
},
"\u8A
8D\u8A3C
\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30D5\u30A1\u30A4\u30EB<{0}>\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F"
},
{
"Submit.this.to.your.CA"
,
"\u3053\u308C\u3092CA\u306B\u63D0\u51FA\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"Submit.this.to.your.CA"
,
"\u3053\u308C\u3092CA\u306B\u63D0\u51FA\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"if.alias.not.specified.destalias.and.srckeypass.must.not.be.specified"
,
{
"if.alias.not.specified.destalias.and.srckeypass.must.not.be.specified"
,
"\u5225\u540D\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u3001\u51FA\u529B\u5148\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u5225\u540D\u304A\u3088\u3073\u30BD\u30FC\u30B9\u30FB\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093"
},
"\u5225\u540D\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u3001\u51FA\u529B\u5148\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u5225\u540D\u304A\u3088\u3073\u30BD\u30FC\u30B9\u30FB\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093"
},
...
@@ -336,7 +336,7 @@ public class Resources_ja extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_ja extends java.util.ListResourceBundle {
{
"New.prompt."
,
"\u65B0\u898F{0}: "
},
{
"New.prompt."
,
"\u65B0\u898F{0}: "
},
{
"Passwords.must.differ"
,
"\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u7570\u306A\u3063\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"
},
{
"Passwords.must.differ"
,
"\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u7570\u306A\u3063\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"
},
{
"Re.enter.new.prompt."
,
"\u65B0\u898F{0}\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Re.enter.new.prompt."
,
"\u65B0\u898F{0}\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Re.enter.pass
p
word."
,
"\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Re.enter.password."
,
"\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Re.enter.new.password."
,
"\u65B0\u898F\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Re.enter.new.password."
,
"\u65B0\u898F\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"They.don.t.match.Try.again"
,
"\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u3082\u3046\u4E00\u5EA6\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"They.don.t.match.Try.again"
,
"\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u3082\u3046\u4E00\u5EA6\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044"
},
{
"Enter.prompt.alias.name."
,
"{0}\u306E\u5225\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
{
"Enter.prompt.alias.name."
,
"{0}\u306E\u5225\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_ko.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_ko extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_ko extends java.util.ListResourceBundle {
{
"New.prompt."
,
"\uC0C8 {0}: "
},
{
"New.prompt."
,
"\uC0C8 {0}: "
},
{
"Passwords.must.differ"
,
"\uBE44\uBC00\uBC88\uD638\uB294 \uB2EC\uB77C\uC57C \uD569\uB2C8\uB2E4."
},
{
"Passwords.must.differ"
,
"\uBE44\uBC00\uBC88\uD638\uB294 \uB2EC\uB77C\uC57C \uD569\uB2C8\uB2E4."
},
{
"Re.enter.new.prompt."
,
"\uC0C8 {0} \uB2E4\uC2DC \uC785\uB825: "
},
{
"Re.enter.new.prompt."
,
"\uC0C8 {0} \uB2E4\uC2DC \uC785\uB825: "
},
{
"Re.enter.pass
p
word."
,
"\uBE44\uBC00\uBC88\uD638 \uB2E4\uC2DC \uC785\uB825: "
},
{
"Re.enter.password."
,
"\uBE44\uBC00\uBC88\uD638 \uB2E4\uC2DC \uC785\uB825: "
},
{
"Re.enter.new.password."
,
"\uC0C8 \uBE44\uBC00\uBC88\uD638 \uB2E4\uC2DC \uC785\uB825: "
},
{
"Re.enter.new.password."
,
"\uC0C8 \uBE44\uBC00\uBC88\uD638 \uB2E4\uC2DC \uC785\uB825: "
},
{
"They.don.t.match.Try.again"
,
"\uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC2ED\uC2DC\uC624."
},
{
"They.don.t.match.Try.again"
,
"\uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC2ED\uC2DC\uC624."
},
{
"Enter.prompt.alias.name."
,
"{0} \uBCC4\uCE6D \uC774\uB984 \uC785\uB825: "
},
{
"Enter.prompt.alias.name."
,
"{0} \uBCC4\uCE6D \uC774\uB984 \uC785\uB825: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_pt_BR.java
浏览文件 @
5606a2cd
...
@@ -336,7 +336,7 @@ public class Resources_pt_BR extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_pt_BR extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Nova {0}: "
},
{
"New.prompt."
,
"Nova {0}: "
},
{
"Passwords.must.differ"
,
"As senhas devem ser diferentes"
},
{
"Passwords.must.differ"
,
"As senhas devem ser diferentes"
},
{
"Re.enter.new.prompt."
,
"Informe novamente a nova {0}: "
},
{
"Re.enter.new.prompt."
,
"Informe novamente a nova {0}: "
},
{
"Re.enter.pass
p
word."
,
"Redigite a senha: "
},
{
"Re.enter.password."
,
"Redigite a senha: "
},
{
"Re.enter.new.password."
,
"Informe novamente a nova senha: "
},
{
"Re.enter.new.password."
,
"Informe novamente a nova senha: "
},
{
"They.don.t.match.Try.again"
,
"Elas n\u00E3o correspondem. Tente novamente"
},
{
"They.don.t.match.Try.again"
,
"Elas n\u00E3o correspondem. Tente novamente"
},
{
"Enter.prompt.alias.name."
,
"Informe o nome do alias {0}: "
},
{
"Enter.prompt.alias.name."
,
"Informe o nome do alias {0}: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_sv.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_sv extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_sv extends java.util.ListResourceBundle {
{
"New.prompt."
,
"Nytt {0}: "
},
{
"New.prompt."
,
"Nytt {0}: "
},
{
"Passwords.must.differ"
,
"L\u00F6senorden m\u00E5ste vara olika"
},
{
"Passwords.must.differ"
,
"L\u00F6senorden m\u00E5ste vara olika"
},
{
"Re.enter.new.prompt."
,
"Ange nytt {0} igen: "
},
{
"Re.enter.new.prompt."
,
"Ange nytt {0} igen: "
},
{
"Re.enter.pass
p
word."
,
"Ange l\u00F6senord igen: "
},
{
"Re.enter.password."
,
"Ange l\u00F6senord igen: "
},
{
"Re.enter.new.password."
,
"Ange det nya l\u00F6senordet igen: "
},
{
"Re.enter.new.password."
,
"Ange det nya l\u00F6senordet igen: "
},
{
"They.don.t.match.Try.again"
,
"De matchar inte. F\u00F6rs\u00F6k igen"
},
{
"They.don.t.match.Try.again"
,
"De matchar inte. F\u00F6rs\u00F6k igen"
},
{
"Enter.prompt.alias.name."
,
"Ange aliasnamn f\u00F6r {0}: "
},
{
"Enter.prompt.alias.name."
,
"Ange aliasnamn f\u00F6r {0}: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_zh_CN.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle {
{
"New.prompt."
,
"\u65B0{0}: "
},
{
"New.prompt."
,
"\u65B0{0}: "
},
{
"Passwords.must.differ"
,
"\u53E3\u4EE4\u4E0D\u80FD\u76F8\u540C"
},
{
"Passwords.must.differ"
,
"\u53E3\u4EE4\u4E0D\u80FD\u76F8\u540C"
},
{
"Re.enter.new.prompt."
,
"\u91CD\u65B0\u8F93\u5165\u65B0{0}: "
},
{
"Re.enter.new.prompt."
,
"\u91CD\u65B0\u8F93\u5165\u65B0{0}: "
},
{
"Re.enter.pass
p
word."
,
"\u518D\u6B21\u8F93\u5165\u53E3\u4EE4: "
},
{
"Re.enter.password."
,
"\u518D\u6B21\u8F93\u5165\u53E3\u4EE4: "
},
{
"Re.enter.new.password."
,
"\u518D\u6B21\u8F93\u5165\u65B0\u53E3\u4EE4: "
},
{
"Re.enter.new.password."
,
"\u518D\u6B21\u8F93\u5165\u65B0\u53E3\u4EE4: "
},
{
"They.don.t.match.Try.again"
,
"\u5B83\u4EEC\u4E0D\u5339\u914D\u3002\u8BF7\u91CD\u8BD5"
},
{
"They.don.t.match.Try.again"
,
"\u5B83\u4EEC\u4E0D\u5339\u914D\u3002\u8BF7\u91CD\u8BD5"
},
{
"Enter.prompt.alias.name."
,
"\u8F93\u5165{0}\u522B\u540D: "
},
{
"Enter.prompt.alias.name."
,
"\u8F93\u5165{0}\u522B\u540D: "
},
...
...
src/share/classes/sun/security/tools/keytool/Resources_zh_TW.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2000, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -336,7 +336,7 @@ public class Resources_zh_TW extends java.util.ListResourceBundle {
...
@@ -336,7 +336,7 @@ public class Resources_zh_TW extends java.util.ListResourceBundle {
{
"New.prompt."
,
"\u65B0 {0}: "
},
{
"New.prompt."
,
"\u65B0 {0}: "
},
{
"Passwords.must.differ"
,
"\u5FC5\u9808\u662F\u4E0D\u540C\u7684\u5BC6\u78BC"
},
{
"Passwords.must.differ"
,
"\u5FC5\u9808\u662F\u4E0D\u540C\u7684\u5BC6\u78BC"
},
{
"Re.enter.new.prompt."
,
"\u91CD\u65B0\u8F38\u5165\u65B0 {0}: "
},
{
"Re.enter.new.prompt."
,
"\u91CD\u65B0\u8F38\u5165\u65B0 {0}: "
},
{
"Re.enter.pass
p
word."
,
"\u91CD\u65B0\u8F38\u5165\u5BC6\u78BC:"
},
{
"Re.enter.password."
,
"\u91CD\u65B0\u8F38\u5165\u5BC6\u78BC:"
},
{
"Re.enter.new.password."
,
"\u91CD\u65B0\u8F38\u5165\u65B0\u5BC6\u78BC: "
},
{
"Re.enter.new.password."
,
"\u91CD\u65B0\u8F38\u5165\u65B0\u5BC6\u78BC: "
},
{
"They.don.t.match.Try.again"
,
"\u5B83\u5011\u4E0D\u76F8\u7B26\u3002\u8ACB\u91CD\u8A66"
},
{
"They.don.t.match.Try.again"
,
"\u5B83\u5011\u4E0D\u76F8\u7B26\u3002\u8ACB\u91CD\u8A66"
},
{
"Enter.prompt.alias.name."
,
"\u8F38\u5165 {0} \u5225\u540D\u540D\u7A31: "
},
{
"Enter.prompt.alias.name."
,
"\u8F38\u5165 {0} \u5225\u540D\u540D\u7A31: "
},
...
...
src/share/classes/sun/security/util/Debug.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1998, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -104,7 +104,15 @@ public class Debug {
...
@@ -104,7 +104,15 @@ public class Debug {
System
.
err
.
println
(
"codebase=<URL>"
);
System
.
err
.
println
(
"codebase=<URL>"
);
System
.
err
.
println
(
" only dump output if specified codebase"
);
System
.
err
.
println
(
" only dump output if specified codebase"
);
System
.
err
.
println
(
" is being checked"
);
System
.
err
.
println
(
" is being checked"
);
System
.
err
.
println
();
System
.
err
.
println
(
"The following can be used with provider:"
);
System
.
err
.
println
();
System
.
err
.
println
(
"engine=<engines>"
);
System
.
err
.
println
(
" only dump output for the specified list"
);
System
.
err
.
println
(
" of JCA engines. Supported values:"
);
System
.
err
.
println
(
" Cipher, KeyAgreement, KeyGenerator,"
);
System
.
err
.
println
(
" KeyPairGenerator, KeyStore, Mac,"
);
System
.
err
.
println
(
" MessageDigest, SecureRandom, Signature."
);
System
.
err
.
println
();
System
.
err
.
println
();
System
.
err
.
println
(
"Note: Separate multiple options with a comma"
);
System
.
err
.
println
(
"Note: Separate multiple options with a comma"
);
System
.
exit
(
0
);
System
.
exit
(
0
);
...
...
src/share/classes/sun/text/resources/FormatData.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1996, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -154,18 +154,18 @@ public class FormatData extends ParallelListResourceBundle {
...
@@ -154,18 +154,18 @@ public class FormatData extends ParallelListResourceBundle {
},
},
{
"MonthNarrows"
,
{
"MonthNarrows"
,
new
String
[]
{
new
String
[]
{
"
J
"
,
"
1
"
,
"
F
"
,
"
2
"
,
"
M
"
,
"
3
"
,
"
A
"
,
"
4
"
,
"
M
"
,
"
5
"
,
"
J
"
,
"
6
"
,
"
J
"
,
"
7
"
,
"
A
"
,
"
8
"
,
"
S
"
,
"
9
"
,
"
O
"
,
"
10
"
,
"
N
"
,
"
11
"
,
"
D
"
,
"
12
"
,
""
,
""
,
}
}
},
},
...
...
src/share/classes/sun/text/resources/en/FormatData_en.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 1997, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -53,6 +53,23 @@ public class FormatData_en extends ParallelListResourceBundle {
...
@@ -53,6 +53,23 @@ public class FormatData_en extends ParallelListResourceBundle {
// define this method as follows:
// define this method as follows:
// return new Object[][] { };
// return new Object[][] { };
return
new
Object
[][]
{
return
new
Object
[][]
{
{
"MonthNarrows"
,
new
String
[]
{
"J"
,
"F"
,
"M"
,
"A"
,
"M"
,
"J"
,
"J"
,
"A"
,
"S"
,
"O"
,
"N"
,
"D"
,
""
,
}
},
{
"NumberPatterns"
,
{
"NumberPatterns"
,
new
String
[]
{
new
String
[]
{
"#,##0.###;-#,##0.###"
,
// decimal pattern
"#,##0.###;-#,##0.###"
,
// decimal pattern
...
...
src/share/classes/sun/tools/jconsole/resources/messages_ja.properties
浏览文件 @
5606a2cd
...
@@ -103,7 +103,7 @@ HELP_ABOUT_DIALOG_JCONSOLE_VERSION=JConsole\u30D0\u30FC\u30B8\u30E7\u30F3:<br>{0
...
@@ -103,7 +103,7 @@ HELP_ABOUT_DIALOG_JCONSOLE_VERSION=JConsole\u30D0\u30FC\u30B8\u30E7\u30F3:<br>{0
HELP_ABOUT_DIALOG_JAVA_VERSION
=
Java VM
\u
30D0
\u
30FC
\u
30B8
\u
30E7
\u
30F3:<br>{0}
HELP_ABOUT_DIALOG_JAVA_VERSION
=
Java VM
\u
30D0
\u
30FC
\u
30B8
\u
30E7
\u
30F3:<br>{0}
HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME
=
\u
30DE
\u
30B9
\u
30C8
\u
30D8
\u
30C3
\u
30C9
\u
56F3
\u
5F62
HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME
=
\u
30DE
\u
30B9
\u
30C8
\u
30D8
\u
30C3
\u
30C9
\u
56F3
\u
5F62
HELP_ABOUT_DIALOG_MASTHEAD_TITLE
=
JConsole
\u
306B
\u3064\u3044\u3066
HELP_ABOUT_DIALOG_MASTHEAD_TITLE
=
JConsole
\u
306B
\u3064\u3044\u3066
HELP_ABOUT_DIALOG_TITLE
=
JConsole:
\u
8A73
\u
7D30
HELP_ABOUT_DIALOG_TITLE
=
JConsole:
\u
60C5
\u5831
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL
=
http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL
=
http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE
=
JConsole
\u
306B
\u3064\u3044\u3066
(&A)
HELP_MENU_ABOUT_TITLE
=
JConsole
\u
306B
\u3064\u3044\u3066
(&A)
HELP_MENU_USER_GUIDE_TITLE
=
\u
30AA
\u
30F3
\u
30E9
\u
30A4
\u
30F3
\u
30FB
\u
30E6
\u
30FC
\u
30B6
\u
30FC
\u
30FB
\u
30AC
\u
30A4
\u
30C9(&U)
HELP_MENU_USER_GUIDE_TITLE
=
\u
30AA
\u
30F3
\u
30E9
\u
30A4
\u
30F3
\u
30FB
\u
30E6
\u
30FC
\u
30B6
\u
30FC
\u
30FB
\u
30AC
\u
30A4
\u
30C9(&U)
...
...
src/share/native/sun/security/ec/ECC_JNI.cpp
浏览文件 @
5606a2cd
...
@@ -41,7 +41,9 @@ extern "C" {
...
@@ -41,7 +41,9 @@ extern "C" {
void
ThrowException
(
JNIEnv
*
env
,
const
char
*
exceptionName
)
void
ThrowException
(
JNIEnv
*
env
,
const
char
*
exceptionName
)
{
{
jclass
exceptionClazz
=
env
->
FindClass
(
exceptionName
);
jclass
exceptionClazz
=
env
->
FindClass
(
exceptionName
);
if
(
exceptionClazz
!=
NULL
)
{
env
->
ThrowNew
(
exceptionClazz
,
NULL
);
env
->
ThrowNew
(
exceptionClazz
,
NULL
);
}
}
}
/*
/*
...
@@ -80,7 +82,6 @@ jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
...
@@ -80,7 +82,6 @@ jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
return
jEncodedBytes
;
return
jEncodedBytes
;
}
}
/*
/*
* Class: sun_security_ec_ECKeyPairGenerator
* Class: sun_security_ec_ECKeyPairGenerator
* Method: generateECKeyPair
* Method: generateECKeyPair
...
@@ -103,6 +104,9 @@ JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
...
@@ -103,6 +104,9 @@ JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
data
=
params_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
if
(
params_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Fill a new ECParams using the supplied OID
// Fill a new ECParams using the supplied OID
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
...
@@ -170,6 +174,7 @@ cleanup:
...
@@ -170,6 +174,7 @@ cleanup:
SECITEM_FreeItem
(
&
privKey
->
publicValue
,
B_FALSE
);
SECITEM_FreeItem
(
&
privKey
->
publicValue
,
B_FALSE
);
free
(
privKey
);
free
(
privKey
);
}
}
if
(
pSeedBuffer
)
{
if
(
pSeedBuffer
)
{
delete
[]
pSeedBuffer
;
delete
[]
pSeedBuffer
;
}
}
...
@@ -206,6 +211,7 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
...
@@ -206,6 +211,7 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
digest_item
.
len
=
jDigestLength
;
digest_item
.
len
=
jDigestLength
;
ECPrivateKey
privKey
;
ECPrivateKey
privKey
;
privKey
.
privateValue
.
data
=
NULL
;
// Initialize the ECParams struct
// Initialize the ECParams struct
ECParams
*
ecparams
=
NULL
;
ECParams
*
ecparams
=
NULL
;
...
@@ -213,6 +219,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
...
@@ -213,6 +219,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
data
=
params_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
if
(
params_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Fill a new ECParams using the supplied OID
// Fill a new ECParams using the supplied OID
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
...
@@ -226,6 +235,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
...
@@ -226,6 +235,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
privKey
.
privateValue
.
len
=
env
->
GetArrayLength
(
privateKey
);
privKey
.
privateValue
.
len
=
env
->
GetArrayLength
(
privateKey
);
privKey
.
privateValue
.
data
=
privKey
.
privateValue
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
privateKey
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
privateKey
,
0
);
if
(
privKey
.
privateValue
.
data
==
NULL
)
{
goto
cleanup
;
}
// Prepare a buffer for the signature (twice the key length)
// Prepare a buffer for the signature (twice the key length)
pSignedDigestBuffer
=
new
jbyte
[
ecparams
->
order
.
len
*
2
];
pSignedDigestBuffer
=
new
jbyte
[
ecparams
->
order
.
len
*
2
];
...
@@ -245,6 +257,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
...
@@ -245,6 +257,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
// Create new byte array
// Create new byte array
temp
=
env
->
NewByteArray
(
signature_item
.
len
);
temp
=
env
->
NewByteArray
(
signature_item
.
len
);
if
(
temp
==
NULL
)
{
goto
cleanup
;
}
// Copy data from native buffer
// Copy data from native buffer
env
->
SetByteArrayRegion
(
temp
,
0
,
signature_item
.
len
,
pSignedDigestBuffer
);
env
->
SetByteArrayRegion
(
temp
,
0
,
signature_item
.
len
,
pSignedDigestBuffer
);
...
@@ -317,6 +332,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
...
@@ -317,6 +332,9 @@ JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
data
=
params_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
if
(
params_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Fill a new ECParams using the supplied OID
// Fill a new ECParams using the supplied OID
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
...
@@ -369,25 +387,37 @@ JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
...
@@ -369,25 +387,37 @@ JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
(
JNIEnv
*
env
,
jclass
clazz
,
jbyteArray
privateKey
,
jbyteArray
publicKey
,
jbyteArray
encodedParams
)
(
JNIEnv
*
env
,
jclass
clazz
,
jbyteArray
privateKey
,
jbyteArray
publicKey
,
jbyteArray
encodedParams
)
{
{
jbyteArray
jSecret
=
NULL
;
jbyteArray
jSecret
=
NULL
;
ECParams
*
ecparams
=
NULL
;
SECItem
privateValue_item
;
privateValue_item
.
data
=
NULL
;
SECItem
publicValue_item
;
publicValue_item
.
data
=
NULL
;
SECKEYECParams
params_item
;
params_item
.
data
=
NULL
;
// Extract private key value
// Extract private key value
SECItem
privateValue_item
;
privateValue_item
.
len
=
env
->
GetArrayLength
(
privateKey
);
privateValue_item
.
len
=
env
->
GetArrayLength
(
privateKey
);
privateValue_item
.
data
=
privateValue_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
privateKey
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
privateKey
,
0
);
if
(
privateValue_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Extract public key value
// Extract public key value
SECItem
publicValue_item
;
publicValue_item
.
len
=
env
->
GetArrayLength
(
publicKey
);
publicValue_item
.
len
=
env
->
GetArrayLength
(
publicKey
);
publicValue_item
.
data
=
publicValue_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
publicKey
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
publicKey
,
0
);
if
(
publicValue_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Initialize the ECParams struct
// Initialize the ECParams struct
ECParams
*
ecparams
=
NULL
;
SECKEYECParams
params_item
;
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
len
=
env
->
GetArrayLength
(
encodedParams
);
params_item
.
data
=
params_item
.
data
=
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
(
unsigned
char
*
)
env
->
GetByteArrayElements
(
encodedParams
,
0
);
if
(
params_item
.
data
==
NULL
)
{
goto
cleanup
;
}
// Fill a new ECParams using the supplied OID
// Fill a new ECParams using the supplied OID
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
if
(
EC_DecodeParams
(
&
params_item
,
&
ecparams
,
0
)
!=
SECSuccess
)
{
...
@@ -409,6 +439,9 @@ JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
...
@@ -409,6 +439,9 @@ JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
// Create new byte array
// Create new byte array
jSecret
=
env
->
NewByteArray
(
secret_item
.
len
);
jSecret
=
env
->
NewByteArray
(
secret_item
.
len
);
if
(
jSecret
==
NULL
)
{
goto
cleanup
;
}
// Copy bytes from the SECItem buffer to a Java byte array
// Copy bytes from the SECItem buffer to a Java byte array
env
->
SetByteArrayRegion
(
jSecret
,
0
,
secret_item
.
len
,
env
->
SetByteArrayRegion
(
jSecret
,
0
,
secret_item
.
len
,
...
...
src/solaris/classes/sun/awt/X11/XRootWindow.java
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2003, 20
05
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 20
14
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -46,7 +46,8 @@ class XRootWindow extends XBaseWindow {
...
@@ -46,7 +46,8 @@ class XRootWindow extends XBaseWindow {
}
}
private
XRootWindow
()
{
private
XRootWindow
()
{
super
(
new
XCreateWindowParams
(
new
Object
[]
{
DELAYED
,
Boolean
.
TRUE
}));
super
(
new
XCreateWindowParams
(
new
Object
[]
{
DELAYED
,
Boolean
.
TRUE
,
EVENT_MASK
,
XConstants
.
StructureNotifyMask
}));
}
}
public
void
postInit
(
XCreateWindowParams
params
){
public
void
postInit
(
XCreateWindowParams
params
){
...
...
src/solaris/classes/sun/awt/X11/XToolkit.java
浏览文件 @
5606a2cd
...
@@ -2354,9 +2354,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
...
@@ -2354,9 +2354,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
private
static
XEventDispatcher
oops_waiter
;
private
static
XEventDispatcher
oops_waiter
;
private
static
boolean
oops_updated
;
private
static
boolean
oops_updated
;
private
static
boolean
oops_failed
;
private
static
boolean
oops_move
;
private
XAtom
oops
;
private
static
final
long
WORKAROUND_SLEEP
=
100
;
/**
/**
* @inheritDoc
* @inheritDoc
...
@@ -2367,52 +2365,33 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
...
@@ -2367,52 +2365,33 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
if
(
oops_waiter
==
null
)
{
if
(
oops_waiter
==
null
)
{
oops_waiter
=
new
XEventDispatcher
()
{
oops_waiter
=
new
XEventDispatcher
()
{
public
void
dispatchEvent
(
XEvent
e
)
{
public
void
dispatchEvent
(
XEvent
e
)
{
if
(
e
.
get_type
()
==
XConstants
.
SelectionNotify
)
{
if
(
e
.
get_type
()
==
XConstants
.
ConfigureNotify
)
{
XSelectionEvent
pe
=
e
.
get_xselection
();
// OOPS ConfigureNotify event catched
if
(
pe
.
get_property
()
==
oops
.
getAtom
())
{
oops_updated
=
true
;
oops_updated
=
true
;
awtLockNotifyAll
();
awtLockNotifyAll
();
}
else
if
(
pe
.
get_selection
()
==
XAtom
.
get
(
"WM_S0"
).
getAtom
()
&&
pe
.
get_target
()
==
XAtom
.
get
(
"VERSION"
).
getAtom
()
&&
pe
.
get_property
()
==
0
&&
XlibWrapper
.
XGetSelectionOwner
(
getDisplay
(),
XAtom
.
get
(
"WM_S0"
).
getAtom
())
==
0
)
{
// WM forgot to acquire selection or there is no WM
oops_failed
=
true
;
awtLockNotifyAll
();
}
}
}
}
}
};
};
}
}
if
(
oops
==
null
)
{
oops
=
XAtom
.
get
(
"OOPS"
);
}
awtLock
();
awtLock
();
try
{
try
{
addEventDispatcher
(
win
.
getWindow
(),
oops_waiter
);
addEventDispatcher
(
win
.
getWindow
(),
oops_waiter
);
oops_updated
=
false
;
oops_updated
=
false
;
oops_failed
=
false
;
// Wait for selection notify for oops on win
long
event_number
=
getEventNumber
();
long
event_number
=
getEventNumber
();
XAtom
atom
=
XAtom
.
get
(
"WM_S0"
);
// Generate OOPS ConfigureNotify event
if
(
eventLog
.
isLoggable
(
PlatformLogger
.
Level
.
FINER
))
{
XlibWrapper
.
XMoveWindow
(
getDisplay
(),
win
.
getWindow
(),
oops_move
?
0
:
1
,
0
);
eventLog
.
finer
(
"WM_S0 selection owner {0}"
,
XlibWrapper
.
XGetSelectionOwner
(
getDisplay
(),
atom
.
getAtom
()));
// Change win position each time to avoid system optimization
}
oops_move
=
!
oops_move
;
XlibWrapper
.
XConvertSelection
(
getDisplay
(),
atom
.
getAtom
(),
XAtom
.
get
(
"VERSION"
).
getAtom
(),
oops
.
getAtom
(),
win
.
getWindow
(),
XConstants
.
CurrentTime
);
XSync
();
XSync
();
eventLog
.
finer
(
"
Requested OOPS
"
);
eventLog
.
finer
(
"
Generated OOPS ConfigureNotify event
"
);
long
start
=
System
.
currentTimeMillis
();
long
start
=
System
.
currentTimeMillis
();
while
(!
oops_updated
&&
!
oops_failed
)
{
while
(!
oops_updated
)
{
try
{
try
{
// Wait for OOPS ConfigureNotify event
awtLockWait
(
timeout
);
awtLockWait
(
timeout
);
}
catch
(
InterruptedException
e
)
{
}
catch
(
InterruptedException
e
)
{
throw
new
RuntimeException
(
e
);
throw
new
RuntimeException
(
e
);
...
@@ -2423,20 +2402,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
...
@@ -2423,20 +2402,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
throw
new
OperationTimedOut
(
Long
.
toString
(
System
.
currentTimeMillis
()
-
start
));
throw
new
OperationTimedOut
(
Long
.
toString
(
System
.
currentTimeMillis
()
-
start
));
}
}
}
}
if
(
oops_failed
&&
getEventNumber
()
-
event_number
==
1
)
{
// Don't take into account OOPS ConfigureNotify event
// If selection update failed we can simply wait some time
return
getEventNumber
()
-
event_number
>
1
;
// hoping some events will arrive
awtUnlock
();
eventLog
.
finest
(
"Emergency sleep"
);
try
{
Thread
.
sleep
(
WORKAROUND_SLEEP
);
}
catch
(
InterruptedException
ie
)
{
throw
new
RuntimeException
(
ie
);
}
finally
{
awtLock
();
}
}
return
getEventNumber
()
-
event_number
>
2
;
}
finally
{
}
finally
{
removeEventDispatcher
(
win
.
getWindow
(),
oops_waiter
);
removeEventDispatcher
(
win
.
getWindow
(),
oops_waiter
);
eventLog
.
finer
(
"Exiting syncNativeQueue"
);
eventLog
.
finer
(
"Exiting syncNativeQueue"
);
...
...
src/solaris/native/sun/awt/awt_util.h
浏览文件 @
5606a2cd
...
@@ -52,6 +52,8 @@
...
@@ -52,6 +52,8 @@
*/
*/
extern
XErrorHandler
current_native_xerror_handler
;
extern
XErrorHandler
current_native_xerror_handler
;
Window
get_xawt_root_shell
(
JNIEnv
*
env
);
#endif
/* !HEADLESS */
#endif
/* !HEADLESS */
#ifndef INTERSECTS
#ifndef INTERSECTS
...
...
src/solaris/native/sun/xawt/XlibWrapper.c
浏览文件 @
5606a2cd
...
@@ -2011,10 +2011,14 @@ static Bool exitSecondaryLoop = True;
...
@@ -2011,10 +2011,14 @@ static Bool exitSecondaryLoop = True;
* Toolkit thread to process PropertyNotify or SelectionNotify events.
* Toolkit thread to process PropertyNotify or SelectionNotify events.
*/
*/
static
Bool
static
Bool
secondary_loop_event
(
Display
*
dpy
,
XEvent
*
event
,
char
*
arg
)
{
secondary_loop_event
(
Display
*
dpy
,
XEvent
*
event
,
XPointer
xawt_root_window
)
{
return
(
event
->
type
==
SelectionNotify
||
return
(
event
->
type
==
SelectionNotify
||
event
->
type
==
SelectionClear
||
event
->
type
==
SelectionClear
||
event
->
type
==
PropertyNotify
)
?
True
:
False
;
event
->
type
==
PropertyNotify
||
(
event
->
type
==
ConfigureNotify
&&
event
->
xany
.
window
==
*
(
Window
*
)
xawt_root_window
)
)
?
True
:
False
;
}
}
...
@@ -2025,8 +2029,11 @@ Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent(JNIEnv *env, jclass clazz,
...
@@ -2025,8 +2029,11 @@ Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent(JNIEnv *env, jclass clazz,
AWT_CHECK_HAVE_LOCK_RETURN
(
JNI_FALSE
);
AWT_CHECK_HAVE_LOCK_RETURN
(
JNI_FALSE
);
exitSecondaryLoop
=
False
;
exitSecondaryLoop
=
False
;
Window
xawt_root_window
=
get_xawt_root_shell
(
env
);
while
(
!
exitSecondaryLoop
)
{
while
(
!
exitSecondaryLoop
)
{
if
(
XCheckIfEvent
((
Display
*
)
jlong_to_ptr
(
display
),
(
XEvent
*
)
jlong_to_ptr
(
ptr
),
secondary_loop_event
,
NULL
))
{
if
(
XCheckIfEvent
((
Display
*
)
jlong_to_ptr
(
display
),
(
XEvent
*
)
jlong_to_ptr
(
ptr
),
secondary_loop_event
,
(
XPointer
)
&
xawt_root_window
))
{
return
JNI_TRUE
;
return
JNI_TRUE
;
}
}
timeout
=
(
timeout
<
AWT_SECONDARY_LOOP_TIMEOUT
)
?
(
timeout
<<
1
)
:
AWT_SECONDARY_LOOP_TIMEOUT
;
timeout
=
(
timeout
<
AWT_SECONDARY_LOOP_TIMEOUT
)
?
(
timeout
<<
1
)
:
AWT_SECONDARY_LOOP_TIMEOUT
;
...
...
src/windows/native/sun/java2d/windows/GDIRenderer.cpp
浏览文件 @
5606a2cd
...
@@ -670,7 +670,7 @@ Java_sun_java2d_windows_GDIRenderer_doFillPoly
...
@@ -670,7 +670,7 @@ Java_sun_java2d_windows_GDIRenderer_doFillPoly
if
(
ypoints
!=
NULL
)
{
if
(
ypoints
!=
NULL
)
{
pPoints
=
TransformPoly
(
xpoints
,
ypoints
,
transx
,
transy
,
pPoints
=
TransformPoly
(
xpoints
,
ypoints
,
transx
,
transy
,
tmpPts
,
&
npoints
,
FALSE
,
FALSE
);
tmpPts
,
&
npoints
,
FALSE
,
FALSE
);
env
->
ReleasePrimitiveArrayCritical
(
ypointsarray
,
x
points
,
JNI_ABORT
);
env
->
ReleasePrimitiveArrayCritical
(
ypointsarray
,
y
points
,
JNI_ABORT
);
}
}
env
->
ReleasePrimitiveArrayCritical
(
xpointsarray
,
xpoints
,
JNI_ABORT
);
env
->
ReleasePrimitiveArrayCritical
(
xpointsarray
,
xpoints
,
JNI_ABORT
);
}
}
...
...
src/windows/native/sun/security/mscapi/security.cpp
浏览文件 @
5606a2cd
/*
/*
* Copyright (c) 2005, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 201
4
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -74,7 +74,10 @@ ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
...
@@ -74,7 +74,10 @@ ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
const
char
*
pszHashAlgorithm
=
NULL
;
const
char
*
pszHashAlgorithm
=
NULL
;
ALG_ID
algId
=
0
;
ALG_ID
algId
=
0
;
pszHashAlgorithm
=
env
->
GetStringUTFChars
(
jHashAlgorithm
,
NULL
);
if
((
pszHashAlgorithm
=
env
->
GetStringUTFChars
(
jHashAlgorithm
,
NULL
))
==
NULL
)
{
return
algId
;
}
if
((
strcmp
(
"SHA"
,
pszHashAlgorithm
)
==
0
)
||
if
((
strcmp
(
"SHA"
,
pszHashAlgorithm
)
==
0
)
||
(
strcmp
(
"SHA1"
,
pszHashAlgorithm
)
==
0
)
||
(
strcmp
(
"SHA1"
,
pszHashAlgorithm
)
==
0
)
||
...
@@ -179,7 +182,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
...
@@ -179,7 +182,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
*/
*/
if
(
length
<
0
)
{
if
(
length
<
0
)
{
length
=
env
->
GetArrayLength
(
seed
);
length
=
env
->
GetArrayLength
(
seed
);
reseedBytes
=
env
->
GetByteArrayElements
(
seed
,
0
);
if
((
reseedBytes
=
env
->
GetByteArrayElements
(
seed
,
0
))
==
NULL
)
{
__leave
;
}
if
(
::
CryptGenRandom
(
if
(
::
CryptGenRandom
(
hCryptProv
,
hCryptProv
,
...
@@ -211,7 +216,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
...
@@ -211,7 +216,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
}
else
{
// length == 0
}
else
{
// length == 0
length
=
env
->
GetArrayLength
(
seed
);
length
=
env
->
GetArrayLength
(
seed
);
seedBytes
=
env
->
GetByteArrayElements
(
seed
,
0
);
if
((
seedBytes
=
env
->
GetByteArrayElements
(
seed
,
0
))
==
NULL
)
{
__leave
;
}
if
(
::
CryptGenRandom
(
if
(
::
CryptGenRandom
(
hCryptProv
,
hCryptProv
,
...
@@ -275,7 +282,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh
...
@@ -275,7 +282,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh
__try
__try
{
{
// Open a system certificate store.
// Open a system certificate store.
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
);
if
((
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
))
==
NULL
)
{
__leave
;
}
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
==
NULL
)
{
...
@@ -710,7 +720,10 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSAKeyPairGenerator_generateR
...
@@ -710,7 +720,10 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSAKeyPairGenerator_generateR
__try
__try
{
{
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
);
if
((
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
))
==
NULL
)
{
__leave
;
}
// Acquire a CSP context (create a new key container).
// Acquire a CSP context (create a new key container).
// Prefer a PROV_RSA_AES CSP, when available, due to its support
// Prefer a PROV_RSA_AES CSP, when available, due to its support
...
@@ -847,7 +860,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate
...
@@ -847,7 +860,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_storeCertificate
__try
__try
{
{
// Open a system certificate store.
// Open a system certificate store.
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
);
if
((
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
))
==
NULL
)
{
__leave
;
}
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
ThrowException
(
env
,
KEYSTORE_EXCEPTION
,
GetLastError
());
ThrowException
(
env
,
KEYSTORE_EXCEPTION
,
GetLastError
());
__leave
;
__leave
;
...
@@ -1086,7 +1102,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate
...
@@ -1086,7 +1102,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate
__try
__try
{
{
// Open a system certificate store.
// Open a system certificate store.
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
);
if
((
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
))
==
NULL
)
{
__leave
;
}
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
ThrowException
(
env
,
KEYSTORE_EXCEPTION
,
GetLastError
());
ThrowException
(
env
,
KEYSTORE_EXCEPTION
,
GetLastError
());
__leave
;
__leave
;
...
@@ -1123,7 +1142,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate
...
@@ -1123,7 +1142,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate
cchNameString
);
cchNameString
);
// Compare the certificate's friendly name with supplied alias name
// Compare the certificate's friendly name with supplied alias name
pszCertAliasName
=
env
->
GetStringUTFChars
(
jCertAliasName
,
NULL
);
if
((
pszCertAliasName
=
env
->
GetStringUTFChars
(
jCertAliasName
,
NULL
))
==
NULL
)
{
__leave
;
}
if
(
strcmp
(
pszCertAliasName
,
pszNameString
)
==
0
)
{
if
(
strcmp
(
pszCertAliasName
,
pszNameString
)
==
0
)
{
// Only delete the certificate if the alias names matches
// Only delete the certificate if the alias names matches
...
@@ -1181,7 +1203,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer
...
@@ -1181,7 +1203,10 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer
__try
__try
{
{
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
);
if
((
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
))
==
NULL
)
{
__leave
;
}
// Destroying the default key container is not permitted
// Destroying the default key container is not permitted
// (because it may contain more one keypair).
// (because it may contain more one keypair).
...
@@ -1234,8 +1259,14 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_findCertificateUsingA
...
@@ -1234,8 +1259,14 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_findCertificateUsingA
__try
__try
{
{
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
);
if
((
pszCertStoreName
=
env
->
GetStringUTFChars
(
jCertStoreName
,
NULL
))
pszCertAliasName
=
env
->
GetStringUTFChars
(
jCertAliasName
,
NULL
);
==
NULL
)
{
__leave
;
}
if
((
pszCertAliasName
=
env
->
GetStringUTFChars
(
jCertAliasName
,
NULL
))
==
NULL
)
{
__leave
;
}
// Open a system certificate store.
// Open a system certificate store.
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
if
((
hCertStore
=
::
CertOpenSystemStore
(
NULL
,
pszCertStoreName
))
==
NULL
)
{
...
@@ -1530,7 +1561,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent
...
@@ -1530,7 +1561,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent
__try
{
__try
{
jsize
length
=
env
->
GetArrayLength
(
jKeyBlob
);
jsize
length
=
env
->
GetArrayLength
(
jKeyBlob
);
keyBlob
=
env
->
GetByteArrayElements
(
jKeyBlob
,
0
);
if
((
keyBlob
=
env
->
GetByteArrayElements
(
jKeyBlob
,
0
))
==
NULL
)
{
__leave
;
}
PUBLICKEYSTRUC
*
pPublicKeyStruc
=
(
PUBLICKEYSTRUC
*
)
keyBlob
;
PUBLICKEYSTRUC
*
pPublicKeyStruc
=
(
PUBLICKEYSTRUC
*
)
keyBlob
;
...
@@ -1580,7 +1613,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus
...
@@ -1580,7 +1613,9 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus
__try
{
__try
{
jsize
length
=
env
->
GetArrayLength
(
jKeyBlob
);
jsize
length
=
env
->
GetArrayLength
(
jKeyBlob
);
keyBlob
=
env
->
GetByteArrayElements
(
jKeyBlob
,
0
);
if
((
keyBlob
=
env
->
GetByteArrayElements
(
jKeyBlob
,
0
))
==
NULL
)
{
__leave
;
}
PUBLICKEYSTRUC
*
pPublicKeyStruc
=
(
PUBLICKEYSTRUC
*
)
keyBlob
;
PUBLICKEYSTRUC
*
pPublicKeyStruc
=
(
PUBLICKEYSTRUC
*
)
keyBlob
;
...
@@ -1632,6 +1667,9 @@ int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
...
@@ -1632,6 +1667,9 @@ int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
}
}
jbyte
*
sourceBytes
=
env
->
GetByteArrayElements
(
source
,
0
);
jbyte
*
sourceBytes
=
env
->
GetByteArrayElements
(
source
,
0
);
if
(
sourceBytes
==
NULL
)
{
return
-
1
;
}
// Copy bytes from the end of the source array to the beginning of the
// Copy bytes from the end of the source array to the beginning of the
// destination array (until the destination array is full).
// destination array (until the destination array is full).
...
@@ -1740,45 +1778,61 @@ jbyteArray generateKeyBlob(
...
@@ -1740,45 +1778,61 @@ jbyteArray generateKeyBlob(
}
}
// The length argument must be the smaller of jPublicExponentLength
// The length argument must be the smaller of jPublicExponentLength
// and sizeof(pRsaPubKey->pubkey)
// and sizeof(pRsaPubKey->pubkey)
convertToLittleEndian
(
env
,
jPublicExponent
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jPublicExponent
,
(
jbyte
*
)
&
(
pRsaPubKey
->
pubexp
),
jPublicExponentLength
);
(
jbyte
*
)
&
(
pRsaPubKey
->
pubexp
),
jPublicExponentLength
))
<
0
)
{
__leave
;
}
// Modulus n
// Modulus n
jBlobElement
=
jBlobElement
=
(
jbyte
*
)
(
jBlobBytes
+
sizeof
(
PUBLICKEYSTRUC
)
+
sizeof
(
RSAPUBKEY
));
(
jbyte
*
)
(
jBlobBytes
+
sizeof
(
PUBLICKEYSTRUC
)
+
sizeof
(
RSAPUBKEY
));
jElementLength
=
convertToLittleEndian
(
env
,
jModulus
,
jBlobElement
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jModulus
,
jBlobElement
,
jKeyByteLength
);
jKeyByteLength
))
<
0
)
{
__leave
;
}
if
(
bGeneratePrivateKeyBlob
)
{
if
(
bGeneratePrivateKeyBlob
)
{
// Prime p
// Prime p
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
jElementLength
=
convertToLittleEndian
(
env
,
jPrimeP
,
jBlobElement
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jPrimeP
,
jKeyByteLength
/
2
);
jBlobElement
,
jKeyByteLength
/
2
))
<
0
)
{
__leave
;
}
// Prime q
// Prime q
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
jElementLength
=
convertToLittleEndian
(
env
,
jPrimeQ
,
jBlobElement
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jPrimeQ
,
jKeyByteLength
/
2
);
jBlobElement
,
jKeyByteLength
/
2
))
<
0
)
{
__leave
;
}
// Prime exponent p
// Prime exponent p
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
jElementLength
=
convertToLittleEndian
(
env
,
jExponentP
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jExponentP
,
jBlobElement
,
jKeyByteLength
/
2
);
jBlobElement
,
jKeyByteLength
/
2
))
<
0
)
{
__leave
;
}
// Prime exponent q
// Prime exponent q
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
jElementLength
=
convertToLittleEndian
(
env
,
jExponentQ
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jExponentQ
,
jBlobElement
,
jKeyByteLength
/
2
);
jBlobElement
,
jKeyByteLength
/
2
))
<
0
)
{
__leave
;
}
// CRT coefficient
// CRT coefficient
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
jElementLength
=
convertToLittleEndian
(
env
,
jCrtCoefficient
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jCrtCoefficient
,
jBlobElement
,
jKeyByteLength
/
2
);
jBlobElement
,
jKeyByteLength
/
2
))
<
0
)
{
__leave
;
}
// Private exponent
// Private exponent
jBlobElement
+=
jElementLength
;
jBlobElement
+=
jElementLength
;
convertToLittleEndian
(
env
,
jPrivateExponent
,
jBlobElement
,
if
((
jElementLength
=
convertToLittleEndian
(
env
,
jPrivateExponent
,
jKeyByteLength
);
jBlobElement
,
jKeyByteLength
))
<
0
)
{
__leave
;
}
}
}
jBlob
=
env
->
NewByteArray
(
jBlobLength
);
jBlob
=
env
->
NewByteArray
(
jBlobLength
);
...
@@ -1849,9 +1903,15 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey
...
@@ -1849,9 +1903,15 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey
__try
__try
{
{
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
);
if
((
pszKeyContainerName
=
env
->
GetStringUTFChars
(
keyContainerName
,
NULL
))
==
NULL
)
{
__leave
;
}
dwBlobLen
=
env
->
GetArrayLength
(
keyBlob
);
dwBlobLen
=
env
->
GetArrayLength
(
keyBlob
);
pbKeyBlob
=
(
BYTE
*
)
env
->
GetByteArrayElements
(
keyBlob
,
0
);
if
((
pbKeyBlob
=
(
BYTE
*
)
env
->
GetByteArrayElements
(
keyBlob
,
0
))
==
NULL
)
{
__leave
;
}
// Acquire a CSP context (create a new key container).
// Acquire a CSP context (create a new key container).
if
(
::
CryptAcquireContext
(
if
(
::
CryptAcquireContext
(
...
@@ -1923,7 +1983,10 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSASignature_importPublicKey
...
@@ -1923,7 +1983,10 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_RSASignature_importPublicKey
__try
__try
{
{
dwBlobLen
=
env
->
GetArrayLength
(
keyBlob
);
dwBlobLen
=
env
->
GetArrayLength
(
keyBlob
);
pbKeyBlob
=
(
BYTE
*
)
env
->
GetByteArrayElements
(
keyBlob
,
0
);
if
((
pbKeyBlob
=
(
BYTE
*
)
env
->
GetByteArrayElements
(
keyBlob
,
0
))
==
NULL
)
{
__leave
;
}
// Acquire a CSP context (create a new key container).
// Acquire a CSP context (create a new key container).
// Prefer a PROV_RSA_AES CSP, when available, due to its support
// Prefer a PROV_RSA_AES CSP, when available, due to its support
...
...
src/windows/native/sun/windows/awt_Component.cpp
浏览文件 @
5606a2cd
...
@@ -3955,7 +3955,6 @@ void AwtComponent::SendInputMethodEvent(jint id, jstring text,
...
@@ -3955,7 +3955,6 @@ void AwtComponent::SendInputMethodEvent(jint id, jstring text,
DASSERT
(
stringCls
);
DASSERT
(
stringCls
);
CHECK_NULL
(
stringCls
);
CHECK_NULL
(
stringCls
);
clauseReading
=
env
->
NewObjectArray
(
cClause
,
stringCls
,
NULL
);
clauseReading
=
env
->
NewObjectArray
(
cClause
,
stringCls
,
NULL
);
env
->
DeleteLocalRef
(
stringCls
);
DASSERT
(
clauseReading
);
DASSERT
(
clauseReading
);
CHECK_NULL
(
clauseReading
);
CHECK_NULL
(
clauseReading
);
for
(
int
i
=
0
;
i
<
cClause
;
i
++
)
env
->
SetObjectArrayElement
(
clauseReading
,
i
,
rgClauseReading
[
i
]);
for
(
int
i
=
0
;
i
<
cClause
;
i
++
)
env
->
SetObjectArrayElement
(
clauseReading
,
i
,
rgClauseReading
[
i
]);
...
...
src/windows/native/sun/windows/awt_TextArea.cpp
浏览文件 @
5606a2cd
...
@@ -47,16 +47,12 @@ struct ReplaceTextStruct {
...
@@ -47,16 +47,12 @@ struct ReplaceTextStruct {
jfieldID
AwtTextArea
::
scrollbarVisibilityID
;
jfieldID
AwtTextArea
::
scrollbarVisibilityID
;
WNDPROC
AwtTextArea
::
sm_pDefWindowProc
=
NULL
;
/************************************************************************
/************************************************************************
* AwtTextArea methods
* AwtTextArea methods
*/
*/
AwtTextArea
::
AwtTextArea
()
{
AwtTextArea
::
AwtTextArea
()
{
m_bIgnoreEnChange
=
FALSE
;
m_bCanUndo
=
FALSE
;
m_bCanUndo
=
FALSE
;
m_hEditCtrl
=
NULL
;
m_lHDeltaAccum
=
0
;
m_lHDeltaAccum
=
0
;
m_lVDeltaAccum
=
0
;
m_lVDeltaAccum
=
0
;
}
}
...
@@ -67,10 +63,6 @@ AwtTextArea::~AwtTextArea()
...
@@ -67,10 +63,6 @@ AwtTextArea::~AwtTextArea()
void
AwtTextArea
::
Dispose
()
void
AwtTextArea
::
Dispose
()
{
{
if
(
m_hEditCtrl
!=
NULL
)
{
VERIFY
(
::
DestroyWindow
(
m_hEditCtrl
));
m_hEditCtrl
=
NULL
;
}
AwtTextComponent
::
Dispose
();
AwtTextComponent
::
Dispose
();
}
}
...
@@ -91,10 +83,6 @@ void AwtTextArea::EditSetSel(CHARRANGE &cr) {
...
@@ -91,10 +83,6 @@ void AwtTextArea::EditSetSel(CHARRANGE &cr) {
}
}
}
}
void
AwtTextArea
::
EditGetSel
(
CHARRANGE
&
cr
)
{
SendMessage
(
EM_EXGETSEL
,
0
,
reinterpret_cast
<
LPARAM
>
(
&
cr
));
}
/* Count how many '\n's are there in jStr */
/* Count how many '\n's are there in jStr */
size_t
AwtTextArea
::
CountNewLines
(
JNIEnv
*
env
,
jstring
jStr
,
size_t
maxlen
)
size_t
AwtTextArea
::
CountNewLines
(
JNIEnv
*
env
,
jstring
jStr
,
size_t
maxlen
)
{
{
...
@@ -149,159 +137,6 @@ AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
...
@@ -149,159 +137,6 @@ AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
return
retValue
;
return
retValue
;
}
}
/*
* This routine is a window procedure for the subclass of the standard edit control
* used to generate context menu. RichEdit controls don't have built-in context menu.
* To implement this functionality we have to create an invisible edit control and
* forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control.
* While the edit control context menu is active we intercept the message generated in
* response to particular item selection and forward it back to the RichEdit control.
* (See AwtTextArea::WmContextMenu for more details).
*/
LRESULT
AwtTextArea
::
EditProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
static
BOOL
bContextMenuActive
=
FALSE
;
LRESULT
retValue
=
0
;
MsgRouting
mr
=
mrDoDefault
;
DASSERT
(
::
IsWindow
(
::
GetParent
(
hWnd
)));
switch
(
message
)
{
case
WM_UNDO
:
case
WM_CUT
:
case
WM_COPY
:
case
WM_PASTE
:
case
WM_CLEAR
:
case
EM_SETSEL
:
if
(
bContextMenuActive
)
{
::
SendMessage
(
::
GetParent
(
hWnd
),
message
,
wParam
,
lParam
);
mr
=
mrConsume
;
}
break
;
case
WM_CONTEXTMENU
:
bContextMenuActive
=
TRUE
;
break
;
}
if
(
mr
==
mrDoDefault
)
{
DASSERT
(
sm_pDefWindowProc
!=
NULL
);
retValue
=
::
CallWindowProc
(
sm_pDefWindowProc
,
hWnd
,
message
,
wParam
,
lParam
);
}
if
(
message
==
WM_CONTEXTMENU
)
{
bContextMenuActive
=
FALSE
;
}
return
retValue
;
}
MsgRouting
AwtTextArea
::
WmContextMenu
(
HWND
hCtrl
,
UINT
xPos
,
UINT
yPos
)
{
/* Use the system provided edit control class to generate context menu. */
if
(
m_hEditCtrl
==
NULL
)
{
DWORD
dwStyle
=
WS_CHILD
;
DWORD
dwExStyle
=
0
;
m_hEditCtrl
=
::
CreateWindowEx
(
dwExStyle
,
L"EDIT"
,
L"TEXT"
,
dwStyle
,
0
,
0
,
0
,
0
,
GetHWnd
(),
reinterpret_cast
<
HMENU
>
(
static_cast
<
INT_PTR
>
(
CreateControlID
())),
AwtToolkit
::
GetInstance
().
GetModuleHandle
(),
NULL
);
DASSERT
(
m_hEditCtrl
!=
NULL
);
if
(
sm_pDefWindowProc
==
NULL
)
{
sm_pDefWindowProc
=
(
WNDPROC
)
::
GetWindowLongPtr
(
m_hEditCtrl
,
GWLP_WNDPROC
);
}
::
SetLastError
(
0
);
INT_PTR
ret
=
::
SetWindowLongPtr
(
m_hEditCtrl
,
GWLP_WNDPROC
,
(
INT_PTR
)
AwtTextArea
::
EditProc
);
DASSERT
(
ret
!=
0
||
::
GetLastError
()
==
0
);
}
/*
* Tricks on the edit control to ensure that its context menu has
* the correct set of enabled items according to the RichEdit state.
*/
::
SetWindowText
(
m_hEditCtrl
,
TEXT
(
"TEXT"
));
if
(
m_bCanUndo
==
TRUE
&&
SendMessage
(
EM_CANUNDO
))
{
/* Enable 'Undo' item. */
::
SendMessage
(
m_hEditCtrl
,
WM_CHAR
,
'A'
,
0
);
}
{
/*
* Initial selection for the edit control - (0,1).
* This enables 'Cut', 'Copy' and 'Delete' and 'Select All'.
*/
INT
nStart
=
0
;
INT
nEnd
=
1
;
if
(
SendMessage
(
EM_SELECTIONTYPE
)
==
SEL_EMPTY
)
{
/*
* RichEdit selection is empty - clear selection of the edit control.
* This disables 'Cut', 'Copy' and 'Delete'.
*/
nStart
=
-
1
;
nEnd
=
0
;
}
else
{
CHARRANGE
cr
;
EditGetSel
(
cr
);
/* Check if all the text is selected. */
if
(
cr
.
cpMin
==
0
)
{
int
len
=
::
GetWindowTextLength
(
GetHWnd
());
if
(
cr
.
cpMin
==
0
&&
cr
.
cpMax
>=
len
)
{
/*
* All the text is selected in RichEdit - select all the
* text in the edit control. This disables 'Select All'.
*/
nStart
=
0
;
nEnd
=
-
1
;
}
}
}
::
SendMessage
(
m_hEditCtrl
,
EM_SETSEL
,
(
WPARAM
)
nStart
,
(
LPARAM
)
nEnd
);
}
/* Disable 'Paste' item if the RichEdit control is read-only. */
::
SendMessage
(
m_hEditCtrl
,
EM_SETREADONLY
,
GetStyle
()
&
ES_READONLY
?
TRUE
:
FALSE
,
0
);
POINT
p
;
p
.
x
=
xPos
;
p
.
y
=
yPos
;
/*
* If the context menu is requested with SHIFT+F10 or VK_APPS key,
* we position its top left corner to the center of the RichEdit
* client rect.
*/
if
(
p
.
x
==
-
1
&&
p
.
y
==
-
1
)
{
RECT
r
;
VERIFY
(
::
GetClientRect
(
GetHWnd
(),
&
r
));
p
.
x
=
(
r
.
left
+
r
.
right
)
/
2
;
p
.
y
=
(
r
.
top
+
r
.
bottom
)
/
2
;
VERIFY
(
::
ClientToScreen
(
GetHWnd
(),
&
p
));
}
// The context menu steals focus from the proxy.
// So, set the focus-restore flag up.
SetRestoreFocus
(
TRUE
);
::
SendMessage
(
m_hEditCtrl
,
WM_CONTEXTMENU
,
(
WPARAM
)
m_hEditCtrl
,
MAKELPARAM
(
p
.
x
,
p
.
y
));
SetRestoreFocus
(
FALSE
);
return
mrConsume
;
}
MsgRouting
MsgRouting
AwtTextArea
::
WmNcHitTest
(
UINT
x
,
UINT
y
,
LRESULT
&
retVal
)
AwtTextArea
::
WmNcHitTest
(
UINT
x
,
UINT
y
,
LRESULT
&
retVal
)
{
{
...
@@ -313,28 +148,9 @@ AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
...
@@ -313,28 +148,9 @@ AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
}
}
MsgRouting
AwtTextArea
::
WmNotify
(
UINT
notifyCode
)
{
if
(
notifyCode
==
EN_CHANGE
)
{
/*
* Ignore notifications if the text hasn't been changed.
* EN_CHANGE sent on character formatting changes as well.
*/
if
(
m_bIgnoreEnChange
==
FALSE
)
{
m_bCanUndo
=
TRUE
;
DoCallback
(
"valueChanged"
,
"()V"
);
}
else
{
m_bCanUndo
=
FALSE
;
}
}
return
mrDoDefault
;
}
MsgRouting
MsgRouting
AwtTextArea
::
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
)
AwtTextArea
::
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
)
{
{
MsgRouting
returnVal
;
/*
/*
* RichEdit 1.0 control starts internal message loop if the
* RichEdit 1.0 control starts internal message loop if the
* left mouse button is pressed while the cursor is not over
* left mouse button is pressed while the cursor is not over
...
@@ -486,26 +302,6 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
...
@@ -486,26 +302,6 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
}
}
delete
msg
;
delete
msg
;
return
mrConsume
;
return
mrConsume
;
}
else
if
(
msg
->
message
==
WM_RBUTTONUP
||
(
msg
->
message
==
WM_SYSKEYDOWN
&&
msg
->
wParam
==
VK_F10
&&
HIBYTE
(
::
GetKeyState
(
VK_SHIFT
))))
{
POINT
p
;
if
(
msg
->
message
==
WM_RBUTTONUP
)
{
VERIFY
(
::
GetCursorPos
(
&
p
));
}
else
{
p
.
x
=
-
1
;
p
.
y
=
-
1
;
}
if
(
!::
PostMessage
(
GetHWnd
(),
WM_CONTEXTMENU
,
(
WPARAM
)
GetHWnd
(),
MAKELPARAM
(
p
.
x
,
p
.
y
)))
{
JNIEnv
*
env
=
(
JNIEnv
*
)
JNU_GetEnv
(
jvm
,
JNI_VERSION_1_2
);
JNU_ThrowInternalError
(
env
,
"Message not posted, native event queue may be full."
);
env
->
ExceptionDescribe
();
env
->
ExceptionClear
();
}
delete
msg
;
return
mrConsume
;
}
else
if
(
msg
->
message
==
WM_MOUSEWHEEL
)
{
}
else
if
(
msg
->
message
==
WM_MOUSEWHEEL
)
{
// 4417236: If there is an old version of RichEd32.dll which
// 4417236: If there is an old version of RichEd32.dll which
// does not provide the mouse wheel scrolling we have to
// does not provide the mouse wheel scrolling we have to
...
@@ -596,15 +392,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
...
@@ -596,15 +392,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
// 4417236: end of fix
// 4417236: end of fix
}
}
/*
return
AwtTextComponent
::
HandleEvent
(
msg
,
synthetic
);
* Store the 'synthetic' parameter so that the WM_PASTE security check
* happens only for synthetic events.
*/
m_synthetic
=
synthetic
;
returnVal
=
AwtComponent
::
HandleEvent
(
msg
,
synthetic
);
m_synthetic
=
FALSE
;
return
returnVal
;
}
}
...
...
src/windows/native/sun/windows/awt_TextArea.h
浏览文件 @
5606a2cd
...
@@ -57,17 +57,11 @@ public:
...
@@ -57,17 +57,11 @@ public:
static
size_t
GetALength
(
JNIEnv
*
env
,
jstring
jStr
,
size_t
maxlen
);
static
size_t
GetALength
(
JNIEnv
*
env
,
jstring
jStr
,
size_t
maxlen
);
LRESULT
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
LRESULT
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
static
LRESULT
CALLBACK
EditProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
MsgRouting
WmEnable
(
BOOL
fEnabled
);
MsgRouting
WmEnable
(
BOOL
fEnabled
);
MsgRouting
WmContextMenu
(
HWND
hCtrl
,
UINT
xPos
,
UINT
yPos
);
MsgRouting
WmNotify
(
UINT
notifyCode
);
MsgRouting
WmNcHitTest
(
UINT
x
,
UINT
y
,
LRESULT
&
retVal
);
MsgRouting
WmNcHitTest
(
UINT
x
,
UINT
y
,
LRESULT
&
retVal
);
MsgRouting
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
);
MsgRouting
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
);
INLINE
void
SetIgnoreEnChange
(
BOOL
b
)
{
m_bIgnoreEnChange
=
b
;
}
virtual
BOOL
InheritsNativeMouseWheelBehavior
();
virtual
BOOL
InheritsNativeMouseWheelBehavior
();
virtual
void
Reshape
(
int
x
,
int
y
,
int
w
,
int
h
);
virtual
void
Reshape
(
int
x
,
int
y
,
int
w
,
int
h
);
...
@@ -81,22 +75,7 @@ public:
...
@@ -81,22 +75,7 @@ public:
protected:
protected:
void
EditSetSel
(
CHARRANGE
&
cr
);
void
EditSetSel
(
CHARRANGE
&
cr
);
void
EditGetSel
(
CHARRANGE
&
cr
);
private:
private:
// RichEdit 1.0 control generates EN_CHANGE notifications not only
// on text changes, but also on any character formatting change.
// This flag is true when the latter case is detected.
BOOL
m_bIgnoreEnChange
;
// RichEdit 1.0 control undoes a character formatting change
// if it is the latest. We don't create our own undo buffer,
// but just prohibit undo in case if the latest operation
// is a formatting change.
BOOL
m_bCanUndo
;
HWND
m_hEditCtrl
;
static
WNDPROC
sm_pDefWindowProc
;
LONG
m_lHDeltaAccum
;
LONG
m_lHDeltaAccum
;
LONG
m_lVDeltaAccum
;
LONG
m_lVDeltaAccum
;
...
...
src/windows/native/sun/windows/awt_TextComponent.cpp
浏览文件 @
5606a2cd
...
@@ -66,6 +66,8 @@ AwtTextComponent::AwtTextComponent() {
...
@@ -66,6 +66,8 @@ AwtTextComponent::AwtTextComponent() {
m_lLastPos
=
-
1
;
m_lLastPos
=
-
1
;
m_isLFonly
=
FALSE
;
m_isLFonly
=
FALSE
;
m_EOLchecked
=
FALSE
;
m_EOLchecked
=
FALSE
;
m_hEditCtrl
=
NULL
;
m_bIgnoreEnChange
=
FALSE
;
// javaEventsMask = 0; // accessibility support
// javaEventsMask = 0; // accessibility support
}
}
...
@@ -213,6 +215,16 @@ done:
...
@@ -213,6 +215,16 @@ done:
return
c
;
return
c
;
}
}
void
AwtTextComponent
::
Dispose
()
{
if
(
m_hEditCtrl
!=
NULL
)
{
VERIFY
(
::
DestroyWindow
(
m_hEditCtrl
));
m_hEditCtrl
=
NULL
;
}
AwtComponent
::
Dispose
();
}
LRESULT
LRESULT
AwtTextComponent
::
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
AwtTextComponent
::
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
...
@@ -322,7 +334,16 @@ MsgRouting
...
@@ -322,7 +334,16 @@ MsgRouting
AwtTextComponent
::
WmNotify
(
UINT
notifyCode
)
AwtTextComponent
::
WmNotify
(
UINT
notifyCode
)
{
{
if
(
notifyCode
==
EN_CHANGE
)
{
if
(
notifyCode
==
EN_CHANGE
)
{
/*
* Ignore notifications if the text hasn't been changed.
* EN_CHANGE sent on character formatting changes as well.
*/
if
(
m_bIgnoreEnChange
==
FALSE
)
{
m_bCanUndo
=
TRUE
;
DoCallback
(
"valueChanged"
,
"()V"
);
DoCallback
(
"valueChanged"
,
"()V"
);
}
else
{
m_bCanUndo
=
FALSE
;
}
}
}
return
mrDoDefault
;
return
mrDoDefault
;
}
}
...
@@ -337,6 +358,28 @@ AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic)
...
@@ -337,6 +358,28 @@ AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic)
{
{
MsgRouting
returnVal
;
MsgRouting
returnVal
;
if
(
msg
->
message
==
WM_RBUTTONUP
||
(
msg
->
message
==
WM_SYSKEYDOWN
&&
msg
->
wParam
==
VK_F10
&&
HIBYTE
(
::
GetKeyState
(
VK_SHIFT
))))
{
POINT
p
;
if
(
msg
->
message
==
WM_RBUTTONUP
)
{
VERIFY
(
::
GetCursorPos
(
&
p
));
}
else
{
p
.
x
=
-
1
;
p
.
y
=
-
1
;
}
if
(
!::
PostMessage
(
GetHWnd
(),
WM_CONTEXTMENU
,
(
WPARAM
)
GetHWnd
(),
MAKELPARAM
(
p
.
x
,
p
.
y
)))
{
JNIEnv
*
env
=
(
JNIEnv
*
)
JNU_GetEnv
(
jvm
,
JNI_VERSION_1_2
);
JNU_ThrowInternalError
(
env
,
"Message not posted, native event queue may be full."
);
env
->
ExceptionDescribe
();
env
->
ExceptionClear
();
}
delete
msg
;
return
mrConsume
;
}
/*
/*
* Store the 'synthetic' parameter so that the WM_PASTE security check
* Store the 'synthetic' parameter so that the WM_PASTE security check
* happens only for synthetic events.
* happens only for synthetic events.
...
@@ -701,6 +744,10 @@ void AwtTextComponent::SetBackgroundColor(COLORREF c) {
...
@@ -701,6 +744,10 @@ void AwtTextComponent::SetBackgroundColor(COLORREF c) {
SendMessage
(
EM_SETBKGNDCOLOR
,
(
WPARAM
)
FALSE
,
(
LPARAM
)
GetBackgroundColor
());
SendMessage
(
EM_SETBKGNDCOLOR
,
(
WPARAM
)
FALSE
,
(
LPARAM
)
GetBackgroundColor
());
}
}
void
AwtTextComponent
::
EditGetSel
(
CHARRANGE
&
cr
)
{
SendMessage
(
EM_EXGETSEL
,
0
,
reinterpret_cast
<
LPARAM
>
(
&
cr
));
}
/************************************************************************
/************************************************************************
* WTextComponentPeer native methods
* WTextComponentPeer native methods
...
@@ -983,6 +1030,161 @@ AwtTextComponent::OleCallback::GetContextMenu(WORD seltype,
...
@@ -983,6 +1030,161 @@ AwtTextComponent::OleCallback::GetContextMenu(WORD seltype,
}
}
/*
* This routine is a window procedure for the subclass of the standard edit control
* used to generate context menu. RichEdit controls don't have built-in context menu.
* To implement this functionality we have to create an invisible edit control and
* forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control.
* While the edit control context menu is active we intercept the message generated in
* response to particular item selection and forward it back to the RichEdit control.
* (See AwtTextArea::WmContextMenu for more details).
*/
WNDPROC
AwtTextComponent
::
sm_pDefWindowProc
=
NULL
;
LRESULT
AwtTextComponent
::
EditProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
static
BOOL
bContextMenuActive
=
FALSE
;
LRESULT
retValue
=
0
;
MsgRouting
mr
=
mrDoDefault
;
DASSERT
(
::
IsWindow
(
::
GetParent
(
hWnd
)));
switch
(
message
)
{
case
WM_UNDO
:
case
WM_CUT
:
case
WM_COPY
:
case
WM_PASTE
:
case
WM_CLEAR
:
case
EM_SETSEL
:
if
(
bContextMenuActive
)
{
::
SendMessage
(
::
GetParent
(
hWnd
),
message
,
wParam
,
lParam
);
mr
=
mrConsume
;
}
break
;
case
WM_CONTEXTMENU
:
bContextMenuActive
=
TRUE
;
break
;
}
if
(
mr
==
mrDoDefault
)
{
DASSERT
(
sm_pDefWindowProc
!=
NULL
);
retValue
=
::
CallWindowProc
(
sm_pDefWindowProc
,
hWnd
,
message
,
wParam
,
lParam
);
}
if
(
message
==
WM_CONTEXTMENU
)
{
bContextMenuActive
=
FALSE
;
}
return
retValue
;
}
MsgRouting
AwtTextComponent
::
WmContextMenu
(
HWND
hCtrl
,
UINT
xPos
,
UINT
yPos
)
{
/* Use the system provided edit control class to generate context menu. */
if
(
m_hEditCtrl
==
NULL
)
{
DWORD
dwStyle
=
WS_CHILD
;
DWORD
dwExStyle
=
0
;
m_hEditCtrl
=
::
CreateWindowEx
(
dwExStyle
,
L"EDIT"
,
L"TEXT"
,
dwStyle
,
0
,
0
,
0
,
0
,
GetHWnd
(),
reinterpret_cast
<
HMENU
>
(
static_cast
<
INT_PTR
>
(
CreateControlID
())),
AwtToolkit
::
GetInstance
().
GetModuleHandle
(),
NULL
);
DASSERT
(
m_hEditCtrl
!=
NULL
);
if
(
sm_pDefWindowProc
==
NULL
)
{
sm_pDefWindowProc
=
(
WNDPROC
)
::
GetWindowLongPtr
(
m_hEditCtrl
,
GWLP_WNDPROC
);
}
::
SetLastError
(
0
);
INT_PTR
ret
=
::
SetWindowLongPtr
(
m_hEditCtrl
,
GWLP_WNDPROC
,
(
INT_PTR
)
AwtTextArea
::
EditProc
);
DASSERT
(
ret
!=
0
||
::
GetLastError
()
==
0
);
}
/*
* Tricks on the edit control to ensure that its context menu has
* the correct set of enabled items according to the RichEdit state.
*/
::
SetWindowText
(
m_hEditCtrl
,
TEXT
(
"TEXT"
));
if
(
m_bCanUndo
==
TRUE
&&
SendMessage
(
EM_CANUNDO
))
{
/* Enable 'Undo' item. */
::
SendMessage
(
m_hEditCtrl
,
WM_CHAR
,
'A'
,
0
);
}
{
/*
* Initial selection for the edit control - (0,1).
* This enables 'Cut', 'Copy' and 'Delete' and 'Select All'.
*/
INT
nStart
=
0
;
INT
nEnd
=
1
;
if
(
SendMessage
(
EM_SELECTIONTYPE
)
==
SEL_EMPTY
)
{
/*
* RichEdit selection is empty - clear selection of the edit control.
* This disables 'Cut', 'Copy' and 'Delete'.
*/
nStart
=
-
1
;
nEnd
=
0
;
}
else
{
CHARRANGE
cr
;
EditGetSel
(
cr
);
/* Check if all the text is selected. */
if
(
cr
.
cpMin
==
0
)
{
int
len
=
::
GetWindowTextLength
(
GetHWnd
());
if
(
cr
.
cpMin
==
0
&&
cr
.
cpMax
>=
len
)
{
/*
* All the text is selected in RichEdit - select all the
* text in the edit control. This disables 'Select All'.
*/
nStart
=
0
;
nEnd
=
-
1
;
}
}
}
::
SendMessage
(
m_hEditCtrl
,
EM_SETSEL
,
(
WPARAM
)
nStart
,
(
LPARAM
)
nEnd
);
}
/* Disable 'Paste' item if the RichEdit control is read-only. */
::
SendMessage
(
m_hEditCtrl
,
EM_SETREADONLY
,
GetStyle
()
&
ES_READONLY
?
TRUE
:
FALSE
,
0
);
POINT
p
;
p
.
x
=
xPos
;
p
.
y
=
yPos
;
/*
* If the context menu is requested with SHIFT+F10 or VK_APPS key,
* we position its top left corner to the center of the RichEdit
* client rect.
*/
if
(
p
.
x
==
-
1
&&
p
.
y
==
-
1
)
{
RECT
r
;
VERIFY
(
::
GetClientRect
(
GetHWnd
(),
&
r
));
p
.
x
=
(
r
.
left
+
r
.
right
)
/
2
;
p
.
y
=
(
r
.
top
+
r
.
bottom
)
/
2
;
VERIFY
(
::
ClientToScreen
(
GetHWnd
(),
&
p
));
}
// The context menu steals focus from the proxy.
// So, set the focus-restore flag up.
SetRestoreFocus
(
TRUE
);
::
SendMessage
(
m_hEditCtrl
,
WM_CONTEXTMENU
,
(
WPARAM
)
m_hEditCtrl
,
MAKELPARAM
(
p
.
x
,
p
.
y
));
SetRestoreFocus
(
FALSE
);
return
mrConsume
;
}
//
//
// Accessibility support
// Accessibility support
...
...
src/windows/native/sun/windows/awt_TextComponent.h
浏览文件 @
5606a2cd
...
@@ -47,6 +47,8 @@ public:
...
@@ -47,6 +47,8 @@ public:
static
AwtTextComponent
*
Create
(
jobject
self
,
jobject
parent
,
BOOL
isMultiline
);
static
AwtTextComponent
*
Create
(
jobject
self
,
jobject
parent
,
BOOL
isMultiline
);
virtual
void
Dispose
();
virtual
LPCTSTR
GetClassName
();
virtual
LPCTSTR
GetClassName
();
LRESULT
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
LRESULT
WindowProc
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
...
@@ -83,6 +85,8 @@ public:
...
@@ -83,6 +85,8 @@ public:
MsgRouting
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
);
MsgRouting
HandleEvent
(
MSG
*
msg
,
BOOL
synthetic
);
MsgRouting
WmPaste
();
MsgRouting
WmPaste
();
INLINE
void
SetIgnoreEnChange
(
BOOL
b
)
{
m_bIgnoreEnChange
=
b
;
}
virtual
BOOL
IsFocusingMouseMessage
(
MSG
*
pMsg
);
virtual
BOOL
IsFocusingMouseMessage
(
MSG
*
pMsg
);
/* To be fully implemented in a future release
/* To be fully implemented in a future release
...
@@ -115,11 +119,24 @@ public:
...
@@ -115,11 +119,24 @@ public:
INLINE
VOID
SetEndSelectionPos
(
LONG
lPos
)
{
m_lEndPos
=
lPos
;
}
INLINE
VOID
SetEndSelectionPos
(
LONG
lPos
)
{
m_lEndPos
=
lPos
;
}
INLINE
VOID
SetLastSelectionPos
(
LONG
lPos
)
{
m_lLastPos
=
lPos
;
}
INLINE
VOID
SetLastSelectionPos
(
LONG
lPos
)
{
m_lLastPos
=
lPos
;
}
void
EditGetSel
(
CHARRANGE
&
cr
);
// Used to prevent untrusted code from synthesizing a WM_PASTE message
// Used to prevent untrusted code from synthesizing a WM_PASTE message
// by posting a <CTRL>-V KeyEvent
// by posting a <CTRL>-V KeyEvent
BOOL
m_synthetic
;
BOOL
m_synthetic
;
LONG
EditGetCharFromPos
(
POINT
&
pt
);
LONG
EditGetCharFromPos
(
POINT
&
pt
);
// RichEdit 1.0 control generates EN_CHANGE notifications not only
// on text changes, but also on any character formatting change.
// This flag is true when the latter case is detected.
BOOL
m_bIgnoreEnChange
;
// RichEdit 1.0 control undoes a character formatting change
// if it is the latest. We don't create our own undo buffer,
// but just prohibit undo in case if the latest operation
// is a formatting change.
BOOL
m_bCanUndo
;
/*****************************************************************
/*****************************************************************
* Inner class OleCallback declaration.
* Inner class OleCallback declaration.
*/
*/
...
@@ -166,6 +183,13 @@ private:
...
@@ -166,6 +183,13 @@ private:
static
OleCallback
sm_oleCallback
;
static
OleCallback
sm_oleCallback
;
static
WNDPROC
sm_pDefWindowProc
;
HWND
m_hEditCtrl
;
static
LRESULT
CALLBACK
EditProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
);
MsgRouting
WmContextMenu
(
HWND
hCtrl
,
UINT
xPos
,
UINT
yPos
);
//
//
// Accessibility support
// Accessibility support
//
//
...
...
src/windows/native/sun/windows/awt_TextField.cpp
浏览文件 @
5606a2cd
...
@@ -249,13 +249,7 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
...
@@ -249,13 +249,7 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic)
}
}
}
}
/*
returnVal
=
AwtTextComponent
::
HandleEvent
(
msg
,
synthetic
);
* Store the 'synthetic' parameter so that the WM_PASTE security check
* happens only for synthetic events.
*/
m_synthetic
=
synthetic
;
returnVal
=
AwtComponent
::
HandleEvent
(
msg
,
synthetic
);
m_synthetic
=
FALSE
;
if
(
systemBeeperEnabled
){
if
(
systemBeeperEnabled
){
SystemParametersInfo
(
SPI_SETBEEP
,
1
,
NULL
,
0
);
SystemParametersInfo
(
SPI_SETBEEP
,
1
,
NULL
,
0
);
...
...
test/com/sun/jdi/EvalInterfaceStatic.sh
0 → 100644
浏览文件 @
5606a2cd
#!/bin/sh
#
# Copyright (c) 2014, 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 8031195
# @summary JDB allows evaluation of calls to static interface methods
# @author Jaroslav Bachorik
#
# @run shell/timeout=300 EvalInterfaceStatic.sh
# The test exercises the ability to invoke static methods on interfaces.
# Static interface methods are a new feature added in JDK8.
#
# The test makes sure that it is, at all, possible to invoke an interface
# static method and that the static methods are not inherited by extending
# interfaces.
classname
=
EvalStaticInterfaces
createJavaFile
()
{
cat
<<
EOF
>
$classname
.java.1
public interface
$classname
{
static String staticMethod1() {
return "base:staticMethod1";
}
static String staticMethod2() {
return "base:staticMethod2";
}
public static void main(String[] args) {
// prove that these work
System.out.println("base staticMethod1(): " +
$classname
.staticMethod1());
System.out.println("base staticMethod2(): " +
$classname
.staticMethod2());
System.out.println("overridden staticMethod2(): " + Extended
$classname
.staticMethod2());
System.out.println("base staticMethod3(): " + Extended
$classname
.staticMethod3());
gus();
}
static void gus() {
int x = 0; // @1 breakpoint
}
}
interface Extended
$classname
extends
$classname
{
static String staticMethod2() {
return "extended:staticMethod2";
}
static String staticMethod3() {
return "extended:staticMethod3";
}
}
EOF
}
# drive jdb by sending cmds to it and examining its output
dojdbCmds
()
{
setBkpts @1
runToBkpt @1
cmd
eval
"
$classname
.staticMethod1()"
jdbFailIfNotPresent
"base:staticMethod1"
2
cmd
eval
"
$classname
.staticMethod2()"
jdbFailIfNotPresent
"base:staticMethod2"
2
cmd
eval
"Extended
$classname
.staticMethod1()"
jdbFailIfPresent
"base:staticMethod1"
2
cmd
eval
"Extended
$classname
.staticMethod2()"
jdbFailIfNotPresent
"extended:staticMethod2"
2
cmd
eval
"Extended
$classname
.staticMethod3()"
jdbFailIfNotPresent
"extended:staticMethod3"
2
}
mysetup
()
{
if
[
-z
"
$TESTSRC
"
]
;
then
TESTSRC
=
.
fi
for
ii
in
.
$TESTSRC
$TESTSRC
/..
;
do
if
[
-r
"
$ii
/ShellScaffold.sh"
]
;
then
.
$ii
/ShellScaffold.sh
break
fi
done
}
# You could replace this next line with the contents
# of ShellScaffold.sh and this script will run just the same.
mysetup
runit
pass
test/com/sun/jdi/InterfaceMethodsTest.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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 8031195
* @summary JDI: Add support for static and default methods in interfaces
*
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run build InterfaceMethodsTest
* @run main InterfaceMethodsTest
*/
import
com.sun.jdi.*
;
import
com.sun.jdi.event.*
;
import
java.util.Collections
;
public
class
InterfaceMethodsTest
extends
TestScaffold
{
private
static
final
int
RESULT_A
=
1
;
private
static
final
int
RESULT_B
=
1
;
private
static
final
int
RESULT_TARGET
=
1
;
static
interface
InterfaceA
{
static
int
staticMethodA
()
{
System
.
out
.
println
(
"-InterfaceA: static interface method A-"
);
return
RESULT_A
;
}
static
int
staticMethodB
()
{
System
.
out
.
println
(
"-InterfaceA: static interface method B-"
);
return
RESULT_A
;
}
default
int
defaultMethodA
()
{
System
.
out
.
println
(
"-InterfaceA: default interface method A-"
);
return
RESULT_A
;
}
default
int
defaultMethodB
()
{
System
.
out
.
println
(
"-InterfaceA: default interface method B-"
);
return
RESULT_A
;
}
default
int
defaultMethodC
()
{
System
.
out
.
println
(
"-InterfaceA: default interface method C-"
);
return
RESULT_A
;
}
int
implementedMethod
();
}
static
interface
InterfaceB
extends
InterfaceA
{
@Override
default
int
defaultMethodC
()
{
System
.
out
.
println
(
"-InterfaceB: overridden default interface method C-"
);
return
RESULT_B
;
}
default
int
defaultMethodD
()
{
System
.
out
.
println
(
"-InterfaceB: default interface method D-"
);
return
RESULT_B
;
}
static
int
staticMethodB
()
{
System
.
out
.
println
(
"-InterfaceB: overridden static interface method B-"
);
return
RESULT_B
;
}
static
int
staticMethodC
()
{
System
.
out
.
println
(
"-InterfaceB: static interface method C-"
);
return
RESULT_B
;
}
}
final
static
class
TargetClass
implements
InterfaceB
{
public
int
classMethod
()
{
System
.
out
.
println
(
"-TargetClass: class only method-"
);
return
RESULT_TARGET
;
}
@Override
public
int
implementedMethod
()
{
System
.
out
.
println
(
"-TargetClass: implemented non-default interface method-"
);
return
RESULT_TARGET
;
}
@Override
public
int
defaultMethodB
()
{
System
.
out
.
println
(
"-TargetClass: overridden default interface method D"
);
return
RESULT_TARGET
;
}
public
static
void
main
(
String
[]
args
)
{
TargetClass
tc
=
new
TargetClass
();
tc
.
doTests
(
tc
);
}
private
void
doTests
(
TargetClass
ref
)
{
// break
}
}
public
InterfaceMethodsTest
(
String
[]
args
)
{
super
(
args
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
InterfaceMethodsTest
(
args
).
startTests
();
}
private
static
final
String
TEST_CLASS_NAME
=
InterfaceMethodsTest
.
class
.
getName
().
replace
(
'.'
,
'/'
);
private
static
final
String
TARGET_CLASS_NAME
=
TargetClass
.
class
.
getName
().
replace
(
'.'
,
'/'
);
private
static
final
String
INTERFACEA_NAME
=
InterfaceA
.
class
.
getName
().
replace
(
'.'
,
'/'
);
private
static
final
String
INTERFACEB_NAME
=
InterfaceB
.
class
.
getName
().
replace
(
'.'
,
'/'
);
protected
void
runTests
()
throws
Exception
{
/*
* Get to the top of main()
* to determine targetClass and mainThread
*/
BreakpointEvent
bpe
=
startToMain
(
TARGET_CLASS_NAME
);
bpe
=
resumeTo
(
TARGET_CLASS_NAME
,
"doTests"
,
"(L"
+
TARGET_CLASS_NAME
+
";)V"
);
mainThread
=
bpe
.
thread
();
StackFrame
frame
=
mainThread
.
frame
(
0
);
ObjectReference
thisObject
=
frame
.
thisObject
();
ObjectReference
ref
=
(
ObjectReference
)
frame
.
getArgumentValues
().
get
(
0
);
ReferenceType
targetClass
=
bpe
.
location
().
declaringType
();
testImplementationClass
(
targetClass
,
thisObject
);
testInterfaceA
(
ref
);
testInterfaceB
(
ref
);
/*
* 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
(
"InterfaceMethodsTest: passed"
);
}
else
{
throw
new
Exception
(
"InterfaceMethodsTest: failed"
);
}
}
private
void
testInterfaceA
(
ObjectReference
ref
)
{
// Test non-virtual calls on InterfaceA
ReferenceType
ifaceClass
=
(
ReferenceType
)
vm
().
classesByName
(
INTERFACEA_NAME
).
get
(
0
);
/* Default method calls */
// invoke the InterfaceA's "defaultMethodA"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// invoke the InterfaceA's "defaultMethodB"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// invoke the InterfaceA's "defaultMethodC"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// "defaultMethodD" from InterfaceB is not accessible from here
testInvokeNeg
(
ifaceClass
,
ref
,
"defaultMethodD"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
),
"Attempted to invoke non-existing method"
);
// trying to invoke the asbtract method "implementedMethod"
testInvokeNeg
(
ifaceClass
,
ref
,
"implementedMethod"
,
"()I"
,
vm
().
mirrorOf
(
TARGET_CLASS_NAME
),
"Invocation of non-default methods is not supported"
);
/* Static method calls */
// invoke interface static method A
testInvokePos
(
ifaceClass
,
null
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// try to invoke static method A on the instance
testInvokePos
(
ifaceClass
,
ref
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// invoke interface static method B
testInvokePos
(
ifaceClass
,
null
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// try to invoke static method B on the instance
testInvokePos
(
ifaceClass
,
ref
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
}
private
void
testInterfaceB
(
ObjectReference
ref
)
{
// Test non-virtual calls on InterfaceB
ReferenceType
ifaceClass
=
(
ReferenceType
)
vm
().
classesByName
(
INTERFACEB_NAME
).
get
(
0
);
/* Default method calls */
// invoke the inherited "defaultMethodA"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// invoke the inherited "defaultMethodB"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
));
// invoke the inherited and overridden "defaultMethodC"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
// invoke InterfaceB only "defaultMethodD"
testInvokePos
(
ifaceClass
,
ref
,
"defaultMethodD"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
// "implementedMethod" is not present in InterfaceB
testInvokeNeg
(
ifaceClass
,
ref
,
"implementedMethod"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
),
"Invocation of non-default methods is not supported"
);
/* Static method calls*/
// "staticMethodA" must not be inherited by InterfaceB
testInvokeNeg
(
ifaceClass
,
null
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
),
"Static interface methods are not inheritable"
);
// however it is possible to call "staticMethodA" on the actual instance
testInvokeNeg
(
ifaceClass
,
ref
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
),
"Static interface methods are not inheritable"
);
// "staticMethodB" is overridden in InterfaceB
testInvokePos
(
ifaceClass
,
null
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
// the instance invokes the overriden form of "staticMethodB" from InterfaceB
testInvokePos
(
ifaceClass
,
ref
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
// "staticMethodC" is present only in InterfaceB
testInvokePos
(
ifaceClass
,
null
,
"staticMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
// "staticMethodC" should be reachable from the instance too
testInvokePos
(
ifaceClass
,
ref
,
"staticMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
));
}
private
void
testImplementationClass
(
ReferenceType
targetClass
,
ObjectReference
thisObject
)
{
// Test invocations on the implementation object
/* Default method calls */
// "defaultMethodA" is accessible and not overridden
testInvokePos
(
targetClass
,
thisObject
,
"defaultMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
// "defaultMethodB" is accessible and overridden in TargetClass
testInvokePos
(
targetClass
,
thisObject
,
"defaultMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
// "defaultMethodC" is accessible and overridden in InterfaceB
testInvokePos
(
targetClass
,
thisObject
,
"defaultMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
// "defaultMethodD" is accessible
testInvokePos
(
targetClass
,
thisObject
,
"defaultMethodD"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
/* Non-default instance method calls */
// "classMethod" declared in TargetClass is accessible
testInvokePos
(
targetClass
,
thisObject
,
"classMethod"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
// the abstract "implementedMethod" has been implemented in TargetClass
testInvokePos
(
targetClass
,
thisObject
,
"implementedMethod"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_TARGET
));
/* Static method calls */
// All the static methods declared by the interfaces are not reachable from the instance of the implementor class
testInvokeNeg
(
targetClass
,
thisObject
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
),
"Static interface methods are not inheritable"
);
testInvokeNeg
(
targetClass
,
thisObject
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
),
"Static interface methods are not inheritable"
);
testInvokeNeg
(
targetClass
,
thisObject
,
"staticMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
),
"Static interface methods are not inheritable"
);
// All the static methods declared by the interfaces are not reachable through the implementor class
testInvokeNeg
(
targetClass
,
null
,
"staticMethodA"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_A
),
"Static interface methods are not inheritable"
);
testInvokeNeg
(
targetClass
,
null
,
"staticMethodB"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
),
"Static interface methods are not inheritable"
);
testInvokeNeg
(
targetClass
,
null
,
"staticMethodC"
,
"()I"
,
vm
().
mirrorOf
(
RESULT_B
),
"Static interface methods are not inheritable"
);
}
private
void
testInvokePos
(
ReferenceType
targetClass
,
ObjectReference
ref
,
String
methodName
,
String
methodSig
,
Value
value
)
{
logInvocation
(
ref
,
methodName
,
methodSig
,
targetClass
);
try
{
invoke
(
targetClass
,
ref
,
methodName
,
methodSig
,
value
);
System
.
err
.
println
(
"--- PASSED"
);
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"--- FAILED"
);
failure
(
"FAILED: Invocation failed with error message "
+
e
.
getLocalizedMessage
());
}
}
private
void
testInvokeNeg
(
ReferenceType
targetClass
,
ObjectReference
ref
,
String
methodName
,
String
methodSig
,
Value
value
,
String
msg
)
{
logInvocation
(
ref
,
methodName
,
methodSig
,
targetClass
);
try
{
invoke
(
targetClass
,
ref
,
methodName
,
methodSig
,
value
);
System
.
err
.
println
(
"--- FAILED"
);
failure
(
"FAILED: "
+
msg
);
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"--- PASSED"
);
}
}
private
void
invoke
(
ReferenceType
targetClass
,
ObjectReference
ref
,
String
methodName
,
String
methodSig
,
Value
value
)
throws
Exception
{
Method
method
=
getMethod
(
targetClass
,
methodName
,
methodSig
);
if
(
method
==
null
)
{
throw
new
Exception
(
"Can't find method: "
+
methodName
+
" for class = "
+
targetClass
);
}
println
(
"Invoking "
+
(
method
.
isAbstract
()
?
"abstract "
:
" "
)
+
"method: "
+
method
);
Value
returnValue
=
null
;
if
(
ref
!=
null
)
{
returnValue
=
invokeInstance
(
ref
,
method
);
}
else
{
returnValue
=
invokeStatic
(
targetClass
,
method
);
}
println
(
" return val = "
+
returnValue
);
// It has to be the same value as what we passed in!
if
(
returnValue
.
equals
(
value
))
{
println
(
" "
+
method
.
name
()
+
" return value matches: "
+
value
);
}
else
{
if
(
value
!=
null
)
{
throw
new
Exception
(
method
.
name
()
+
" returned: "
+
returnValue
+
" expected: "
+
value
);
}
else
{
println
(
" "
+
method
.
name
()
+
" return value : "
+
returnValue
);
}
}
}
private
Value
invokeInstance
(
ObjectReference
ref
,
Method
method
)
throws
Exception
{
return
ref
.
invokeMethod
(
mainThread
,
method
,
Collections
.
emptyList
(),
ObjectReference
.
INVOKE_NONVIRTUAL
);
}
private
Value
invokeStatic
(
ReferenceType
refType
,
Method
method
)
throws
Exception
{
if
(
refType
instanceof
ClassType
)
{
return
((
ClassType
)
refType
).
invokeMethod
(
mainThread
,
method
,
Collections
.
emptyList
(),
ObjectReference
.
INVOKE_NONVIRTUAL
);
}
else
{
return
((
InterfaceType
)
refType
).
invokeMethod
(
mainThread
,
method
,
Collections
.
emptyList
(),
ObjectReference
.
INVOKE_NONVIRTUAL
);
}
}
private
Method
getMethod
(
ReferenceType
rt
,
String
name
,
String
signature
)
{
if
(
rt
==
null
)
return
null
;
Method
m
=
findMethod
(
rt
,
name
,
signature
);
if
(
m
==
null
)
{
if
(
rt
instanceof
ClassType
)
{
for
(
Object
ifc
:
((
ClassType
)
rt
).
interfaces
())
{
m
=
getMethod
((
ReferenceType
)
ifc
,
name
,
signature
);
if
(
m
!=
null
)
{
break
;
}
}
if
(
m
==
null
)
{
m
=
getMethod
(((
ClassType
)
rt
).
superclass
(),
name
,
signature
);
}
else
{
if
(
m
.
isStatic
())
{
// interface static methods are not inherited
m
=
null
;
}
}
}
else
if
(
rt
instanceof
InterfaceType
)
{
for
(
Object
ifc
:
((
InterfaceType
)
rt
).
superinterfaces
())
{
m
=
getMethod
((
ReferenceType
)
ifc
,
name
,
signature
);
if
(
m
!=
null
)
{
if
(
m
.
isStatic
())
{
// interface static methods are not inherited
m
=
null
;
}
break
;
}
}
}
}
return
m
;
}
private
void
logInvocation
(
ObjectReference
ref
,
String
methodName
,
String
methodSig
,
ReferenceType
targetClass
)
{
if
(
ref
!=
null
)
{
System
.
err
.
println
(
"Invoking: "
+
ref
.
referenceType
().
name
()
+
"."
+
methodName
+
methodSig
+
" with target of type "
+
targetClass
.
name
());
}
else
{
System
.
err
.
println
(
"Invoking static : "
+
targetClass
.
name
()
+
"."
+
methodName
+
methodSig
);
}
}
}
test/com/sun/jdi/VisibleMethods.java
0 → 100644
浏览文件 @
5606a2cd
/*
* 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
* @summary Test ReferenceType.visibleMethods
* @bug 8028430
*
* @author Staffan Larsen
*
* @run build TestScaffold VMConnection TargetListener TargetAdapter
* @run compile -g VisibleMethods.java
* @run main VisibleMethods
*/
import
com.sun.jdi.Method
;
import
com.sun.jdi.ReferenceType
;
import
com.sun.jdi.StackFrame
;
import
com.sun.jdi.StringReference
;
import
com.sun.jdi.ThreadReference
;
import
com.sun.jdi.event.BreakpointEvent
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/********** target program **********/
interface
Super
{
public
void
m
(
Object
o
);
// This method should not be visible in AC
public
void
m
(
String
s
);
// This method should not be visible in AC
}
interface
One
extends
Super
{
public
void
m
(
Object
o
);
public
void
m1
();
// Either this method or Two.m1 should be visible in AC
}
interface
Two
extends
Super
{
public
void
m
(
String
s
);
public
void
m1
();
// Either this method or One.m1 should be visible in AC
}
abstract
class
AC
implements
One
,
Two
{
}
class
CC
extends
AC
{
public
void
m
(
Object
o
)
{
}
public
void
m
(
String
s
)
{
}
public
void
m1
()
{
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"Goodbye from VisibleMethods!"
);
}
}
/********** test program **********/
public
class
VisibleMethods
extends
TestScaffold
{
ReferenceType
targetClass
;
ThreadReference
mainThread
;
VisibleMethods
(
String
args
[])
{
super
(
args
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
VisibleMethods
(
args
).
startTests
();
}
/********** test core **********/
protected
void
runTests
()
throws
Exception
{
/*
* Run to String.<init>
*/
startToMain
(
"CC"
);
ReferenceType
ac
=
findReferenceType
(
"AC"
);
List
<
String
>
visible
=
ac
.
visibleMethods
().
stream
().
map
(
Method:
:
toString
).
collect
(
Collectors
.
toList
());
System
.
out
.
println
(
"visibleMethods(): "
+
visible
);
verifyContains
(
visible
,
1
,
"Two.m(java.lang.String)"
);
verifyContains
(
visible
,
1
,
"One.m(java.lang.Object)"
);
verifyContains
(
visible
,
0
,
"Super.m(java.lang.Object)"
);
verifyContains
(
visible
,
0
,
"Super.m(java.lang.String)"
);
verifyContains
(
visible
,
1
,
"Two.m1()"
,
"One.m1()"
);
/*
* resume the target listening for events
*/
listenUntilVMDisconnect
();
}
private
void
verifyContains
(
List
<
String
>
methods
,
int
matches
,
String
...
sigs
)
throws
Exception
{
if
(
countMatches
(
methods
,
sigs
)
!=
matches
)
{
throw
new
Exception
(
"visibleMethods() should have contained "
+
matches
+
" entry/entries from "
+
Arrays
.
toString
(
sigs
));
}
}
private
int
countMatches
(
List
<
String
>
list1
,
String
[]
list2
)
{
int
count
=
0
;
for
(
String
s1
:
list1
)
{
for
(
String
s2
:
list2
)
{
if
(
s1
.
equals
(
s2
))
{
count
++;
}
}
}
return
count
;
}
}
test/java/awt/Focus/SortingFPT/JDK8048887.java
浏览文件 @
5606a2cd
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
@bug 8048887
@bug 8048887
@summary Tests SortingFTP for an exception caused by the tim-sort algo.
@summary Tests SortingFTP for an exception caused by the tim-sort algo.
@author anton.tarasov: area=awt.focus
@author anton.tarasov: area=awt.focus
@run main JDK804
0632
@run main JDK804
8887
*/
*/
import
javax.swing.JFrame
;
import
javax.swing.JFrame
;
...
...
test/java/net/InetAddress/IPv4Formats.java
浏览文件 @
5606a2cd
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
* @summary InetAddress.getByName behaves differently on windows
* @summary InetAddress.getByName behaves differently on windows
*/
*/
import
java.net.*
;
import
java.net.*
;
import
java.util.UUID
;
public
class
IPv4Formats
{
public
class
IPv4Formats
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
...
@@ -36,7 +37,7 @@ public class IPv4Formats {
...
@@ -36,7 +37,7 @@ public class IPv4Formats {
{
"126.1"
,
"126.0.0.1"
},
{
"126.1"
,
"126.0.0.1"
},
{
"128.50.65534"
,
"128.50.255.254"
},
{
"128.50.65534"
,
"128.50.255.254"
},
{
"192.168.1.2"
,
"192.168.1.2"
},
{
"192.168.1.2"
,
"192.168.1.2"
},
{
"
hello.foo.bar
"
,
null
},
{
"
invalidhost.invalid
"
,
null
},
{
"1024.1.2.3"
,
null
},
{
"1024.1.2.3"
,
null
},
{
"128.14.66000"
,
null
}
{
"128.14.66000"
,
null
}
};
};
...
...
test/java/util/logging/FileHandlerPath.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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.
*/
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.FilePermission
;
import
java.io.IOException
;
import
java.nio.channels.FileChannel
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
static
java
.
nio
.
file
.
StandardOpenOption
.
CREATE_NEW
;
import
static
java
.
nio
.
file
.
StandardOpenOption
.
WRITE
;
import
java.security.CodeSource
;
import
java.security.Permission
;
import
java.security.PermissionCollection
;
import
java.security.Permissions
;
import
java.security.Policy
;
import
java.security.ProtectionDomain
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.PropertyPermission
;
import
java.util.UUID
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.logging.FileHandler
;
import
java.util.logging.LogManager
;
import
java.util.logging.LoggingPermission
;
/**
* @test
* @bug 8059269
* @summary tests that using a simple (non composite) pattern does not lead
* to NPE when the lock file already exists.
* @run main/othervm FileHandlerPath UNSECURE
* @run main/othervm FileHandlerPath SECURE
* @author danielfuchs
*/
public
class
FileHandlerPath
{
/**
* We will test the simple pattern in two configurations.
* UNSECURE: No security manager.
* SECURE: With the security manager present - and the required
* permissions granted.
*/
public
static
enum
TestCase
{
UNSECURE
,
SECURE
;
public
void
run
(
Properties
propertyFile
)
throws
Exception
{
System
.
out
.
println
(
"Running test case: "
+
name
());
Configure
.
setUp
(
this
,
propertyFile
);
test
(
this
.
name
()
+
" "
+
propertyFile
.
getProperty
(
"test.name"
),
propertyFile
);
}
}
// Use a random name provided by UUID to avoid collision with other tests
final
static
String
logFile
=
FileHandlerPath
.
class
.
getSimpleName
()
+
"_"
+
UUID
.
randomUUID
().
toString
()
+
".log"
;
final
static
String
tmpLogFile
;
final
static
String
userDir
=
System
.
getProperty
(
"user.dir"
);
final
static
String
tmpDir
=
System
.
getProperty
(
"java.io.tmpdir"
);
private
static
final
List
<
Properties
>
properties
;
static
{
tmpLogFile
=
new
File
(
tmpDir
,
logFile
).
toString
();
Properties
props1
=
new
Properties
();
Properties
props2
=
new
Properties
();
props1
.
setProperty
(
"test.name"
,
"relative file"
);
props1
.
setProperty
(
"test.file.name"
,
logFile
);
props1
.
setProperty
(
FileHandler
.
class
.
getName
()
+
".pattern"
,
logFile
);
props1
.
setProperty
(
FileHandler
.
class
.
getName
()
+
".count"
,
"1"
);
props2
.
setProperty
(
"test.name"
,
"absoluste file"
);
props2
.
setProperty
(
"test.file.name"
,
tmpLogFile
);
props2
.
setProperty
(
FileHandler
.
class
.
getName
()
+
".pattern"
,
"%t/"
+
logFile
);
props2
.
setProperty
(
FileHandler
.
class
.
getName
()
+
".count"
,
"1"
);
properties
=
Collections
.
unmodifiableList
(
Arrays
.
asList
(
props1
,
props2
));
}
public
static
void
main
(
String
...
args
)
throws
Exception
{
if
(
args
==
null
||
args
.
length
==
0
)
{
args
=
new
String
[]
{
TestCase
.
UNSECURE
.
name
(),
TestCase
.
SECURE
.
name
(),
};
}
// Sanity checks
if
(!
Files
.
isWritable
(
Paths
.
get
(
userDir
)))
{
throw
new
RuntimeException
(
userDir
+
": user.dir is not writable - can't run test."
);
}
if
(!
Files
.
isWritable
(
Paths
.
get
(
tmpDir
)))
{
throw
new
RuntimeException
(
tmpDir
+
": java.io.tmpdir is not writable - can't run test."
);
}
File
[]
files
=
{
new
File
(
logFile
),
new
File
(
tmpLogFile
),
new
File
(
logFile
+
".1"
),
new
File
(
tmpLogFile
+
".1"
),
new
File
(
logFile
+
".lck"
),
new
File
(
tmpLogFile
+
".lck"
),
new
File
(
logFile
+
".1.lck"
),
new
File
(
tmpLogFile
+
".1.lck"
)
};
for
(
File
log
:
files
)
{
if
(
log
.
exists
())
{
throw
new
Exception
(
log
+
": file already exists - can't run test."
);
}
}
// Now start the real test
try
{
for
(
String
testName
:
args
)
{
for
(
Properties
propertyFile
:
properties
)
{
TestCase
test
=
TestCase
.
valueOf
(
testName
);
test
.
run
(
propertyFile
);
}
}
}
finally
{
// Cleanup...
Configure
.
doPrivileged
(()
->
{
for
(
File
log
:
files
)
{
try
{
final
boolean
isLockFile
=
log
.
getName
().
endsWith
(
".lck"
);
// lock file should already be deleted, except if the
// test failed in exception.
// log file should all be present, except if the test
// failed in exception.
if
(
log
.
exists
())
{
if
(!
isLockFile
)
{
System
.
out
.
println
(
"deleting "
+
log
.
toString
());
}
else
{
System
.
err
.
println
(
"deleting lock file "
+
log
.
toString
());
}
log
.
delete
();
}
else
{
if
(!
isLockFile
)
{
System
.
err
.
println
(
log
.
toString
()
+
": not found."
);
}
}
}
catch
(
Throwable
t
)
{
// should not happen
t
.
printStackTrace
();
}
}
});
}
}
static
class
Configure
{
static
Policy
policy
=
null
;
static
final
AtomicBoolean
allowAll
=
new
AtomicBoolean
(
false
);
static
void
setUp
(
TestCase
test
,
Properties
propertyFile
)
{
switch
(
test
)
{
case
SECURE:
if
(
policy
==
null
&&
System
.
getSecurityManager
()
!=
null
)
{
throw
new
IllegalStateException
(
"SecurityManager already set"
);
}
else
if
(
policy
==
null
)
{
policy
=
new
SimplePolicy
(
TestCase
.
SECURE
,
allowAll
);
Policy
.
setPolicy
(
policy
);
System
.
setSecurityManager
(
new
SecurityManager
());
}
if
(
System
.
getSecurityManager
()
==
null
)
{
throw
new
IllegalStateException
(
"No SecurityManager."
);
}
if
(
policy
==
null
)
{
throw
new
IllegalStateException
(
"policy not configured"
);
}
break
;
case
UNSECURE:
if
(
System
.
getSecurityManager
()
!=
null
)
{
throw
new
IllegalStateException
(
"SecurityManager already set"
);
}
break
;
default
:
new
InternalError
(
"No such testcase: "
+
test
);
}
doPrivileged
(()
->
{
try
{
ByteArrayOutputStream
bytes
=
new
ByteArrayOutputStream
();
propertyFile
.
store
(
bytes
,
propertyFile
.
getProperty
(
"test.name"
));
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
bytes
.
toByteArray
());
LogManager
.
getLogManager
().
readConfiguration
(
bais
);
}
catch
(
IOException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
});
}
static
void
doPrivileged
(
Runnable
run
)
{
allowAll
.
set
(
true
);
try
{
run
.
run
();
}
finally
{
allowAll
.
set
(
false
);
}
}
}
public
static
void
test
(
String
name
,
Properties
props
)
throws
Exception
{
System
.
out
.
println
(
"Testing: "
+
name
);
String
file
=
props
.
getProperty
(
"test.file.name"
);
// create the lock files first - in order to take the path that
// used to trigger the NPE
Files
.
createFile
(
Paths
.
get
(
file
+
".lck"
));
Files
.
createFile
(
Paths
.
get
(
file
+
".1.lck"
));
final
FileHandler
f1
=
new
FileHandler
();
final
FileHandler
f2
=
new
FileHandler
();
f1
.
close
();
f2
.
close
();
System
.
out
.
println
(
"Success for "
+
name
);
}
final
static
class
PermissionsBuilder
{
final
Permissions
perms
;
public
PermissionsBuilder
()
{
this
(
new
Permissions
());
}
public
PermissionsBuilder
(
Permissions
perms
)
{
this
.
perms
=
perms
;
}
public
PermissionsBuilder
add
(
Permission
p
)
{
perms
.
add
(
p
);
return
this
;
}
public
PermissionsBuilder
addAll
(
PermissionCollection
col
)
{
if
(
col
!=
null
)
{
for
(
Enumeration
<
Permission
>
e
=
col
.
elements
();
e
.
hasMoreElements
();
)
{
perms
.
add
(
e
.
nextElement
());
}
}
return
this
;
}
public
Permissions
toPermissions
()
{
final
PermissionsBuilder
builder
=
new
PermissionsBuilder
();
builder
.
addAll
(
perms
);
return
builder
.
perms
;
}
}
public
static
class
SimplePolicy
extends
Policy
{
final
Permissions
permissions
;
final
Permissions
allPermissions
;
final
AtomicBoolean
allowAll
;
public
SimplePolicy
(
TestCase
test
,
AtomicBoolean
allowAll
)
{
this
.
allowAll
=
allowAll
;
permissions
=
new
Permissions
();
permissions
.
add
(
new
LoggingPermission
(
"control"
,
null
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
"<<ALL FILES>>"
,
"read"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
logFile
,
"write,delete"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
logFile
+
".lck"
,
"write,delete"
));
// needed by FileHandler.close()
permissions
.
add
(
new
FilePermission
(
logFile
+
".1"
,
"write,delete"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
logFile
+
".1.lck"
,
"write,delete"
));
// needed by FileHandler.close()
permissions
.
add
(
new
FilePermission
(
tmpLogFile
,
"write,delete"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
tmpLogFile
+
".lck"
,
"write,delete"
));
// needed by FileHandler.close()
permissions
.
add
(
new
FilePermission
(
tmpLogFile
+
".1"
,
"write,delete"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
tmpLogFile
+
".1.lck"
,
"write,delete"
));
// needed by FileHandler.close()
permissions
.
add
(
new
FilePermission
(
userDir
,
"write"
));
// needed by new FileHandler()
permissions
.
add
(
new
FilePermission
(
tmpDir
,
"write"
));
// needed by new FileHandler()
permissions
.
add
(
new
PropertyPermission
(
"user.dir"
,
"read"
));
permissions
.
add
(
new
PropertyPermission
(
"java.io.tmpdir"
,
"read"
));
allPermissions
=
new
Permissions
();
allPermissions
.
add
(
new
java
.
security
.
AllPermission
());
}
@Override
public
boolean
implies
(
ProtectionDomain
domain
,
Permission
permission
)
{
if
(
allowAll
.
get
())
return
allPermissions
.
implies
(
permission
);
return
permissions
.
implies
(
permission
);
}
@Override
public
PermissionCollection
getPermissions
(
CodeSource
codesource
)
{
return
new
PermissionsBuilder
().
addAll
(
allowAll
.
get
()
?
allPermissions
:
permissions
).
toPermissions
();
}
@Override
public
PermissionCollection
getPermissions
(
ProtectionDomain
domain
)
{
return
new
PermissionsBuilder
().
addAll
(
allowAll
.
get
()
?
allPermissions
:
permissions
).
toPermissions
();
}
}
}
test/javax/xml/ws/xsanymixed/CopyingResponse.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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.
*/
import
org.somewhere.ws.EchoRequest
;
import
org.somewhere.ws.EchoResponse
;
public
class
CopyingResponse
extends
EchoResponse
{
public
CopyingResponse
()
{}
public
CopyingResponse
(
EchoRequest
request
)
{
content
=
request
.
getContent
();
}
}
test/javax/xml/ws/xsanymixed/ServiceImpl.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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.
*/
import
org.somewhere.ws.EchoRequest
;
import
org.somewhere.ws.EchoResponse
;
import
org.somewhere.ws.TestPort
;
import
javax.jws.WebService
;
import
javax.xml.namespace.QName
;
/**
* Simple Webservice implementation just copying xml part as is
* from incoming request into outgoing response
*/
@WebService
(
endpointInterface
=
"org.somewhere.ws.TestPort"
,
targetNamespace
=
"http://ws.somewhere.org/"
,
serviceName
=
"TestService"
,
portName
=
"TestPort"
)
public
class
ServiceImpl
implements
TestPort
{
public
static
final
QName
PORT_NAME
=
new
QName
(
"http://ws.somewhere.org/"
,
"TestPort"
);
public
static
final
QName
SERVICE_NAME
=
new
QName
(
"http://ws.somewhere.org/"
,
"TestService"
);
@Override
public
EchoResponse
echo
(
EchoRequest
request
)
{
return
new
CopyingResponse
(
request
);
}
}
test/javax/xml/ws/xsanymixed/Test.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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 8036981 8038966 8051441
* @summary the content of xs:any content:mixed should remain as is,
* no white space changes and no changes to namespace prefixes
* @run shell compile-wsdl.sh
* @run main/othervm Test
*/
import
com.sun.net.httpserver.HttpServer
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.Transformer
;
import
javax.xml.transform.TransformerException
;
import
javax.xml.transform.TransformerFactory
;
import
javax.xml.transform.stream.StreamResult
;
import
javax.xml.transform.stream.StreamSource
;
import
javax.xml.ws.Dispatch
;
import
javax.xml.ws.Endpoint
;
import
javax.xml.ws.Service
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.StringReader
;
import
java.net.InetSocketAddress
;
import
java.net.URL
;
import
java.nio.file.FileVisitResult
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.SimpleFileVisitor
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
static
java
.
nio
.
file
.
FileVisitResult
.
CONTINUE
;
public
class
Test
{
private
static
HttpServer
httpServer
;
private
static
Endpoint
endpoint
;
private
static
final
String
NL
=
System
.
getProperty
(
"line.separator"
);
private
static
final
String
XS_ANY_MIXED_PART
=
"<AppHdr xmlns=\"urn:head.001\">"
+
NL
+
" <Fr>"
+
NL
+
NL
+
"<FIId xmlns=\"urn:head.009\">"
+
NL
+
NL
+
" any"
+
NL
+
" white"
+
NL
+
" space"
+
NL
+
NL
+
" <FinInstnId>... and"
+
NL
+
NL
+
" NO namespace prefixes!!!"
+
NL
+
NL
+
" </FinInstnId>"
+
NL
+
NL
+
" </FIId>"
+
NL
+
"</Fr>"
+
NL
+
"</AppHdr>"
;
private
static
final
String
XML_REQUEST
=
"<soap:Envelope "
+
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+
"xmlns:ws=\"http://ws.somewhere.org/\">"
+
"<soap:Header/><soap:Body>"
+
"<ws:echoRequest>"
+
NL
+
XS_ANY_MIXED_PART
+
NL
+
"</ws:echoRequest>"
+
"</soap:Body></soap:Envelope>"
;
private
static
String
deployWebservice
()
throws
IOException
{
// Manually create HttpServer here using ephemeral address for port
// so as to not end up with attempt to bind to an in-use port
httpServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
0
),
0
);
httpServer
.
start
();
endpoint
=
Endpoint
.
create
(
new
ServiceImpl
());
endpoint
.
publish
(
httpServer
.
createContext
(
"/wservice"
));
String
wsdlAddress
=
"http://localhost:"
+
httpServer
.
getAddress
().
getPort
()
+
"/wservice?wsdl"
;
log
(
"address = "
+
wsdlAddress
);
return
wsdlAddress
;
}
private
static
void
stopWebservice
()
{
if
(
endpoint
!=
null
&&
endpoint
.
isPublished
())
{
endpoint
.
stop
();
}
if
(
httpServer
!=
null
)
{
httpServer
.
stop
(
0
);
}
}
public
static
void
main
(
String
[]
args
)
throws
IOException
,
TransformerException
{
try
{
String
address
=
deployWebservice
();
Service
service
=
Service
.
create
(
new
URL
(
address
),
ServiceImpl
.
SERVICE_NAME
);
Dispatch
<
Source
>
d
=
service
.
createDispatch
(
ServiceImpl
.
PORT_NAME
,
Source
.
class
,
Service
.
Mode
.
MESSAGE
);
Source
response
=
d
.
invoke
(
new
StreamSource
(
new
StringReader
(
XML_REQUEST
)));
String
resultXml
=
toString
(
response
);
log
(
"= request ======== \n"
);
log
(
XML_REQUEST
);
log
(
"= result ========= \n"
);
log
(
resultXml
);
log
(
"\n=================="
);
boolean
xsAnyMixedPartSame
=
resultXml
.
contains
(
XS_ANY_MIXED_PART
);
log
(
"resultXml.contains(XS_ANY_PART) = "
+
xsAnyMixedPartSame
);
if
(!
xsAnyMixedPartSame
)
{
fail
(
"The xs:any content=mixed part is supposed to be same in request and response."
);
throw
new
RuntimeException
();
}
log
(
"TEST PASSED"
);
}
finally
{
stopWebservice
();
// if you need to debug or explore wsdl generation result
// comment this line out:
deleteGeneratedFiles
();
}
}
private
static
String
toString
(
Source
response
)
throws
TransformerException
,
IOException
{
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
();
TransformerFactory
transformerFactory
=
TransformerFactory
.
newInstance
();
Transformer
transformer
=
transformerFactory
.
newTransformer
();
transformer
.
transform
(
response
,
new
StreamResult
(
bos
));
bos
.
close
();
return
new
String
(
bos
.
toByteArray
());
}
private
static
void
fail
(
String
message
)
{
log
(
"TEST FAILED."
);
throw
new
RuntimeException
(
message
);
}
private
static
void
log
(
String
msg
)
{
System
.
out
.
println
(
msg
);
}
private
static
void
deleteGeneratedFiles
()
{
Path
p
=
Paths
.
get
(
".."
,
"classes"
,
"javax"
,
"xml"
,
"ws"
,
"xsanymixed"
,
"org"
);
System
.
out
.
println
(
"performing cleanup, deleting wsdl compilation result: "
+
p
.
toFile
().
getAbsolutePath
());
if
(
Files
.
exists
(
p
))
{
try
{
Files
.
walkFileTree
(
p
,
new
SimpleFileVisitor
<
Path
>()
{
@Override
public
FileVisitResult
visitFile
(
Path
file
,
BasicFileAttributes
attrs
)
throws
IOException
{
System
.
out
.
println
(
"deleting file ["
+
file
.
toFile
().
getAbsoluteFile
()
+
"]"
);
Files
.
delete
(
file
);
return
CONTINUE
;
}
@Override
public
FileVisitResult
postVisitDirectory
(
Path
dir
,
IOException
exc
)
throws
IOException
{
System
.
out
.
println
(
"deleting dir ["
+
dir
.
toFile
().
getAbsoluteFile
()
+
"]"
);
if
(
exc
==
null
)
{
Files
.
delete
(
dir
);
return
CONTINUE
;
}
else
{
throw
exc
;
}
}
});
}
catch
(
IOException
ioe
)
{
ioe
.
printStackTrace
();
}
}
}
}
test/javax/xml/ws/xsanymixed/compile-wsdl.sh
0 → 100644
浏览文件 @
5606a2cd
#! /bin/sh
#
# Copyright (c) 2014, 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.
#
#
if
[
"x
$TESTJAVA
"
=
x
]
;
then
TESTJAVA
=
$1
;
shift
TESTCLASSES
=
.
fi
echo
"compiling [test-service.wsdl] wsdl ..."
$TESTJAVA
/bin/wsimport
-keep
-d
${
TESTCLASSES
}
${
TESTSRC
}
/service.wsdl
echo
"WSDL compiled. Main test class Test.java can be compiled now."
test/javax/xml/ws/xsanymixed/service.wsdl
0 → 100644
浏览文件 @
5606a2cd
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Copyright (c) 2014, 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.
-->
<definitions
xmlns=
"http://schemas.xmlsoap.org/wsdl/"
xmlns:soap=
"http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns=
"http://ws.somewhere.org/"
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
xmlns:wsam=
"http://www.w3.org/2007/05/addressing/metadata"
name=
"TestService"
targetNamespace=
"http://ws.somewhere.org/"
>
<types>
<xsd:schema
targetNamespace=
"http://ws.somewhere.org/"
version=
"1.0"
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
xmlns:tns=
"http://ws.somewhere.org/"
>
<xsd:element
type=
"tns:echoRequest"
name=
"echoRequest"
/>
<xsd:element
type=
"tns:echoResponse"
name=
"echoResponse"
/>
<xsd:complexType
name=
"echoRequest"
mixed=
"true"
>
<xsd:sequence>
<xsd:any
namespace=
"##any"
processContents=
"skip"
minOccurs=
"1"
maxOccurs=
"10"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType
name=
"echoResponse"
mixed=
"true"
>
<xsd:sequence>
<xsd:any
namespace=
"##any"
processContents=
"skip"
minOccurs=
"1"
maxOccurs=
"10"
/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</types>
<message
name=
"echoRequest"
>
<part
element=
"tns:echoRequest"
name=
"parameters"
/>
</message>
<message
name=
"echoResponse"
>
<part
element=
"tns:echoResponse"
name=
"parameters"
/>
</message>
<portType
name=
"TestPort"
>
<operation
name=
"echo"
>
<input
message=
"tns:echoRequest"
wsam:Action=
"http://ws.somewhere.org/tester/echoRequest"
/>
<output
message=
"tns:echoResponse"
wsam:Action=
"http://ws.somewhere.org/tester/echoResponse"
/>
</operation>
</portType>
<binding
name=
"TestServicePortBinding"
type=
"tns:TestPort"
>
<soap:binding
style=
"document"
transport=
"http://schemas.xmlsoap.org/soap/http"
/>
<operation
name=
"echo"
>
<soap:operation
soapAction=
""
/>
<input>
<soap:body
use=
"literal"
/>
</input>
<output>
<soap:body
use=
"literal"
/>
</output>
</operation>
</binding>
<service
name=
"TestService"
>
<port
binding=
"tns:TestServicePortBinding"
name=
"TestPort"
>
<soap:address
location=
"http://localhost/ws/tester"
/>
</port>
</service>
</definitions>
test/sun/awt/datatransfer/DataFlavorComparatorTest1.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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 8058473
@summary "Comparison method violates its general contract" when using Clipboard
Ensure that DataTransferer.DataFlavorComparator conforms to Comparator contract
@author Anton Nashatyrev
@run main DataFlavorComparatorTest1
*/
import
sun.awt.datatransfer.DataTransferer
;
import
java.awt.datatransfer.DataFlavor
;
import
java.util.Comparator
;
public
class
DataFlavorComparatorTest1
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
[]
mimes
=
new
String
[]
{
"text/plain"
,
"text/plain; charset=unicode"
,
"text/plain; charset=cp1251"
,
"text/plain; charset=unicode; class=java.io.InputStream"
,
"text/plain; charset=unicode; class=java.io.Serializable"
,
"text/plain; charset=unicode; class=java.lang.Object"
,
"text/plain; class=java.lang.String"
,
"text/plain; class=java.io.Reader"
,
"text/plain; class=java.lang.Object"
,
"text/html"
,
"text/html; charset=unicode"
,
"text/html; charset=cp1251"
,
"text/html; charset=unicode; class=java.io.InputStream"
,
"text/html; charset=unicode; class=java.io.Serializable"
,
"text/html; charset=unicode; class=java.lang.Object"
,
"text/html; class=java.lang.String"
,
"text/html; class=java.io.Reader"
,
"text/html; class=java.lang.Object"
,
"text/unknown"
,
"text/unknown; charset=unicode"
,
"text/unknown; charset=cp1251"
,
"text/unknown; charset=unicode; class=java.io.InputStream"
,
"text/unknown; charset=unicode; class=java.io.Serializable"
,
"text/unknown; charset=unicode; class=java.lang.Object"
,
"text/unknown; class=java.lang.String"
,
"text/unknown; class=java.io.Reader"
,
"text/unknown; class=java.lang.Object"
,
"application/unknown; class=java.io.InputStream"
,
"application/unknown; class=java.lang.Object"
,
"application/unknown"
,
"application/x-java-jvm-local-objectref; class=java.io.InputStream"
,
"application/x-java-jvm-local-objectref; class=java.lang.Object"
,
"application/x-java-jvm-local-objectref"
,
"unknown/flavor"
,
"unknown/flavor; class=java.io.InputStream"
,
"unknown/flavor; class=java.lang.Object"
,
};
DataFlavor
[]
flavors
=
new
DataFlavor
[
mimes
.
length
];
for
(
int
i
=
0
;
i
<
flavors
.
length
;
i
++)
{
flavors
[
i
]
=
new
DataFlavor
(
mimes
[
i
]);
}
testComparator
(
new
DataTransferer
.
DataFlavorComparator
(
true
),
flavors
);
testComparator
(
new
DataTransferer
.
DataFlavorComparator
(
false
),
flavors
);
}
private
static
void
testComparator
(
Comparator
cmp
,
DataFlavor
[]
flavs
)
throws
ClassNotFoundException
{
for
(
DataFlavor
x:
flavs
)
{
for
(
DataFlavor
y:
flavs
)
{
if
(
Math
.
signum
(
cmp
.
compare
(
x
,
y
))
!=
-
Math
.
signum
(
cmp
.
compare
(
y
,
x
)))
{
throw
new
RuntimeException
(
"Antisymmetry violated: "
+
x
+
", "
+
y
);
}
if
(
cmp
.
compare
(
x
,
y
)
==
0
&&
!
x
.
equals
(
y
))
{
throw
new
RuntimeException
(
"Equals rule violated: "
+
x
+
", "
+
y
);
}
for
(
DataFlavor
z:
flavs
)
{
if
(
cmp
.
compare
(
x
,
y
)
==
0
)
{
if
(
Math
.
signum
(
cmp
.
compare
(
x
,
z
))
!=
Math
.
signum
(
cmp
.
compare
(
y
,
z
)))
{
throw
new
RuntimeException
(
"Transitivity (1) violated: "
+
x
+
", "
+
y
+
", "
+
z
);
}
}
else
{
if
(
Math
.
signum
(
cmp
.
compare
(
x
,
y
))
==
Math
.
signum
(
cmp
.
compare
(
y
,
z
)))
{
if
(
Math
.
signum
(
cmp
.
compare
(
x
,
y
))
!=
Math
.
signum
(
cmp
.
compare
(
x
,
z
)))
{
throw
new
RuntimeException
(
"Transitivity (2) violated: "
+
x
+
", "
+
y
+
", "
+
z
);
}
}
}
}
}
}
}
}
test/sun/security/jgss/spnego/NotPreferredMech.java
0 → 100644
浏览文件 @
5606a2cd
/*
* Copyright (c) 2014, 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 8048194
* @run main/othervm NotPreferredMech
* @summary GSSContext.acceptSecContext fails when a supported mech is not initiator preferred
*/
import
org.ietf.jgss.*
;
import
sun.security.jgss.*
;
import
sun.security.jgss.spnego.NegTokenInit
;
import
sun.security.jgss.spnego.NegTokenTarg
;
import
sun.security.util.BitArray
;
import
sun.security.util.DerOutputStream
;
import
sun.security.util.DerValue
;
import
sun.security.util.ObjectIdentifier
;
import
java.io.ByteArrayOutputStream
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Method
;
public
class
NotPreferredMech
{
public
static
void
main
(
String
[]
argv
)
throws
Exception
{
// Generates a NegTokenInit mechTypes field, with an
// unsupported mech as the preferred.
DerOutputStream
mech
=
new
DerOutputStream
();
mech
.
write
(
new
Oid
(
"1.2.3.4"
).
getDER
());
mech
.
write
(
GSSUtil
.
GSS_KRB5_MECH_OID
.
getDER
());
DerOutputStream
mechTypeList
=
new
DerOutputStream
();
mechTypeList
.
write
(
DerValue
.
tag_Sequence
,
mech
);
// Generates a NegTokenInit mechToken field for 1.2.3.4 mech
GSSHeader
h1
=
new
GSSHeader
(
new
ObjectIdentifier
(
"1.2.3.4"
),
1
);
ByteArrayOutputStream
bout
=
new
ByteArrayOutputStream
();
h1
.
encode
(
bout
);
bout
.
write
(
new
byte
[
1
]);
// Generates the NegTokenInit token
Constructor
<
NegTokenInit
>
ctor
=
NegTokenInit
.
class
.
getDeclaredConstructor
(
byte
[].
class
,
BitArray
.
class
,
byte
[].
class
,
byte
[].
class
);
ctor
.
setAccessible
(
true
);
NegTokenInit
initToken
=
ctor
.
newInstance
(
mechTypeList
.
toByteArray
(),
new
BitArray
(
0
),
bout
.
toByteArray
(),
null
);
Method
m
=
Class
.
forName
(
"sun.security.jgss.spnego.SpNegoToken"
)
.
getDeclaredMethod
(
"getEncoded"
);
m
.
setAccessible
(
true
);
byte
[]
spnegoToken
=
(
byte
[])
m
.
invoke
(
initToken
);
// and wraps it into a GSSToken
GSSHeader
h
=
new
GSSHeader
(
new
ObjectIdentifier
(
GSSUtil
.
GSS_SPNEGO_MECH_OID
.
toString
()),
spnegoToken
.
length
);
bout
=
new
ByteArrayOutputStream
();
h
.
encode
(
bout
);
bout
.
write
(
spnegoToken
);
byte
[]
token
=
bout
.
toByteArray
();
// and feeds it to a GSS acceptor
GSSManager
man
=
GSSManager
.
getInstance
();
GSSContext
ctxt
=
man
.
createContext
((
GSSCredential
)
null
);
token
=
ctxt
.
acceptSecContext
(
token
,
0
,
token
.
length
);
NegTokenTarg
targ
=
new
NegTokenTarg
(
token
);
// Make sure it's a GO-ON message
Method
m2
=
NegTokenTarg
.
class
.
getDeclaredMethod
(
"getNegotiatedResult"
);
m2
.
setAccessible
(
true
);
int
negResult
=
(
int
)
m2
.
invoke
(
targ
);
if
(
negResult
!=
1
/* ACCEPT_INCOMPLETE */
)
{
throw
new
Exception
(
"Not a continue"
);
}
}
}
test/sun/text/resources/LocaleData
浏览文件 @
5606a2cd
...
@@ -7702,3 +7702,577 @@ FormatData/es_DO/DatePatterns/3=dd/MM/yy
...
@@ -7702,3 +7702,577 @@ FormatData/es_DO/DatePatterns/3=dd/MM/yy
# bug 8055222
# bug 8055222
CurrencyNames/lt_LT/EUR=\u20AC
CurrencyNames/lt_LT/EUR=\u20AC
# bug 8042126 + missing MonthNarrows data
FormatData//MonthNarrows/0=1
FormatData//MonthNarrows/1=2
FormatData//MonthNarrows/2=3
FormatData//MonthNarrows/3=4
FormatData//MonthNarrows/4=5
FormatData//MonthNarrows/5=6
FormatData//MonthNarrows/6=7
FormatData//MonthNarrows/7=8
FormatData//MonthNarrows/8=9
FormatData//MonthNarrows/9=10
FormatData//MonthNarrows/10=11
FormatData//MonthNarrows/11=12
FormatData//MonthNarrows/12=
FormatData/bg/MonthNarrows/0=\u044f
FormatData/bg/MonthNarrows/1=\u0444
FormatData/bg/MonthNarrows/2=\u043c
FormatData/bg/MonthNarrows/3=\u0430
FormatData/bg/MonthNarrows/4=\u043c
FormatData/bg/MonthNarrows/5=\u044e
FormatData/bg/MonthNarrows/6=\u044e
FormatData/bg/MonthNarrows/7=\u0430
FormatData/bg/MonthNarrows/8=\u0441
FormatData/bg/MonthNarrows/9=\u043e
FormatData/bg/MonthNarrows/10=\u043d
FormatData/bg/MonthNarrows/11=\u0434
FormatData/bg/MonthNarrows/12=
FormatData/zh_TW/MonthNarrows/0=1
FormatData/zh_TW/MonthNarrows/1=2
FormatData/zh_TW/MonthNarrows/2=3
FormatData/zh_TW/MonthNarrows/3=4
FormatData/zh_TW/MonthNarrows/4=5
FormatData/zh_TW/MonthNarrows/5=6
FormatData/zh_TW/MonthNarrows/6=7
FormatData/zh_TW/MonthNarrows/7=8
FormatData/zh_TW/MonthNarrows/8=9
FormatData/zh_TW/MonthNarrows/9=10
FormatData/zh_TW/MonthNarrows/10=11
FormatData/zh_TW/MonthNarrows/11=12
FormatData/zh_TW/MonthNarrows/12=
FormatData/it/MonthNarrows/0=G
FormatData/it/MonthNarrows/1=F
FormatData/it/MonthNarrows/2=M
FormatData/it/MonthNarrows/3=A
FormatData/it/MonthNarrows/4=M
FormatData/it/MonthNarrows/5=G
FormatData/it/MonthNarrows/6=L
FormatData/it/MonthNarrows/7=A
FormatData/it/MonthNarrows/8=S
FormatData/it/MonthNarrows/9=O
FormatData/it/MonthNarrows/10=N
FormatData/it/MonthNarrows/11=D
FormatData/it/MonthNarrows/12=
FormatData/ko/MonthNarrows/0=1\uc6d4
FormatData/ko/MonthNarrows/1=2\uc6d4
FormatData/ko/MonthNarrows/2=3\uc6d4
FormatData/ko/MonthNarrows/3=4\uc6d4
FormatData/ko/MonthNarrows/4=5\uc6d4
FormatData/ko/MonthNarrows/5=6\uc6d4
FormatData/ko/MonthNarrows/6=7\uc6d4
FormatData/ko/MonthNarrows/7=8\uc6d4
FormatData/ko/MonthNarrows/8=9\uc6d4
FormatData/ko/MonthNarrows/9=10\uc6d4
FormatData/ko/MonthNarrows/10=11\uc6d4
FormatData/ko/MonthNarrows/11=12\uc6d4
FormatData/ko/MonthNarrows/12=
FormatData/uk/MonthNarrows/0=\u0421
FormatData/uk/MonthNarrows/1=\u041b
FormatData/uk/MonthNarrows/2=\u0411
FormatData/uk/MonthNarrows/3=\u041a
FormatData/uk/MonthNarrows/4=\u0422
FormatData/uk/MonthNarrows/5=\u0427
FormatData/uk/MonthNarrows/6=\u041b
FormatData/uk/MonthNarrows/7=\u0421
FormatData/uk/MonthNarrows/8=\u0412
FormatData/uk/MonthNarrows/9=\u0416
FormatData/uk/MonthNarrows/10=\u041b
FormatData/uk/MonthNarrows/11=\u0413
FormatData/uk/MonthNarrows/12=
FormatData/lv/MonthNarrows/0=J
FormatData/lv/MonthNarrows/1=F
FormatData/lv/MonthNarrows/2=M
FormatData/lv/MonthNarrows/3=A
FormatData/lv/MonthNarrows/4=M
FormatData/lv/MonthNarrows/5=J
FormatData/lv/MonthNarrows/6=J
FormatData/lv/MonthNarrows/7=A
FormatData/lv/MonthNarrows/8=S
FormatData/lv/MonthNarrows/9=O
FormatData/lv/MonthNarrows/10=N
FormatData/lv/MonthNarrows/11=D
FormatData/lv/MonthNarrows/12=
FormatData/pt/MonthNarrows/0=J
FormatData/pt/MonthNarrows/1=F
FormatData/pt/MonthNarrows/2=M
FormatData/pt/MonthNarrows/3=A
FormatData/pt/MonthNarrows/4=M
FormatData/pt/MonthNarrows/5=J
FormatData/pt/MonthNarrows/6=J
FormatData/pt/MonthNarrows/7=A
FormatData/pt/MonthNarrows/8=S
FormatData/pt/MonthNarrows/9=O
FormatData/pt/MonthNarrows/10=N
FormatData/pt/MonthNarrows/11=D
FormatData/pt/MonthNarrows/12=
FormatData/sk/MonthNarrows/0=j
FormatData/sk/MonthNarrows/1=f
FormatData/sk/MonthNarrows/2=m
FormatData/sk/MonthNarrows/3=a
FormatData/sk/MonthNarrows/4=m
FormatData/sk/MonthNarrows/5=j
FormatData/sk/MonthNarrows/6=j
FormatData/sk/MonthNarrows/7=a
FormatData/sk/MonthNarrows/8=s
FormatData/sk/MonthNarrows/9=o
FormatData/sk/MonthNarrows/10=n
FormatData/sk/MonthNarrows/11=d
FormatData/sk/MonthNarrows/12=
FormatData/hi_IN/MonthNarrows/0=\u091c
FormatData/hi_IN/MonthNarrows/1=\u092b\u093c
FormatData/hi_IN/MonthNarrows/2=\u092e\u093e
FormatData/hi_IN/MonthNarrows/3=\u0905
FormatData/hi_IN/MonthNarrows/4=\u092e
FormatData/hi_IN/MonthNarrows/5=\u091c\u0942
FormatData/hi_IN/MonthNarrows/6=\u091c\u0941
FormatData/hi_IN/MonthNarrows/7=\u0905
FormatData/hi_IN/MonthNarrows/8=\u0938\u093f
FormatData/hi_IN/MonthNarrows/9=\u0905
FormatData/hi_IN/MonthNarrows/10=\u0928
FormatData/hi_IN/MonthNarrows/11=\u0926\u093f
FormatData/hi_IN/MonthNarrows/12=
FormatData/ga/MonthNarrows/0=E
FormatData/ga/MonthNarrows/1=F
FormatData/ga/MonthNarrows/2=M
FormatData/ga/MonthNarrows/3=A
FormatData/ga/MonthNarrows/4=B
FormatData/ga/MonthNarrows/5=M
FormatData/ga/MonthNarrows/6=I
FormatData/ga/MonthNarrows/7=L
FormatData/ga/MonthNarrows/8=M
FormatData/ga/MonthNarrows/9=D
FormatData/ga/MonthNarrows/10=S
FormatData/ga/MonthNarrows/11=N
FormatData/ga/MonthNarrows/12=
FormatData/et/MonthNarrows/0=J
FormatData/et/MonthNarrows/1=V
FormatData/et/MonthNarrows/2=M
FormatData/et/MonthNarrows/3=A
FormatData/et/MonthNarrows/4=M
FormatData/et/MonthNarrows/5=J
FormatData/et/MonthNarrows/6=J
FormatData/et/MonthNarrows/7=A
FormatData/et/MonthNarrows/8=S
FormatData/et/MonthNarrows/9=O
FormatData/et/MonthNarrows/10=N
FormatData/et/MonthNarrows/11=D
FormatData/et/MonthNarrows/12=
FormatData/sv/MonthNarrows/0=J
FormatData/sv/MonthNarrows/1=F
FormatData/sv/MonthNarrows/2=M
FormatData/sv/MonthNarrows/3=A
FormatData/sv/MonthNarrows/4=M
FormatData/sv/MonthNarrows/5=J
FormatData/sv/MonthNarrows/6=J
FormatData/sv/MonthNarrows/7=A
FormatData/sv/MonthNarrows/8=S
FormatData/sv/MonthNarrows/9=O
FormatData/sv/MonthNarrows/10=N
FormatData/sv/MonthNarrows/11=D
FormatData/sv/MonthNarrows/12=
FormatData/cs/MonthNarrows/0=l
FormatData/cs/MonthNarrows/1=\u00fa
FormatData/cs/MonthNarrows/2=b
FormatData/cs/MonthNarrows/3=d
FormatData/cs/MonthNarrows/4=k
FormatData/cs/MonthNarrows/5=\u010d
FormatData/cs/MonthNarrows/6=\u010d
FormatData/cs/MonthNarrows/7=s
FormatData/cs/MonthNarrows/8=z
FormatData/cs/MonthNarrows/9=\u0159
FormatData/cs/MonthNarrows/10=l
FormatData/cs/MonthNarrows/11=p
FormatData/cs/MonthNarrows/12=
FormatData/el/MonthNarrows/0=\u0399
FormatData/el/MonthNarrows/1=\u03a6
FormatData/el/MonthNarrows/2=\u039c
FormatData/el/MonthNarrows/3=\u0391
FormatData/el/MonthNarrows/4=\u039c
FormatData/el/MonthNarrows/5=\u0399
FormatData/el/MonthNarrows/6=\u0399
FormatData/el/MonthNarrows/7=\u0391
FormatData/el/MonthNarrows/8=\u03a3
FormatData/el/MonthNarrows/9=\u039f
FormatData/el/MonthNarrows/10=\u039d
FormatData/el/MonthNarrows/11=\u0394
FormatData/el/MonthNarrows/12=
FormatData/hu/MonthNarrows/0=J
FormatData/hu/MonthNarrows/1=F
FormatData/hu/MonthNarrows/2=M
FormatData/hu/MonthNarrows/3=\u00c1
FormatData/hu/MonthNarrows/4=M
FormatData/hu/MonthNarrows/5=J
FormatData/hu/MonthNarrows/6=J
FormatData/hu/MonthNarrows/7=A
FormatData/hu/MonthNarrows/8=Sz
FormatData/hu/MonthNarrows/9=O
FormatData/hu/MonthNarrows/10=N
FormatData/hu/MonthNarrows/11=D
FormatData/hu/MonthNarrows/12=
FormatData/es/MonthNarrows/0=E
FormatData/es/MonthNarrows/1=F
FormatData/es/MonthNarrows/2=M
FormatData/es/MonthNarrows/3=A
FormatData/es/MonthNarrows/4=M
FormatData/es/MonthNarrows/5=J
FormatData/es/MonthNarrows/6=J
FormatData/es/MonthNarrows/7=A
FormatData/es/MonthNarrows/8=S
FormatData/es/MonthNarrows/9=O
FormatData/es/MonthNarrows/10=N
FormatData/es/MonthNarrows/11=D
FormatData/es/MonthNarrows/12=
FormatData/tr/MonthNarrows/0=O
FormatData/tr/MonthNarrows/1=\u015e
FormatData/tr/MonthNarrows/2=M
FormatData/tr/MonthNarrows/3=N
FormatData/tr/MonthNarrows/4=M
FormatData/tr/MonthNarrows/5=H
FormatData/tr/MonthNarrows/6=T
FormatData/tr/MonthNarrows/7=A
FormatData/tr/MonthNarrows/8=E
FormatData/tr/MonthNarrows/9=E
FormatData/tr/MonthNarrows/10=K
FormatData/tr/MonthNarrows/11=A
FormatData/tr/MonthNarrows/12=
FormatData/hr/MonthNarrows/0=1.
FormatData/hr/MonthNarrows/1=2.
FormatData/hr/MonthNarrows/2=3.
FormatData/hr/MonthNarrows/3=4.
FormatData/hr/MonthNarrows/4=5.
FormatData/hr/MonthNarrows/5=6.
FormatData/hr/MonthNarrows/6=7.
FormatData/hr/MonthNarrows/7=8.
FormatData/hr/MonthNarrows/8=9.
FormatData/hr/MonthNarrows/9=10.
FormatData/hr/MonthNarrows/10=11.
FormatData/hr/MonthNarrows/11=12.
FormatData/hr/MonthNarrows/12=
FormatData/lt/MonthNarrows/0=S
FormatData/lt/MonthNarrows/1=V
FormatData/lt/MonthNarrows/2=K
FormatData/lt/MonthNarrows/3=B
FormatData/lt/MonthNarrows/4=G
FormatData/lt/MonthNarrows/5=B
FormatData/lt/MonthNarrows/6=L
FormatData/lt/MonthNarrows/7=R
FormatData/lt/MonthNarrows/8=R
FormatData/lt/MonthNarrows/9=S
FormatData/lt/MonthNarrows/10=L
FormatData/lt/MonthNarrows/11=G
FormatData/lt/MonthNarrows/12=
FormatData/sq/MonthNarrows/0=J
FormatData/sq/MonthNarrows/1=S
FormatData/sq/MonthNarrows/2=M
FormatData/sq/MonthNarrows/3=P
FormatData/sq/MonthNarrows/4=M
FormatData/sq/MonthNarrows/5=Q
FormatData/sq/MonthNarrows/6=K
FormatData/sq/MonthNarrows/7=G
FormatData/sq/MonthNarrows/8=S
FormatData/sq/MonthNarrows/9=T
FormatData/sq/MonthNarrows/10=N
FormatData/sq/MonthNarrows/11=D
FormatData/sq/MonthNarrows/12=
FormatData/fr/MonthNarrows/0=J
FormatData/fr/MonthNarrows/1=F
FormatData/fr/MonthNarrows/2=M
FormatData/fr/MonthNarrows/3=A
FormatData/fr/MonthNarrows/4=M
FormatData/fr/MonthNarrows/5=J
FormatData/fr/MonthNarrows/6=J
FormatData/fr/MonthNarrows/7=A
FormatData/fr/MonthNarrows/8=S
FormatData/fr/MonthNarrows/9=O
FormatData/fr/MonthNarrows/10=N
FormatData/fr/MonthNarrows/11=D
FormatData/fr/MonthNarrows/12=
FormatData/is/MonthNarrows/0=J
FormatData/is/MonthNarrows/1=F
FormatData/is/MonthNarrows/2=M
FormatData/is/MonthNarrows/3=A
FormatData/is/MonthNarrows/4=M
FormatData/is/MonthNarrows/5=J
FormatData/is/MonthNarrows/6=J
FormatData/is/MonthNarrows/7=\u00c1
FormatData/is/MonthNarrows/8=L
FormatData/is/MonthNarrows/9=O
FormatData/is/MonthNarrows/10=N
FormatData/is/MonthNarrows/11=D
FormatData/is/MonthNarrows/12=
FormatData/de/MonthNarrows/0=J
FormatData/de/MonthNarrows/1=F
FormatData/de/MonthNarrows/2=M
FormatData/de/MonthNarrows/3=A
FormatData/de/MonthNarrows/4=M
FormatData/de/MonthNarrows/5=J
FormatData/de/MonthNarrows/6=J
FormatData/de/MonthNarrows/7=A
FormatData/de/MonthNarrows/8=S
FormatData/de/MonthNarrows/9=O
FormatData/de/MonthNarrows/10=N
FormatData/de/MonthNarrows/11=D
FormatData/de/MonthNarrows/12=
FormatData/en/MonthNarrows/0=J
FormatData/en/MonthNarrows/1=F
FormatData/en/MonthNarrows/2=M
FormatData/en/MonthNarrows/3=A
FormatData/en/MonthNarrows/4=M
FormatData/en/MonthNarrows/5=J
FormatData/en/MonthNarrows/6=J
FormatData/en/MonthNarrows/7=A
FormatData/en/MonthNarrows/8=S
FormatData/en/MonthNarrows/9=O
FormatData/en/MonthNarrows/10=N
FormatData/en/MonthNarrows/11=D
FormatData/en/MonthNarrows/12=
FormatData/ca/MonthNarrows/0=G
FormatData/ca/MonthNarrows/1=F
FormatData/ca/MonthNarrows/2=M
FormatData/ca/MonthNarrows/3=A
FormatData/ca/MonthNarrows/4=M
FormatData/ca/MonthNarrows/5=J
FormatData/ca/MonthNarrows/6=G
FormatData/ca/MonthNarrows/7=A
FormatData/ca/MonthNarrows/8=S
FormatData/ca/MonthNarrows/9=O
FormatData/ca/MonthNarrows/10=N
FormatData/ca/MonthNarrows/11=D
FormatData/ca/MonthNarrows/12=
FormatData/sl/MonthNarrows/0=j
FormatData/sl/MonthNarrows/1=f
FormatData/sl/MonthNarrows/2=m
FormatData/sl/MonthNarrows/3=a
FormatData/sl/MonthNarrows/4=m
FormatData/sl/MonthNarrows/5=j
FormatData/sl/MonthNarrows/6=j
FormatData/sl/MonthNarrows/7=a
FormatData/sl/MonthNarrows/8=s
FormatData/sl/MonthNarrows/9=o
FormatData/sl/MonthNarrows/10=n
FormatData/sl/MonthNarrows/11=d
FormatData/sl/MonthNarrows/12=
FormatData/fi/MonthNarrows/0=T
FormatData/fi/MonthNarrows/1=H
FormatData/fi/MonthNarrows/2=M
FormatData/fi/MonthNarrows/3=H
FormatData/fi/MonthNarrows/4=T
FormatData/fi/MonthNarrows/5=K
FormatData/fi/MonthNarrows/6=H
FormatData/fi/MonthNarrows/7=E
FormatData/fi/MonthNarrows/8=S
FormatData/fi/MonthNarrows/9=L
FormatData/fi/MonthNarrows/10=M
FormatData/fi/MonthNarrows/11=J
FormatData/fi/MonthNarrows/12=
FormatData/mk/MonthNarrows/0=\u0458
FormatData/mk/MonthNarrows/1=\u0444
FormatData/mk/MonthNarrows/2=\u043c
FormatData/mk/MonthNarrows/3=\u0430
FormatData/mk/MonthNarrows/4=\u043c
FormatData/mk/MonthNarrows/5=\u0458
FormatData/mk/MonthNarrows/6=\u0458
FormatData/mk/MonthNarrows/7=\u0430
FormatData/mk/MonthNarrows/8=\u0441
FormatData/mk/MonthNarrows/9=\u043e
FormatData/mk/MonthNarrows/10=\u043d
FormatData/mk/MonthNarrows/11=\u0434
FormatData/mk/MonthNarrows/12=
FormatData/sr-Latn/MonthNarrows/0=j
FormatData/sr-Latn/MonthNarrows/1=f
FormatData/sr-Latn/MonthNarrows/2=m
FormatData/sr-Latn/MonthNarrows/3=a
FormatData/sr-Latn/MonthNarrows/4=m
FormatData/sr-Latn/MonthNarrows/5=j
FormatData/sr-Latn/MonthNarrows/6=j
FormatData/sr-Latn/MonthNarrows/7=a
FormatData/sr-Latn/MonthNarrows/8=s
FormatData/sr-Latn/MonthNarrows/9=o
FormatData/sr-Latn/MonthNarrows/10=n
FormatData/sr-Latn/MonthNarrows/11=d
FormatData/sr-Latn/MonthNarrows/12=
FormatData/th/MonthNarrows/0=\u0e21.\u0e04.
FormatData/th/MonthNarrows/1=\u0e01.\u0e1e.
FormatData/th/MonthNarrows/2=\u0e21\u0e35.\u0e04.
FormatData/th/MonthNarrows/3=\u0e40\u0e21.\u0e22.
FormatData/th/MonthNarrows/4=\u0e1e.\u0e04.
FormatData/th/MonthNarrows/5=\u0e21\u0e34.\u0e22
FormatData/th/MonthNarrows/6=\u0e01.\u0e04.
FormatData/th/MonthNarrows/7=\u0e2a.\u0e04.
FormatData/th/MonthNarrows/8=\u0e01.\u0e22.
FormatData/th/MonthNarrows/9=\u0e15.\u0e04.
FormatData/th/MonthNarrows/10=\u0e1e.\u0e22.
FormatData/th/MonthNarrows/11=\u0e18.\u0e04.
FormatData/th/MonthNarrows/12=
FormatData/ar/MonthNarrows/0=\u064a
FormatData/ar/MonthNarrows/1=\u0641
FormatData/ar/MonthNarrows/2=\u0645
FormatData/ar/MonthNarrows/3=\u0623
FormatData/ar/MonthNarrows/4=\u0648
FormatData/ar/MonthNarrows/5=\u0646
FormatData/ar/MonthNarrows/6=\u0644
FormatData/ar/MonthNarrows/7=\u063a
FormatData/ar/MonthNarrows/8=\u0633
FormatData/ar/MonthNarrows/9=\u0643
FormatData/ar/MonthNarrows/10=\u0628
FormatData/ar/MonthNarrows/11=\u062f
FormatData/ar/MonthNarrows/12=
FormatData/ru/MonthNarrows/0=\u042f
FormatData/ru/MonthNarrows/1=\u0424
FormatData/ru/MonthNarrows/2=\u041c
FormatData/ru/MonthNarrows/3=\u0410
FormatData/ru/MonthNarrows/4=\u041c
FormatData/ru/MonthNarrows/5=\u0418
FormatData/ru/MonthNarrows/6=\u0418
FormatData/ru/MonthNarrows/7=\u0410
FormatData/ru/MonthNarrows/8=\u0421
FormatData/ru/MonthNarrows/9=\u041e
FormatData/ru/MonthNarrows/10=\u041d
FormatData/ru/MonthNarrows/11=\u0414
FormatData/ru/MonthNarrows/12=
FormatData/ms/MonthNarrows/0=J
FormatData/ms/MonthNarrows/1=F
FormatData/ms/MonthNarrows/2=M
FormatData/ms/MonthNarrows/3=A
FormatData/ms/MonthNarrows/4=M
FormatData/ms/MonthNarrows/5=J
FormatData/ms/MonthNarrows/6=J
FormatData/ms/MonthNarrows/7=O
FormatData/ms/MonthNarrows/8=S
FormatData/ms/MonthNarrows/9=O
FormatData/ms/MonthNarrows/10=N
FormatData/ms/MonthNarrows/11=D
FormatData/ms/MonthNarrows/12=
FormatData/nl/MonthNarrows/0=J
FormatData/nl/MonthNarrows/1=F
FormatData/nl/MonthNarrows/2=M
FormatData/nl/MonthNarrows/3=A
FormatData/nl/MonthNarrows/4=M
FormatData/nl/MonthNarrows/5=J
FormatData/nl/MonthNarrows/6=J
FormatData/nl/MonthNarrows/7=A
FormatData/nl/MonthNarrows/8=S
FormatData/nl/MonthNarrows/9=O
FormatData/nl/MonthNarrows/10=N
FormatData/nl/MonthNarrows/11=D
FormatData/nl/MonthNarrows/12=
FormatData/vi/MonthNarrows/0=1
FormatData/vi/MonthNarrows/1=2
FormatData/vi/MonthNarrows/2=3
FormatData/vi/MonthNarrows/3=4
FormatData/vi/MonthNarrows/4=5
FormatData/vi/MonthNarrows/5=6
FormatData/vi/MonthNarrows/6=7
FormatData/vi/MonthNarrows/7=8
FormatData/vi/MonthNarrows/8=9
FormatData/vi/MonthNarrows/9=10
FormatData/vi/MonthNarrows/10=11
FormatData/vi/MonthNarrows/11=12
FormatData/vi/MonthNarrows/12=
FormatData/sr/MonthNarrows/0=\u0458
FormatData/sr/MonthNarrows/1=\u0444
FormatData/sr/MonthNarrows/2=\u043c
FormatData/sr/MonthNarrows/3=\u0430
FormatData/sr/MonthNarrows/4=\u043c
FormatData/sr/MonthNarrows/5=\u0458
FormatData/sr/MonthNarrows/6=\u0458
FormatData/sr/MonthNarrows/7=\u0430
FormatData/sr/MonthNarrows/8=\u0441
FormatData/sr/MonthNarrows/9=\u043e
FormatData/sr/MonthNarrows/10=\u043d
FormatData/sr/MonthNarrows/11=\u0434
FormatData/sr/MonthNarrows/12=
FormatData/mt/MonthNarrows/0=J
FormatData/mt/MonthNarrows/1=F
FormatData/mt/MonthNarrows/2=M
FormatData/mt/MonthNarrows/3=A
FormatData/mt/MonthNarrows/4=M
FormatData/mt/MonthNarrows/5=\u0120
FormatData/mt/MonthNarrows/6=L
FormatData/mt/MonthNarrows/7=A
FormatData/mt/MonthNarrows/8=S
FormatData/mt/MonthNarrows/9=O
FormatData/mt/MonthNarrows/10=N
FormatData/mt/MonthNarrows/11=D
FormatData/mt/MonthNarrows/12=
FormatData/da/MonthNarrows/0=J
FormatData/da/MonthNarrows/1=F
FormatData/da/MonthNarrows/2=M
FormatData/da/MonthNarrows/3=A
FormatData/da/MonthNarrows/4=M
FormatData/da/MonthNarrows/5=J
FormatData/da/MonthNarrows/6=J
FormatData/da/MonthNarrows/7=A
FormatData/da/MonthNarrows/8=S
FormatData/da/MonthNarrows/9=O
FormatData/da/MonthNarrows/10=N
FormatData/da/MonthNarrows/11=D
FormatData/da/MonthNarrows/12=
FormatData/ro/MonthNarrows/0=I
FormatData/ro/MonthNarrows/1=F
FormatData/ro/MonthNarrows/2=M
FormatData/ro/MonthNarrows/3=A
FormatData/ro/MonthNarrows/4=M
FormatData/ro/MonthNarrows/5=I
FormatData/ro/MonthNarrows/6=I
FormatData/ro/MonthNarrows/7=A
FormatData/ro/MonthNarrows/8=S
FormatData/ro/MonthNarrows/9=O
FormatData/ro/MonthNarrows/10=N
FormatData/ro/MonthNarrows/11=D
FormatData/ro/MonthNarrows/12=
FormatData/no/MonthNarrows/0=J
FormatData/no/MonthNarrows/1=F
FormatData/no/MonthNarrows/2=M
FormatData/no/MonthNarrows/3=A
FormatData/no/MonthNarrows/4=M
FormatData/no/MonthNarrows/5=J
FormatData/no/MonthNarrows/6=J
FormatData/no/MonthNarrows/7=A
FormatData/no/MonthNarrows/8=S
FormatData/no/MonthNarrows/9=O
FormatData/no/MonthNarrows/10=N
FormatData/no/MonthNarrows/11=D
FormatData/no/MonthNarrows/12=
FormatData/pl/MonthNarrows/0=s
FormatData/pl/MonthNarrows/1=l
FormatData/pl/MonthNarrows/2=m
FormatData/pl/MonthNarrows/3=k
FormatData/pl/MonthNarrows/4=m
FormatData/pl/MonthNarrows/5=c
FormatData/pl/MonthNarrows/6=l
FormatData/pl/MonthNarrows/7=s
FormatData/pl/MonthNarrows/8=w
FormatData/pl/MonthNarrows/9=p
FormatData/pl/MonthNarrows/10=l
FormatData/pl/MonthNarrows/11=g
FormatData/pl/MonthNarrows/12=
FormatData/iw/MonthNarrows/0=1
FormatData/iw/MonthNarrows/1=2
FormatData/iw/MonthNarrows/2=3
FormatData/iw/MonthNarrows/3=4
FormatData/iw/MonthNarrows/4=5
FormatData/iw/MonthNarrows/5=6
FormatData/iw/MonthNarrows/6=7
FormatData/iw/MonthNarrows/7=8
FormatData/iw/MonthNarrows/8=9
FormatData/iw/MonthNarrows/9=10
FormatData/iw/MonthNarrows/10=11
FormatData/iw/MonthNarrows/11=12
FormatData/iw/MonthNarrows/12=
FormatData/zh/MonthNarrows/0=1
FormatData/zh/MonthNarrows/1=2
FormatData/zh/MonthNarrows/2=3
FormatData/zh/MonthNarrows/3=4
FormatData/zh/MonthNarrows/4=5
FormatData/zh/MonthNarrows/5=6
FormatData/zh/MonthNarrows/6=7
FormatData/zh/MonthNarrows/7=8
FormatData/zh/MonthNarrows/8=9
FormatData/zh/MonthNarrows/9=10
FormatData/zh/MonthNarrows/10=11
FormatData/zh/MonthNarrows/11=12
FormatData/zh/MonthNarrows/12=
test/sun/text/resources/LocaleDataTest.java
浏览文件 @
5606a2cd
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
* 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826
* 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826
* 8017142 8037343 8055222
* 8017142 8037343 8055222
8042126
* @summary Verify locale data
* @summary Verify locale data
*
*
*/
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录